[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf\ninsert_final_newline = true\n\n[*.gradle]\nindent_size = 4\nindent_style = space\n\n[*.yml]\nindent_size = 2\nindent_style = space\n\n[common/**.java]\nindent_size = 4\nindent_style = tab\nij_java_imports_layout = java.**,javax.**,|,net.minecraft.**,|,net.minecraftforge.**,|,*,|,logisticspipes.**,network.rs485.**\n\n[src/**.java]\nindent_size = 4\nindent_style = space\nij_java_imports_layout = java.**,javax.**,|,net.minecraft.**,|,net.minecraftforge.**,|,*,|,logisticspipes.**,network.rs485.**\n\n[*.{kt,kts}]\nindent_size = 4\nindent_style = space\nmax_line_length = 120\nktlint_code_style = official\nktlint_disabled_rules = no-wildcard-imports\nij_kotlin_name_count_to_use_star_import = 5\nij_kotlin_name_count_to_use_star_import_for_members = 3\nij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**,io.ktor.**\nij_kotlin_imports_layout = network.rs485.**,logisticspipes.**,*,net.minecraftforge.**,net.minecraft.**,java.**,javax.**,kotlin.**,kotlinx.**,^\nij_kotlin_allow_trailing_comma = true\nij_kotlin_allow_trailing_comma_on_call_site = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.bat text eol=crlf\n*.bdf binary\n*.jar filter=lfs diff=lfs merge=lfs -text\n"
  },
  {
    "path": ".gitignore",
    "content": "# IDEA project output path\n/classes\n/logs\n\n# IDEA run configurations\n.idea/runConfigurations\n\n# Created by https://www.gitignore.io/api/java,gradle,kotlin,forgegradle,intellij+iml\n# Edit at https://www.gitignore.io/?templates=java,gradle,kotlin,forgegradle,intellij+iml\n\n### ForgeGradle ###\n# Minecraft client/server files\nrun/*\nrun-server/*\nrun-server-test/*\n!run/.gitkeep\n!run-server/.gitkeep\n\n### Intellij+iml ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/**/usage.statistics.xml\n.idea/**/dictionaries\n.idea/**/shelf\n.idea/**/vcs.xml\n\n# Generated files\n.idea/**/contentModel.xml\n\n# Sensitive or high-churn files\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n.idea/**/dbnavigator.xml\n\n# Gradle\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# Gradle and Maven with auto-import\n# When using Gradle or Maven with auto-import, you should exclude module files,\n# since they will be recreated, and may cause churn.  Uncomment if using\n# auto-import.\n# .idea/artifacts\n.idea/compiler.xml\n.idea/jarRepositories.xml\n# .idea/modules.xml\n# .idea/*.iml\n# .idea/modules\n# *.iml\n# *.ipr\n\n# File-based project format\n*.iws\n\n# IntelliJ\nout/\n\n### Intellij+iml Patch ###\n# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023\n\n*.iml\nmodules.xml\n.idea/misc.xml\n*.ipr\n\n### Java ###\n# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\nreplay_pid*\n\n### Gradle ###\n.gradle\n**/build/\n!src/**/build/\n\n# Ignore Gradle GUI config\ngradle-app.setting\n\n# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)\n!gradle-wrapper.jar\n\n# Avoid ignore Gradle wrappper properties\n!gradle-wrapper.properties\n\n# Cache of project\n.gradletasknamecache\n\n# Eclipse Gradle plugin generated files\n# Eclipse Core\n.project\n# JDT-specific (Eclipse Java Development Tools)\n.classpath\n\n### Gradle Patch ###\n# Java heap dump\n*.hprof\n\n# End of https://www.gitignore.io/api/java,gradle,kotlin,forgegradle,intellij+iml\n"
  },
  {
    "path": ".idea/.name",
    "content": "LogisticsPipes"
  },
  {
    "path": ".idea/codeInsightSettings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"JavaProjectCodeInsightSettings\">\n    <excluded-names>\n      <name>scala</name>\n    </excluded-names>\n  </component>\n</project>"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <option name=\"LINE_SEPARATOR\" value=\"&#10;\" />\n    <option name=\"FORMATTER_TAGS_ENABLED\" value=\"true\" />\n    <JavaCodeStyleSettings>\n      <option name=\"LAYOUT_STATIC_IMPORTS_SEPARATELY\" value=\"false\" />\n      <option name=\"CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"999\" />\n      <option name=\"NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"999\" />\n      <option name=\"PACKAGES_TO_USE_IMPORT_ON_DEMAND\">\n        <value />\n      </option>\n      <option name=\"IMPORT_LAYOUT_TABLE\">\n        <value>\n          <package name=\"java\" withSubpackages=\"true\" static=\"false\" />\n          <package name=\"javax\" withSubpackages=\"true\" static=\"false\" />\n          <emptyLine />\n          <package name=\"net.minecraft\" withSubpackages=\"true\" static=\"false\" />\n          <emptyLine />\n          <package name=\"net.minecraftforge\" withSubpackages=\"true\" static=\"false\" />\n          <emptyLine />\n          <package name=\"\" withSubpackages=\"true\" static=\"false\" />\n          <emptyLine />\n          <package name=\"logisticspipes\" withSubpackages=\"true\" static=\"false\" />\n          <package name=\"network.rs485\" withSubpackages=\"true\" static=\"false\" />\n        </value>\n      </option>\n      <option name=\"JD_KEEP_EMPTY_LINES\" value=\"false\" />\n    </JavaCodeStyleSettings>\n    <JetCodeStyleSettings>\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </JetCodeStyleSettings>\n    <codeStyleSettings language=\"JAVA\">\n      <option name=\"KEEP_LINE_BREAKS\" value=\"false\" />\n      <option name=\"KEEP_FIRST_COLUMN_COMMENT\" value=\"false\" />\n      <option name=\"KEEP_BLANK_LINES_IN_DECLARATIONS\" value=\"1\" />\n      <option name=\"KEEP_BLANK_LINES_IN_CODE\" value=\"1\" />\n      <option name=\"KEEP_BLANK_LINES_BEFORE_RBRACE\" value=\"1\" />\n      <option name=\"BLANK_LINES_AFTER_CLASS_HEADER\" value=\"1\" />\n      <option name=\"BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER\" value=\"1\" />\n      <option name=\"ALIGN_MULTILINE_PARAMETERS\" value=\"false\" />\n      <option name=\"ALIGN_MULTILINE_RESOURCES\" value=\"false\" />\n      <option name=\"SPACE_WITHIN_ARRAY_INITIALIZER_BRACES\" value=\"true\" />\n      <option name=\"SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE\" value=\"true\" />\n      <option name=\"CALL_PARAMETERS_WRAP\" value=\"1\" />\n      <option name=\"METHOD_PARAMETERS_WRAP\" value=\"1\" />\n      <option name=\"RESOURCE_LIST_WRAP\" value=\"5\" />\n      <option name=\"EXTENDS_LIST_WRAP\" value=\"1\" />\n      <option name=\"THROWS_LIST_WRAP\" value=\"1\" />\n      <option name=\"EXTENDS_KEYWORD_WRAP\" value=\"1\" />\n      <option name=\"THROWS_KEYWORD_WRAP\" value=\"1\" />\n      <option name=\"METHOD_CALL_CHAIN_WRAP\" value=\"1\" />\n      <option name=\"BINARY_OPERATION_WRAP\" value=\"1\" />\n      <option name=\"BINARY_OPERATION_SIGN_ON_NEXT_LINE\" value=\"true\" />\n      <option name=\"TERNARY_OPERATION_WRAP\" value=\"5\" />\n      <option name=\"KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE\" value=\"true\" />\n      <option name=\"KEEP_SIMPLE_CLASSES_IN_ONE_LINE\" value=\"true\" />\n      <option name=\"ARRAY_INITIALIZER_WRAP\" value=\"1\" />\n      <option name=\"VARIABLE_ANNOTATION_WRAP\" value=\"2\" />\n      <indentOptions>\n        <option name=\"USE_TAB_CHARACTER\" value=\"true\" />\n      </indentOptions>\n    </codeStyleSettings>\n    <codeStyleSettings language=\"Markdown\">\n      <option name=\"SOFT_MARGINS\" value=\"80\" />\n    </codeStyleSettings>\n    <codeStyleSettings language=\"kotlin\">\n      <option name=\"CALL_PARAMETERS_WRAP\" value=\"5\" />\n      <option name=\"CALL_PARAMETERS_LPAREN_ON_NEXT_LINE\" value=\"true\" />\n      <option name=\"CALL_PARAMETERS_RPAREN_ON_NEXT_LINE\" value=\"true\" />\n      <option name=\"METHOD_PARAMETERS_WRAP\" value=\"5\" />\n      <option name=\"METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE\" value=\"true\" />\n      <option name=\"METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE\" value=\"true\" />\n      <option name=\"EXTENDS_LIST_WRAP\" value=\"1\" />\n      <option name=\"METHOD_CALL_CHAIN_WRAP\" value=\"1\" />\n      <option name=\"ASSIGNMENT_WRAP\" value=\"1\" />\n    </codeStyleSettings>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"PREFERRED_PROJECT_CODE_STYLE\" value=\"LP Format\" />\n  </state>\n</component>"
  },
  {
    "path": ".idea/copyright/RS485_Dual_MIT_MMPL.xml",
    "content": "<component name=\"CopyrightManager\">\n  <copyright>\n    <option name=\"keyword\" value=\"This MIT license was reworded to only match this file.\" />\n    <option name=\"notice\" value=\"Copyright (c) &amp;#36;today.year  RS485&#10;&#10;&quot;LogisticsPipes&quot; is distributed under the terms of the Minecraft Mod Public&#10;License 1.0.1, or MMPL. Please check the contents of the license located in&#10;https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md&#10;&#10;This file can instead be distributed under the license terms of the&#10;MIT license:&#10;&#10;Copyright (c) &amp;#36;today.year  RS485&#10;&#10;This MIT license was reworded to only match this file. If you use the regular&#10;MIT license in your project, replace this copyright notice (this line and any&#10;lines below and NOT the copyright line above) with the lines from the original&#10;MIT license located here: http://opensource.org/licenses/MIT&#10;&#10;Permission is hereby granted, free of charge, to any person obtaining a copy of&#10;this file and associated documentation files (the &quot;Source Code&quot;), to deal in&#10;the Source Code without restriction, including without limitation the rights to&#10;use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies&#10;of the Source Code, and to permit persons to whom the Source Code is furnished&#10;to do so, subject to the following conditions:&#10;&#10;The above copyright notice and this permission notice shall be included in all&#10;copies or substantial portions of the Source Code, which also can be&#10;distributed under the MIT.&#10;&#10;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#10;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#10;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#10;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#10;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#10;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE&#10;SOFTWARE.\" />\n    <option name=\"myName\" value=\"RS485 Dual MIT MMPL\" />\n  </copyright>\n</component>"
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "content": "<component name=\"CopyrightManager\">\n  <settings>\n    <module2copyright>\n      <element module=\"network.rs485 package\" copyright=\"RS485 Dual MIT MMPL\" />\n    </module2copyright>\n  </settings>\n</component>"
  },
  {
    "path": ".idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\" addBOMForNewFiles=\"with NO BOM\" />\n</project>"
  },
  {
    "path": ".idea/externalAnnotations/net/minecraft/block/state/annotations.xml",
    "content": "<root>\n    <item name='net.minecraft.block.state.IBlockProperties net.minecraft.util.math.RayTraceResult collisionRayTrace(net.minecraft.world.World, net.minecraft.util.math.BlockPos, net.minecraft.util.math.Vec3d, net.minecraft.util.math.Vec3d)'>\n        <annotation name='javax.annotation.Nullable'/>\n    </item>\n</root>\n"
  },
  {
    "path": ".idea/externalAnnotations/net/minecraft/client/gui/inventory/annotations.xml",
    "content": "<root>\n    <item name='net.minecraft.client.gui.inventory.GuiContainer void handleMouseClick(net.minecraft.inventory.Slot, int, int, net.minecraft.inventory.ClickType) 0'>\n        <annotation name='javax.annotation.Nullable'/>\n    </item>\n</root>\n"
  },
  {
    "path": ".idea/externalAnnotations/net/minecraft/item/annotations.xml",
    "content": "<root>\n    <item name='net.minecraft.item.Item net.minecraft.item.ItemStack onItemUseFinish(net.minecraft.item.ItemStack, net.minecraft.world.World, net.minecraft.entity.EntityLivingBase) 1'>\n        <annotation name='javax.annotation.Nullable'/>\n    </item>\n    <item name='net.minecraft.item.Item net.minecraft.util.ActionResult&lt;net.minecraft.item.ItemStack&gt; onItemRightClick(net.minecraft.world.World, net.minecraft.entity.player.EntityPlayer, net.minecraft.util.EnumHand) 0'>\n        <annotation name='javax.annotation.Nullable'/>\n    </item>\n    <item name='net.minecraft.item.Item net.minecraft.util.EnumActionResult onItemUse(net.minecraft.entity.player.EntityPlayer, net.minecraft.world.World, net.minecraft.util.math.BlockPos, net.minecraft.util.EnumHand, net.minecraft.util.EnumFacing, float, float, float) 1'>\n        <annotation name='javax.annotation.Nullable'/>\n    </item>\n</root>"
  },
  {
    "path": ".idea/externalAnnotations/net/minecraft/world/annotations.xml",
    "content": "<root>\n    <item name='net.minecraft.world.IWorldNameable net.minecraft.util.text.ITextComponent getDisplayName()'>\n        <annotation name='javax.annotation.Nullable'/>\n    </item>\n</root>"
  },
  {
    "path": ".idea/inspectionProfiles/Project_Default.xml",
    "content": "<component name=\"InspectionProjectProfileManager\">\n  <profile version=\"1.0\">\n    <option name=\"myName\" value=\"Project Default\" />\n    <inspection_tool class=\"WeakerAccess\" enabled=\"false\" level=\"WARNING\" enabled_by_default=\"false\">\n      <option name=\"SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS\" value=\"true\" />\n      <option name=\"SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES\" value=\"true\" />\n      <option name=\"SUGGEST_PRIVATE_FOR_INNERS\" value=\"false\" />\n    </inspection_tool>\n  </profile>\n</component>"
  },
  {
    "path": ".idea/kotlinc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"KotlinJpsPluginSettings\">\n    <option name=\"version\" value=\"1.7.10\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/libraries-with-intellij-classes.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"libraries-with-intellij-classes\">\n    <option name=\"intellijApiContainingLibraries\">\n      <list>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIU\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.idea\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIU\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIC\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.idea\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"ideaIC\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPY\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.pycharm\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPY\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPC\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.pycharm\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"pycharmPC\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"clion\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.clion\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"clion\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"riderRD\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.rider\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"riderRD\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"goland\" />\n          <option name=\"groupId\" value=\"com.jetbrains.intellij.goland\" />\n        </LibraryCoordinatesState>\n        <LibraryCoordinatesState>\n          <option name=\"artifactId\" value=\"goland\" />\n          <option name=\"groupId\" value=\"com.jetbrains\" />\n        </LibraryCoordinatesState>\n      </list>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/scopes/network_rs485_package.xml",
    "content": "<component name=\"DependencyValidationManager\">\n  <scope name=\"network.rs485 package\" pattern=\"network.rs485..*\" />\n</component>"
  },
  {
    "path": ".travis.yml",
    "content": "language: java\njobs:\n  include:\n    - stage: build\n      name: \"Build and install\"\n      script: ./gradlew install -xtest\n    - stage: test\n      name: \"Unit tests\"\n      script: ./gradlew check\n    - stage: test\n      name: \"Integration tests\"\n      script: ./gradlew -P acceptMinecraftServerEula=true integrationTests\njdk:\n  - openjdk8\nbefore_cache:\n  - rm -f  $HOME/.gradle/caches/modules-2/modules-2.lock\n  - rm -fr $HOME/.gradle/caches/*/plugin-resolution/\ncache:\n  directories:\n    - build/fg_cache\n    - $HOME/.gradle/caches/\n    - $HOME/.gradle/wrapper/\n"
  },
  {
    "path": "BUILDING.md",
    "content": "# Building Logistics Pipes\n\nIf you are familiar with Minecraft Forge and Gradle or you are a Java developer\nyou should not have many problems starting with Logistics Pipes and your IDE.\nBut we have some required steps that you need to follow to make things work.\n\n\n## Prerequisites\n\n1. Having [git](http://git-scm.com/) and git-lfs installed\n2. Having an IDE (we do use [IntelliJ IDEA](https://www.jetbrains.com/idea/))\n3. Having Java Development Kit 8; newer versions are not supported by this\n   Minecraft or Minecraft Forge version.\n4. Matrix/Discord wouldn't be bad if you want to communicate with other\n   contributors and us.\n\n\n## Matrix\n\n[Logistics Pipes Space](https://matrix.to/#/#logisticspipes+space:rs485.network)\n\n- [Dev Channel](https://matrix.to/#/#logisticspipes+dev:rs485.network)\n\nThe channels are all linked to Discord and some even to IRC.\n\n\n## How to set up a local development environment\n\n### git\n\nFirst off you need to clone Logistics Pipes from GitHub of course. If you only\nwant to browse the source, you can clone the official repository. But it is best\npractice to actually fork the repository and clone your own copy.\n\nThe git command line is `git clone https://github.com/RS485/LogisticsPipes.git`\nwhere you can replace *RS485* by your own user name, **if** you forked the\nrepository.\n\n\n### git-lfs\n\nIf you didn't have git-lfs installed at the time of cloning the git repository,\njar files are \"broken\", because lfs did not download and replace them.\nYou can manually run the following commands to fix the situation peacefully:\n\n```shell\n$ git lfs install\n$ git lfs fetch\n$ git lfs checkout\n```\n\n\n### Gradle\n\nMake sure you are running Gradle with Java 8: You can check the default\njava version with `java -version` and control the version Gradle uses with\nthe `JAVA_HOME` environment variable. LP can be built with `./gradlew build`\nand the output found in the directory `build/libs`.\nIf the task fails there may be something wrong with maven repositories or\n[a Java update broke ForgeGradle 2](https://github.com/MinecraftForge/ForgeGradle/issues/652)\nor something may be wrong with your setup. You may definitely ask for help on\nthe mentioned communication channels above, but please be sure to state your\nissue as good as possible and be nice to others.\n\n### IDEA Quirks\n\nFor IDEA to use the correct Java SDK, you might have to select the correct\nJDK (Java JDK 8, OpenJDK build preferred) in `File > Project Structure` in the\nproject part of the project settings under SDK.\n\n### Running Minecraft from your dev environment\n\nAfter you successfully built LP you can probably run Minecraft directly from\nyour IDE after running the correct ForgeGradle generate run configuration task.\nPlease look at ForgeGradle documentation for more information.\n\nIf you are not using IntelliJ IDEA, there may be a ton of missing texture\nerrors and missing language files. The cause is newer ForgeGradle versions.\nOur ForgeGradle version and our build script contain fixes for IntelliJ IDEA\nonly; sorry if you are not using IDEA. The solution is to remove\n`build/classes/*/*` and `build/resources/*` from the run configuration\nclasspath and add the custom `build/run_classes` path to the classpath.\nWe are open for any contributions for a better solution or wider support.\n\nThe workaround is to copy your `build/resources/main/*` into \n`build/classes/java/main` before launching the game, or you may link those two\n together (Linux or WSL):\n\n```shell\n$ rm -r build/resources/main && ln -s ../classes/java/main build/resources/main\n```\n\nWindows `cmd`:\n\n```\nrd /s /q \"build\\\\resources\\\\main\" && mklink /D \"build\\\\resources\\\\main\" \"..\\\\classes\\\\java\\\\main\"\n```\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Minecraft Mod Public License\n============================\n\nVersion 1.0.1\n\n0. Definitions\n--------------\n\nMinecraft: Denotes a copy of the Minecraft game licensed by Mojang AB\n\nUser: Anybody that interacts with the software in one of the following ways:\n   - play\n   - decompile\n   - recompile or compile\n   - modify\n   - distribute\n\nMod: The mod code designated by the present license, in source form, binary\nform, as obtained standalone, as part of a wider distribution or resulting from\nthe compilation of the original or modified sources.\n\nDependency: Code required for the mod to work properly. This includes \ndependencies required to compile the code as well as any file or modification\nthat is explicitely or implicitely required for the mod to be working.\n\n1. Scope\n--------\n\nThe present license is granted to any user of the mod. As a prerequisite, \na user must own a legally acquired copy of Minecraft\n\n2. Liability\n------------\n\nThis mod is provided 'as is' with no warranties, implied or otherwise. The owner\nof this mod takes no responsibility for any damages incurred from the use of\nthis mod. This mod alters fundamental parts of the Minecraft game, parts of\nMinecraft may not work with this mod installed. All damages caused from the use\nor misuse of this mad fall on the user.\n\n3. Play rights\n--------------\n\nThe user is allowed to install this mod on a client or a server and to play \nwithout restriction.\n\n4. Modification rights\n----------------------\n\nThe user has the right to decompile the source code, look at either the \ndecompiled version or the original source code, and to modify it.\n\n5. Derivation rights\n--------------------\n\nThe user has the rights to derive code from this mod, that is to say to\nwrite code that extends or instanciate the mod classes or interfaces, refer to\nits objects, or calls its functions. This code is known as \"derived\" code, and \ncan be licensed under a license different from this mod.\n\n6. Distribution of original or modified copy rights\n---------------------------------------------------\n\nIs subject to distribution rights this entire mod in its various forms. This\ninclude:\n   - original binary or source forms of this mod files\n   - modified versions of these binaries or source files, as well as binaries\n     resulting from source modifications\n   - patch to its source or binary files\n   - any copy of a portion of its binary source files\n\nThe user is allowed to redistribute this mod partially, in totality, or \nincluded in a distribution.\n\nWhen distributing binary files, the user must provide means to obtain its \nentire set of sources or modified sources at no costs.\n\nAll distributions of this mod must remain licensed under the MMPL.\n\nAll dependencies that this mod have on other mods or classes must be licensed\nunder conditions comparable to this version of MMPL, with the exception of the\nMinecraft code and the mod loading framework (e.g. ModLoader, ModLoaderMP or\nBukkit).\n\nModified version of binaries and sources, as well as files containing sections\ncopied from this mod, should be distributed under the terms of the present\nlicense.\n"
  },
  {
    "path": "README.md",
    "content": "# LogisticsPipes\n\n[![Jenkins](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fci.rs485.network%2Fview%2Fall%2Fjob%2FLogisticsPipes-0.10-mc112)](https://ci.rs485.network/)\n![Lines of Code](https://tokei.rs/b1/github/RS485/LogisticsPipes?category=code)\n\nLogistics Pipes is an extensive overhaul of the Buildcraft pipe system. It allows for better distribution of items via pipes, more organised stockkeeping and easier automated crafting.\n\nGo to the [CurseForge Page](https://www.curseforge.com/minecraft/mc-mods/logistics-pipes) for more information and recent downloads.\nWe advise anyone who is not a developer to go there.\n\nYou are free to use this mod in your modpack without asking or noticing us.\n\nIf you want to understand the sheer amount of changes we have made to the source, you can use [Gource](http://gource.io/)\n\nCredits for the code goes to all [contributors](https://github.com/RS485/LogisticsPipes/contributors).\nCredits for the idea and basic code goes to Krapht.\n\n## Translate\n\nSee [this repo](https://github.com/RS485/LogisticsPipes-Language) for translations.\n\n## Builds\n\nSee our [Jenkins](https://ci.rs485.network/).\n\nOur jar certificate fingerprint is `e0c86912b2f7cc0cc646ad57799574aea43dbd45`.\n\nOur GPG key id is `C4E5 0DBF CE49 AC33 E052  B591 2669 A04F D19F 2F7A` and we sign our jars with the subkey `386B 2790 B001 3BF8 1ED2  2D81 0119 F8E9 56C4 E048`.\n\n## Contact\n\nGet in touch with us on [Matrix](https://matrix.to/#/#lp:rs485.network) or the [RS485 Discord](https://discord.gg/6vPP3A8)\n"
  },
  {
    "path": "build.gradle",
    "content": "buildscript {\n    repositories {\n        mavenCentral()\n        maven {\n            url = \"https://maven.removeco.de/\"\n        }\n    }\n    dependencies {\n        classpath group: 'network.rs485.forge', name: 'ForgeGradle', version: forgegradle_version\n    }\n}\n\nplugins {\n    id 'java'\n    id 'maven-publish'\n    id 'org.jetbrains.kotlin.jvm' version \"$kotlin_version\"\n    id 'org.jetbrains.kotlin.plugin.serialization' version \"$kotlin_version\"\n    id 'org.jetbrains.kotlin.plugin.lombok' version \"$kotlin_version\"\n    id 'io.freefair.lombok' version \"$lombok_plugin_version\"\n    id 'signing'\n    id 'com.matthewprenger.cursegradle' version \"$cursegradle_version\"\n    id 'com.github.johnrengelman.shadow' version \"$shadow_version\"\n}\napply plugin: 'network.rs485.forge'\n\narchivesBaseName = \"logisticspipes\"\ngroup = \"network.rs485\"\nversion = \"0.10.4\"\next.vendor = \"unknown\"\next.target = \"Forge $forge_version\"\n\njava.toolchain.languageVersion = JavaLanguageVersion.of(8)\n\nprintln \"Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}\"\n\ndef ENV = System.getenv()\n\nif (ENV.BUILD_NUMBER) {\n    version = \"$version.${ENV.BUILD_NUMBER}\"\n} else if (ENV.VERSION) {\n    version = \"$version.${ENV.VERSION}\"\n} else {\n    version = \"$version-SNAPSHOT\"\n}\n\nif (ENV.JENKINS_URL) {\n    ext.vendor = ENV.JENKINS_URL\n} else if (ENV.JITPACK) {\n    ext.vendor = \"JitPack.io\"\n    group = ENV.GROUP\n}\n\next.sharedManifest = manifest {\n    attributes(\n            'FMLCorePlugin': 'logisticspipes.asm.LogisticsPipesCoreLoader',\n            'FMLCorePluginContainsFMLMod': 'true',\n            'FMLAT': 'lp_at.cfg',\n            'Specification-Title': 'LogisticsPipes',\n            'Specification-Vendor': 'RS485',\n            'Specification-Version': '1',\n            'Implementation-Vendor': \"$vendor\",\n            'Implementation-Title': \"${project.name}\",\n            'Implementation-Version': \"$version\",\n            'Implementation-Target': \"$target\",\n            'Implementation-Timestamp': new Date().format(\"yyyy-MM-dd'T'HH:mm:ssZ\"))\n}\n\nsourceSets {\n    api {\n        java {\n            srcDirs = ['src/api/java']\n        }\n    }\n    dummy {\n        java {\n            srcDirs = ['dummy/src/main/java']\n        }\n    }\n    main {\n        compileClasspath += dummy.output\n        compileClasspath += api.output\n        runtimeClasspath += api.output\n\n        java {\n            srcDirs += 'common'\n        }\n        resources {\n            srcDirs += 'resources'\n        }\n    }\n    test {\n        compileClasspath += dummy.output\n        compileClasspath += api.output\n        runtimeClasspath += api.output\n    }\n}\n\nconfigurations {\n    testCompileOnly.extendsFrom compileOnly\n    ktlint\n}\n\ntasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {\n    kotlinOptions {\n        languageVersion = \"1.7\"\n        jvmTarget = JavaVersion.VERSION_1_8\n        freeCompilerArgs += \"-Xjvm-default=all\"\n    }\n}\n\nkotlinLombok {\n    lombokConfigurationFile file(\"lombok.config\")\n}\n\nproject.afterEvaluate {\n    tasks.register('copyRunClasses', Copy.class) {\n        dependsOn ['classes']\n        from sourceSets.main.output.classesDirs, sourceSets.main.output.resourcesDir, sourceSets.api.output.classesDirs\n        into \"${project.buildDir}/run_classes/\"\n        duplicatesStrategy = DuplicatesStrategy.EXCLUDE\n\n        includeEmptyDirs false\n    }\n\n    tasks['prepareRuns'].dependsOn('copyRunClasses')\n}\n\nminecraft {\n    mappings channel: 'snapshot', version: \"$mappings_version\"\n    accessTransformer = file(\"$rootDir/resources/META-INF/lp_at.cfg\")\n\n    runs {\n        client {\n            workingDirectory project.file('run')\n\n            // Recommended logging data for a userdev environment\n            property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'\n\n            // Recommended logging level for the console\n            property 'forge.logging.console.level', 'debug'\n\n            // load LP core mod from classpath\n            property 'fml.coreMods.load', 'logisticspipes.asm.LogisticsPipesCoreLoader'\n\n            jvmArgs '-ea'\n            environment 'MC_VERSION', mcversion\n\n            lazyToken 'classpathExclude', {\n                def paths = [\n                    sourceSets.main.output.resourcesDir.toPath().toString(),\n                    sourceSets.api.output.resourcesDir.toPath().toString(),\n                ]\n                for (final def file in sourceSets.main.output.classesDirs.getFiles()) {\n                    paths.add(file.toPath().toString())\n                }\n                for (final def file in sourceSets.api.output.classesDirs.getFiles()) {\n                    paths.add(file.toPath().toString())\n                }\n                String.join(File.pathSeparator, paths)\n            }\n            lazyToken 'classpathInclude', {\n                def paths = [project.buildDir.toPath().resolve(\"run_classes\").toString()]\n                String.join(File.pathSeparator, paths)\n            }\n\n            mods {\n                logisticspipes {\n                    sources = [sourceSets.api, sourceSets.main]\n                }\n            }\n        }\n\n        server {\n            workingDirectory project.file('run-server')\n\n            // Recommended logging data for a userdev environment\n            property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'\n\n            // Recommended logging level for the console\n            property 'forge.logging.console.level', 'debug'\n\n            // load LP core mod from classpath\n            property 'fml.coreMods.load', 'logisticspipes.asm.LogisticsPipesCoreLoader'\n\n            jvmArgs '-ea'\n            environment 'MC_VERSION', mcversion\n\n            lazyToken 'classpathExclude', {\n                def paths = [\n                        sourceSets.main.output.classesDirs.asPath,\n                        sourceSets.api.output.classesDirs.asPath,\n                        sourceSets.main.output.resourcesDir.path,\n                        sourceSets.api.output.resourcesDir.path,\n                ]\n                String.join(File.pathSeparator, paths)\n            }\n            lazyToken 'classpathInclude', {\n                def paths = [\"${project.buildDir}/run_classes/\"]\n                String.join(File.pathSeparator, paths)\n            }\n\n            mods {\n                logisticspipes {\n                    sources = [sourceSets.api, sourceSets.main]\n                }\n            }\n        }\n\n        serverTest {\n            environment 'target', 'server'\n            // mimic the runServer task\n            environment 'mainClass', 'net.minecraft.launchwrapper.Launch'\n            environment 'MCP_TO_SRG', \"$buildDir/createSrgToMcp/output.srg\"\n            environment 'MC_VERSION', mcversion\n            main 'net.minecraftforge.legacydev.MainServer'\n            args '--tweakClass', 'net.minecraftforge.fml.common.launcher.FMLServerTweaker'\n            arg 'nogui' // without GUI\n            jvmArg '-ea'\n            workingDirectory project.file('run-server-test')\n\n            // load LP core mod from classpath\n            property 'fml.coreMods.load', 'logisticspipes.asm.LogisticsPipesCoreLoader'\n\n            // put LP in test mode\n            property 'logisticspipes.test', 'true'\n            property 'logisticspipes.test.debug', 'false' // set this to true in the generated run configuration\n\n            lazyToken 'classpathExclude', {\n                def paths = [\n                    sourceSets.main.output.classesDirs.asPath,\n                    sourceSets.api.output.classesDirs.asPath,\n                    sourceSets.main.output.resourcesDir.path,\n                    sourceSets.api.output.resourcesDir.path,\n                ]\n                String.join(File.pathSeparator, paths)\n            }\n            lazyToken 'classpathInclude', {\n                def paths = [\n                    \"${project.buildDir}/run_classes/\",\n                    sourceSets.test.output.classesDirs.asPath,\n                    sourceSets.test.output.resourcesDir.path,\n                ]\n                // sorry for the mess in the run configuration's classpath,\n                // but using the test classpath included the dependencies from the provided scope\n                for (final def file in configurations.testRuntimeClasspath.resolvedConfiguration.files) {\n                    paths.add(file.toPath().toString())\n                }\n                String.join(File.pathSeparator, paths)\n            }\n\n            mods {\n                logisticspipes {\n                    sources = [sourceSets.api, sourceSets.main, sourceSets.test]\n                }\n            }\n        }\n    }\n}\n\njar {\n    from sourceSets.api.output\n    finalizedBy 'shadowJar'\n    duplicatesStrategy = DuplicatesStrategy.WARN\n\n    manifest = project.manifest {\n        from sharedManifest\n    }\n}\n\nshadowJar {\n    from sourceSets.api.output\n    finalizedBy 'reobfJar'\n\n    archiveClassifier.set('')\n\n    dependencies {\n        include(dependency(group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_version))\n        include(dependency(group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlin_version))\n        include(dependency(group: 'org.jetbrains', name: 'annotations', version: kannotations_version))\n        include(dependency(group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core-jvm', version: kcoroutines_version))\n        include(dependency(group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-jdk8', version: kcoroutines_version))\n        include(dependency(group: 'org.jetbrains.kotlinx', name: 'kotlinx-serialization-json-jvm', version: kserialization_version))\n        include(dependency(group: 'org.jetbrains.kotlinx', name: 'kotlinx-serialization-core-jvm', version: kserialization_version))\n        include(dependency(group: 'com.charleskorn.kaml', name: 'kaml-jvm', version: kaml_version))\n        include(dependency(group: 'org.snakeyaml', name: 'snakeyaml-engine', version: '2.3'))\n    }\n\n    relocate 'kotlin', 'logisticspipes.kotlin'\n    relocate 'kotlinx', 'logisticspipes.kotlinx'\n    relocate 'org.intellij', 'logisticspipes.intellij'\n    relocate 'org.jetbrains', 'logisticspipes.jetbrains'\n    relocate 'org.snakeyaml', 'logisticspipes.snakeyaml'\n    relocate 'com.charleskorn.kaml', 'logisticspipes.kaml'\n\n    exclude 'META-INF/versions/9/*'\n    exclude 'DebugProbesKt.bin'\n\n    manifest {\n        inheritFrom sharedManifest\n    }\n}\n\ntask sourceJar(type: Jar) {\n    from sourceSets.api.allSource\n    from sourceSets.main.allSource\n    archiveClassifier.set('sources')\n}\n\ntest {\n    reports {\n        html.required.set(true)\n    }\n}\n\nprocessResources {\n    // this will ensure that this task is redone when the versions change.\n    inputs.property \"version\", project.version\n\n    duplicatesStrategy = DuplicatesStrategy.FAIL\n\n    // replace stuff in mcmod.info, nothing else\n    from(project.file('resources_raw')) {\n        include 'mcmod.info'\n\n        // replace version and mcversion\n        expand 'version': project.version, 'mcversion': mcversion\n    }\n}\n\nrepositories {\n    mavenCentral()\n    maven {\n        url = \"https://maven.removeco.de/\"\n    }\n}\n\ndependencies {\n    minecraft group: 'net.minecraftforge', name: 'forge', version: forge_version\n    apiImplementation group: 'net.minecraftforge', name: 'forge', version: forge_version\n    dummyImplementation group: 'net.minecraftforge', name: 'forge', version: forge_version\n\n    implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_version\n    implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8', version: kotlin_version\n    implementation group: 'org.jetbrains', name: 'annotations', version: kannotations_version\n    implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: kcoroutines_version\n    implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-jdk8', version: kcoroutines_version\n    implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-serialization-json', version: kserialization_version\n    implementation group: 'com.charleskorn.kaml', name: 'kaml', version: kaml_version\n    implementation group: 'network.rs485', name: 'CodeChickenLib', version: '3.3.0.9', classifier: 'deobf'\n\n    compileOnly group: 'mcjty.theoneprobe', name: 'TheOneProbe-1.12', version: '1.12-1.4.28-17', classifier: 'api'\n    compileOnly group: 'mezz.jei', name: 'jei_1.12.2', version: '4.15.0.293'\n    compileOnly group: 'MCMultiPart2', name: 'MCMultiPart', version: '2.5.4', classifier: 'deobf'\n    compileOnly group: 'com.mod-buildcraft', name: 'buildcraft-all', version: '7.99.24.6', transitive: false\n    compileOnly group: 'net.industrial-craft', name: 'industrialcraft-2', version: '2.8.170-ex112', classifier: 'api'\n    compileOnly group: 'codechicken', name: 'NotEnoughItems', version: '1.12.2-2.4.3.245', classifier: 'deobf', transitive: false\n    compileOnly group: 'codechicken', name: 'EnderStorage', version: '1.12.2-2.4.6.137', classifier: 'deobf', transitive: false\n    compileOnly group: 'li.cil.oc', name: 'OpenComputers', version: 'MC1.12.2-1.7.5.205', classifier: 'api'\n    compileOnly files('lib/appliedenergistics2-rv6-stable-7-api.jar')\n    compileOnly group: 'cofh', name: 'CoFHCore', version: '1.12.2-4.6.3.27', classifier: 'deobf', transitive: false\n    compileOnly group: 'cofh', name: 'RedstoneFlux', version: '1.12-2.1.0.7', classifier: 'deobf', transitive: false\n    compileOnly group: 'cofh', name: 'CoFHWorld', version: '1.12.2-1.2.0.5', classifier: 'deobf', transitive: false\n    compileOnly group: 'cofh', name: 'ThermalDynamics', version: '1.12.2-2.5.5.21', classifier: 'deobf', transitive: false\n    compileOnly group: 'cofh', name: 'ThermalFoundation', version: '1.12.2-2.6.3.27', classifier: 'deobf', transitive: false\n    compileOnly group: 'cofh', name: 'ThermalExpansion', version: '1.12.2-5.5.4.43', classifier: 'deobf', transitive: false\n    compileOnly group: 'org.squiddev', name: 'cc-tweaked-1.12.2', version: '1.89.2', transitive: false\n    compileOnly group: 'com.jaquadro.minecraft.storagedrawers', name: 'StorageDrawers', version: '1.12.2-5.4.2', transitive: false\n    compileOnly group: 'pl.asie.charset', name: 'Charset', version: '0.5.6.6', classifier: 'api', transitive: false\n\n    ktlint(\"com.pinterest:ktlint:0.47.1\") {\n        attributes {\n            attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))\n        }\n    }\n\n    testImplementation 'org.jetbrains.kotlin:kotlin-test'\n    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'\n    testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'\n}\n\n\nimport net.minecraftforge.gradle.userdev.MinecraftUserRepo\n\nimport java.nio.file.Files\n\nfinal nonMinecraftConfigurations = configurations.findAll { conf -> conf != configurations.minecraft }\nif (!nonMinecraftConfigurations.empty) {\n    final fgextension = project.getExtensions().findByName(\"minecraft\")\n    final mcrepo = new MinecraftUserRepo(\n        /* project = */ project,\n        /* group = */ 'net.minecraftforge',\n        /* name = */ 'forge',\n        /* version = */ \"$forge_version\",\n        /* ats = */ fgextension.getAccessTransformers().getFrom().toList(),\n        /* mapping = */ fgextension.getMappings().get(),\n    )\n    nonMinecraftConfigurations.each {\n        it.resolutionStrategy.dependencySubstitution {\n            substitute module('net.minecraftforge:forge') using module(mcrepo.getDependencyString())\n        }\n    }\n}\n\ntask ktlint(type: JavaExec, group: \"verification\") {\n    description = \"Check Kotlin code style.\"\n    classpath = configurations.ktlint\n    mainClass.set(\"com.pinterest.ktlint.Main\")\n    args \"**/*.kt\"\n}\n//check.dependsOn ktlint // not enforced, ktlint is in trial mode\n\nclean {\n    // this folder is created by dependency resolution and will be created before 'clean' runs,\n    // resulting in missing minecraft sources etc. Set here: https://fckaf.de/voZ\n    setDelete(project.fileTree(\"$buildDir\") {\n        exclude 'fg_cache'\n    })\n}\n\ntasks.withType(Test) {\n    useJUnitPlatform()\n    testLogging {\n        events(\"passed\", \"skipped\", \"failed\")\n    }\n}\n\ntask deobfJar(type: Jar) {\n    from sourceSets.main.output\n    from sourceSets.api.output\n    archiveClassifier.set('deobf')\n    duplicatesStrategy = DuplicatesStrategy.WARN\n\n    manifest = project.manifest {\n        from sharedManifest\n    }\n}\n\ntask apiJar(type: Jar, dependsOn: apiClasses) {\n    from sourceSets.api.output\n    from sourceSets.api.allSource\n    archiveClassifier.set('api')\n    duplicatesStrategy = DuplicatesStrategy.WARN\n}\n\ncurseforge {\n    apiKey = project.hasProperty('LogisticsPipes.curseForgeApiKey') ? project.findProperty(\"LogisticsPipes.curseForgeApiKey\") : '0'\n    project {\n        id = \"232838\"\n        changelog = project.hasProperty('changelog') ? project.findProperty('changelog') : ''\n        releaseType = 'beta'\n        relations {\n            requiredDependency 'codechicken-lib-1-8'\n        }\n\n        mainArtifact(shadowJar) {\n            displayName = \"Logistics Pipes $project.version\"\n        }\n    }\n}\n\nartifacts {\n    archives apiJar\n    archives shadowJar\n    archives deobfJar\n    archives sourceJar\n}\n\ntask enableSigningTasks {\n    doFirst {\n        tasks.withType(Sign) {\n            enabled = true\n        }\n    }\n}\n\nsigning {\n    useGpgCmd()\n    sign apiJar\n    sign shadowJar\n    sign deobfJar\n    sign sourceJar\n}\n\ntask sign {\n    dependsOn enableSigningTasks\n    dependsOn(tasks.withType(Sign))\n}\n\ntasks.withType(Sign) {\n    // disable signing by default\n    enabled = false\n    mustRunAfter enableSigningTasks\n    // sign all jars, except the source jar – it doesn't have classes\n    ext.useJarsigner = (name.toLowerCase().endsWith(\"jar\") && name != \"signSourceJar\")\n}\n\ngradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->\n    taskGraph.allTasks.each { Task task ->\n        if (task instanceof Sign && task.useJarsigner) {\n            task.doFirst {\n                task.filesToSign.each { File file ->\n                    // see https://ant.apache.org/manual/Tasks/signjar.html for arguments\n                    // ForgeGradle also uses ant.signjar: https://fckaf.de/DCw\n                    println \"$task – signing $file with ant.signjar\"\n                    task.ant.signjar(\n                            jar: file,\n                            alias: \"1\",\n                            storetype: findProperty(\"LogisticsPipes.storetype\"),\n                            keystore: findProperty(\"LogisticsPipes.keystore\"),\n                            storepass: findProperty(\"LogisticsPipes.storepass\"),\n                            verbose: \"true\",\n                            preservelastmodified: \"true\"\n                    )\n                }\n            }\n        } else if (task.name.startsWith('prepareRunServerTest')) {\n            task.doFirst {\n                final def serverTestHome = projectDir.toPath().resolve('run-server-test')\n                if (findProperty(\"acceptMinecraftServerEula\") == 'true') {\n                    def eulaFile = serverTestHome.resolve('eula.txt')\n                    Files.deleteIfExists(eulaFile)\n                    eulaFile.write('eula=true')\n                }\n\n                final serverProperties = serverTestHome.resolve('server.properties')\n                def properties = new Properties()\n                try {\n                    serverProperties.withReader {reader ->\n                        properties.load(reader)\n                    }\n                } catch (IOException e) {\n                    println \"Error reading $serverProperties\"\n                    e.printStackTrace()\n                }\n                properties.setProperty('spawn-monsters', 'false')\n                properties.setProperty('spawn-npcs', 'false')\n                properties.setProperty('spawn-animals', 'false')\n                properties.setProperty('generate-structures', 'false')\n                properties.setProperty('online-mode', 'false')\n                properties.setProperty('gamemode', '1')\n                properties.setProperty('level-type', 'FLAT')\n                properties.setProperty('generator-settings', '3;minecraft:bedrock,3*minecraft:stone,96*minecraft:sandstone;2;')\n                properties.setProperty('motd', 'Logistics Pipes Test Server')\n                //properties.setProperty('max-tick-time', '0') // for debugging the server\n                try {\n                    serverProperties.withWriter {writer ->\n                        properties.store(writer, null)\n                    }\n                } catch (IOException e) {\n                    println \"Error reading $serverProperties\"\n                    e.printStackTrace()\n                }\n            }\n        }\n    }\n}\n\nabstract class DownloadTask extends DefaultTask {\n    @Input\n    String url\n\n    @OutputFile\n    final RegularFileProperty outputFile = project.objects.fileProperty()\n\n    @TaskAction\n    void download() {\n        ant.get(src: url, dest: outputFile.get().asFile)\n    }\n}\n\ntask downloadLanguage(type: DownloadTask) {\n    url = \"https://github.com/RS485/LogisticsPipes-Language/archive/master.zip\"\n    outputFile.set(layout.buildDirectory.file(\"language.zip\"))\n}\n\ntask languageMain(dependsOn: downloadLanguage, type: Copy) {\n    from zipTree(downloadLanguage.outputFile)\n    into \"${sourceSets.main.getOutput().resourcesDir}/assets/logisticspipes/lang/\"\n    include \"*/*.lang\"\n\n    includeEmptyDirs false\n    eachFile { FileCopyDetails fcd ->\n        fcd.relativePath = new RelativePath(!fcd.isDirectory(), fcd.relativePath.segments.drop(1))\n    }\n}\n\ntask languageBook(dependsOn: downloadLanguage, type: Copy) {\n    from zipTree(downloadLanguage.outputFile)\n    into \"${sourceSets.main.getOutput().resourcesDir}/assets/logisticspipes/book/\"\n    include \"*/book/\"\n\n    includeEmptyDirs false\n    eachFile { FileCopyDetails fcd ->\n        fcd.relativePath = new RelativePath(!fcd.isDirectory(), fcd.relativePath.segments.drop(2))\n    }\n}\n\ntask language(dependsOn: [languageMain, languageBook], type: Copy) {\n    processResources.dependsOn language\n}\n\ntasks.named('wrapper') {\n    gradleVersion = '7.5'\n    distributionType = Wrapper.DistributionType.ALL\n}\n\ntasks.withType(AbstractArchiveTask) {\n    preserveFileTimestamps = false\n    reproducibleFileOrder = true\n}\n\ntask integrationTests(dependsOn: ['prepareRunServerTest'], type: Exec) {\n    workingDir projectDir\n\n    commandLine \"$projectDir/gradlew\"\n    args '--no-daemon', '--stacktrace', 'runServerTest'\n    ignoreExitValue = true\n\n    standardOutput = new ByteArrayOutputStream()\n    errorOutput = standardOutput // redirect stderr to stdout\n\n\tdoFirst {\n\t\tif (System.properties['os.name'].toLowerCase().contains('windows')) {\n\t\t\tcommandLine = [\"cmd\", \"/c\", \"$projectDir/gradlew.bat\"] + args\n\t\t}\n\t}\n\n    doLast {\n        final output = standardOutput.toString()\n        final start = output.indexOf('[STARTING LOGISTICSPIPES TESTS]')\n        if (start == -1) throw new GradleException(\"Cannot find LP test start:\\n${output}\")\n        final logStart = output.substring(0, start).lastIndexOf('\\n') + 1\n        def testOutput = output.substring(logStart)\n        final end = testOutput.indexOf('Attempting to read last messages from the daemon log')\n        if (end != -1) {\n            // remove double output from daemon log\n            testOutput = testOutput.substring(0, end)\n        }\n        if (testOutput.contains('[FAILED]')) {\n            throw new GradleException(\"Error in LP Tests:\\n${testOutput}\")\n        } else {\n            testOutput.eachLine {\n                if (it.contains('[STARTING LOGISTICSPIPES TESTS]') ||\n                        it.contains('[PASSED]') ||\n                        it.contains('[SKIPPED]')) {\n                    println(it)\n                }\n            }\n        }\n    }\n}\n\npublishing {\n    publications {\n        mavenJava(MavenPublication) {\n            artifact jar\n        }\n    }\n    repositories {\n        maven {\n            url \"file://${project.projectDir}/mcmodsrepo\"\n        }\n    }\n}\n\ntasks.withType(JavaCompile).configureEach {\n    options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation\n}\n"
  },
  {
    "path": "common/logisticspipes/LPBlocks.java",
    "content": "package logisticspipes;\n\nimport net.minecraftforge.fml.common.registry.GameRegistry;\n\nimport logisticspipes.blocks.BlockDummy;\nimport logisticspipes.blocks.LogisticsSolidBlock;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericSubMultiBlock;\n\npublic class LPBlocks {\n\n\t// Logistics Blocks\n\t@GameRegistry.ObjectHolder(\"logisticspipes:solid_block\")\n\tpublic static BlockDummy dummy;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:frame\")\n\tpublic static LogisticsSolidBlock frame;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:power_junction\")\n\tpublic static LogisticsSolidBlock powerJunction;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:security_station\")\n\tpublic static LogisticsSolidBlock securityStation;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:crafting_table\")\n\tpublic static LogisticsSolidBlock crafter;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:crafting_table_fuzzy\")\n\tpublic static LogisticsSolidBlock crafterFuzzy;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:statistics_table\")\n\tpublic static LogisticsSolidBlock statisticsTable;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:power_provider_rf\")\n\tpublic static LogisticsSolidBlock powerProviderRF;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:power_provider_eu\")\n\tpublic static LogisticsSolidBlock powerProviderEU;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:power_provider_mj\")\n\tpublic static LogisticsSolidBlock powerProviderMJ;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:program_compiler\")\n\tpublic static LogisticsSolidBlock programCompiler;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:pipe\")\n\tpublic static LogisticsBlockGenericPipe pipe;\n\n\t@GameRegistry.ObjectHolder(\"logisticspipes:sub_multiblock\")\n\tpublic static LogisticsBlockGenericSubMultiBlock subMultiblock;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/LPConstants.java",
    "content": "package logisticspipes;\n\npublic class LPConstants {\n\n\tprivate LPConstants() {}\n\n\tpublic static final String LP_MOD_ID = \"logisticspipes\";\n\n\tpublic static final float FACADE_THICKNESS = 2F / 16F;\n\tpublic static final float PIPE_NORMAL_SPEED = 0.01F;\n\tpublic static final float PIPE_MIN_POS = 0.1875F;\n\tpublic static final float PIPE_MAX_POS = 0.8125F;\n\tpublic static final float BC_PIPE_MIN_POS = 0.25F;\n\tpublic static final float BC_PIPE_MAX_POS = 0.75F;\n\n\tpublic static final String computerCraftModID = \"computercraft\";\n\tpublic static final String openComputersModID = \"opencomputers\";\n\tpublic static final String ic2ModID = \"ic2\";\n\tpublic static final String bcSiliconModID = \"buildcraftsilicon\";\n\tpublic static final String bcTransportModID = \"buildcrafttransport\";\n\tpublic static final String thermalExpansionModID = \"thermalexpansion\";\n\tpublic static final String enderCoreModID = \"endercore\";\n\tpublic static final String neiModID = \"notenoughitems\";\n\tpublic static final String thermalDynamicsModID = \"thermaldynamics\";\n\tpublic static final String cclrenderModID = \"cclrender\";\n\tpublic static final String ironChestModID = \"ironchest\";\n\tpublic static final String cofhCoreModID = \"cofhcore\";\n\tpublic static final String mcmpModID = \"mcmultipart\";\n\tpublic static final String appliedenergisticsModID = \"appliedenergistics2\";\n\tpublic static final String storagedrawersModID = \"storagedrawers\";\n\tpublic static final String theOneProbeModID = \"theoneprobe\";\n\n}\n"
  },
  {
    "path": "common/logisticspipes/LPItems.java",
    "content": "package logisticspipes;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.fml.common.registry.GameRegistry.ObjectHolder;\n\nimport com.google.common.collect.BiMap;\nimport com.google.common.collect.HashBiMap;\n\nimport logisticspipes.items.ItemBlankModule;\nimport logisticspipes.items.ItemDisk;\nimport logisticspipes.items.ItemHUDArmor;\nimport logisticspipes.items.ItemLogisticsChips;\nimport logisticspipes.items.ItemLogisticsProgrammer;\nimport logisticspipes.items.ItemPipeController;\nimport logisticspipes.items.LogisticsBrokenItem;\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.items.RemoteOrderer;\nimport network.rs485.logisticspipes.guidebook.ItemGuideBook;\n\npublic class LPItems {\n\n\t// Logistics Pipes\n\t@ObjectHolder(\"logisticspipes:pipe_transport_basic\")\n\tpublic static Item pipeUnrouted;\n\n\t@ObjectHolder(\"logisticspipes:pipe_basic\")\n\tpublic static Item pipeBasic;\n\n\t@ObjectHolder(\"logisticspipes:pipe_request\")\n\tpublic static Item pipeRequest;\n\n\t@ObjectHolder(\"logisticspipes:pipe_request_mk2\")\n\tpublic static Item pipeRequestMk2;\n\n\t@ObjectHolder(\"logisticspipes:pipe_provider\")\n\tpublic static Item pipeProvider;\n\n\t@ObjectHolder(\"logisticspipes:pipe_crafting\")\n\tpublic static Item pipeCrafting;\n\n\t@ObjectHolder(\"logisticspipes:pipe_satellite\")\n\tpublic static Item pipeSatellite;\n\n\t@ObjectHolder(\"logisticspipes:pipe_supplier\")\n\tpublic static Item pipeSupplier;\n\n\t@ObjectHolder(\"logisticspipes:pipe_chassis_mk1\")\n\tpublic static Item pipeChassisMk1;\n\n\t@ObjectHolder(\"logisticspipes:pipe_chassis_mk2\")\n\tpublic static Item pipeChassisMk2;\n\n\t@ObjectHolder(\"logisticspipes:pipe_chassis_mk3\")\n\tpublic static Item pipeChassisMk3;\n\n\t@ObjectHolder(\"logisticspipes:pipe_chassis_mk4\")\n\tpublic static Item pipeChassisMk4;\n\n\t@ObjectHolder(\"logisticspipes:pipe_chassis_mk5\")\n\tpublic static Item pipeChassisMk5;\n\n\t@ObjectHolder(\"logisticspipes:pipe_inventory_system_connector\")\n\tpublic static Item pipeInvSystemConnector;\n\n\t@ObjectHolder(\"logisticspipes:pipe_system_entrance\")\n\tpublic static Item pipeSystemEntrance;\n\n\t@ObjectHolder(\"logisticspipes:pipe_system_destination\")\n\tpublic static Item pipeSystemDestination;\n\n\t@ObjectHolder(\"logisticspipes:pipe_firewall\")\n\tpublic static Item pipeFirewall;\n\n\t@ObjectHolder(\"logisticspipes:pipe_remote_orderer\")\n\tpublic static Item pipeRemoteOrderer;\n\n\t@ObjectHolder(\"logisticspipes:pipe_request_table\")\n\tpublic static Item requestTable;\n\n\t// Logistics Fluid Pipes\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_basic\")\n\tpublic static Item pipeFluidBasic;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_request\")\n\tpublic static Item pipeFluidRequest;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_provider\")\n\tpublic static Item pipeFluidProvider;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_satellite\")\n\tpublic static Item pipeFluidSatellite;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_supplier\")\n\tpublic static Item pipeFluidSupplier;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_supplier_mk2\")\n\tpublic static Item pipeFluidSupplierMk2;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_insertion\")\n\tpublic static Item pipeFluidInsertion;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_extractor\")\n\tpublic static Item pipeFluidExtractor;\n\n\t@ObjectHolder(\"logisticspipes:pipe_fluid_terminus\")\n\tpublic static Item pipeFluidTerminus;\n\n\t// Logistics Modules/Upgrades\n\t@ObjectHolder(\"logisticspipes:module_blank\")\n\tpublic static ItemBlankModule blankModule;\n\n\tpublic static BiMap<String, ResourceLocation> modules = HashBiMap.create();\n\tpublic static BiMap<String, ResourceLocation> upgrades = HashBiMap.create();\n\n\t// Miscellaneous Items\n\t@ObjectHolder(\"logisticspipes:guide_book\")\n\tpublic static ItemGuideBook itemGuideBook;\n\n\t@ObjectHolder(\"logisticspipes:remote_orderer\")\n\tpublic static RemoteOrderer remoteOrderer;\n\n\t@ObjectHolder(\"logisticspipes:disk\")\n\tpublic static ItemDisk disk;\n\n\t@ObjectHolder(\"logisticspipes:item_card\")\n\tpublic static LogisticsItemCard itemCard;\n\n\t@ObjectHolder(\"logisticspipes:hud_glasses\")\n\tpublic static ItemHUDArmor hudGlasses;\n\n\t@ObjectHolder(\"logisticspipes:fluid_container\")\n\tpublic static LogisticsFluidContainer fluidContainer;\n\n\t@ObjectHolder(\"logisticspipes:pipe_controller\")\n\tpublic static ItemPipeController pipeController;\n\n\t@ObjectHolder(\"logisticspipes:logistics_programmer\")\n\tpublic static ItemLogisticsProgrammer logisticsProgrammer;\n\n\t@ObjectHolder(\"logisticspipes:chip_basic\")\n\tpublic static ItemLogisticsChips chipBasic;\n\n\t@ObjectHolder(\"logisticspipes:chip_basic_raw\")\n\tpublic static ItemLogisticsChips chipBasicRaw;\n\n\t@ObjectHolder(\"logisticspipes:chip_advanced\")\n\tpublic static ItemLogisticsChips chipAdvanced;\n\n\t@ObjectHolder(\"logisticspipes:chip_advanced_raw\")\n\tpublic static ItemLogisticsChips chipAdvancedRaw;\n\n\t@ObjectHolder(\"logisticspipes:chip_fpga\")\n\tpublic static ItemLogisticsChips chipFPGA;\n\n\t@ObjectHolder(\"logisticspipes:chip_fpga_raw\")\n\tpublic static ItemLogisticsChips chipFPGARaw;\n\n\t@ObjectHolder(\"logisticspipes:broken_item\")\n\tpublic static LogisticsBrokenItem brokenItem;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/LogisticsEventListener.java",
    "content": "package logisticspipes;\n\nimport java.lang.ref.WeakReference;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Queue;\nimport java.util.WeakHashMap;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.entity.EntityPlayerSP;\nimport net.minecraft.client.gui.inventory.GuiChest;\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.tileentity.TileEntityChest;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.ChunkPos;\nimport net.minecraft.util.text.TextComponentString;\nimport net.minecraft.util.text.TextComponentTranslation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.event.GuiOpenEvent;\nimport net.minecraftforge.event.entity.EntityJoinWorldEvent;\nimport net.minecraftforge.event.entity.player.ItemTooltipEvent;\nimport net.minecraftforge.event.entity.player.PlayerInteractEvent;\nimport net.minecraftforge.event.world.ChunkWatchEvent.UnWatch;\nimport net.minecraftforge.event.world.ChunkWatchEvent.Watch;\nimport net.minecraftforge.event.world.WorldEvent;\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.gameevent.PlayerEvent;\nimport net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;\nimport net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent;\nimport net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.IItemAdvancedExistance;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.PlayerConfigToClientPacket;\nimport logisticspipes.network.packets.chassis.ChestGuiClosed;\nimport logisticspipes.network.packets.chassis.ChestGuiOpened;\nimport logisticspipes.network.packets.gui.GuiReopenPacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.GuiOverlay;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.ticks.VersionChecker;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.QuickSortChestMarkerStorage;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.config.PlayerConfiguration;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.module.AsyncQuicksortModule;\nimport network.rs485.logisticspipes.util.TextUtil;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\npublic class LogisticsEventListener {\n\n\tpublic static final WeakHashMap<EntityPlayer, List<WeakReference<AsyncQuicksortModule>>> chestQuickSortConnection = new WeakHashMap<>();\n\tpublic static Map<ChunkPos, PlayerCollectionList> watcherList = new ConcurrentHashMap<>();\n\n\t@SubscribeEvent\n\tpublic void onEntitySpawn(EntityJoinWorldEvent event) {\n\t\tif (event != null && event.getEntity() instanceof EntityItem && event.getEntity().world != null && !event.getEntity().world.isRemote) {\n\t\t\tItemStack stack = ((EntityItem) event.getEntity()).getItem(); //Get ItemStack\n\t\t\tif (!stack.isEmpty() && stack.getItem() instanceof IItemAdvancedExistance && !((IItemAdvancedExistance) stack.getItem()).canExistInWorld(stack)) {\n\t\t\t\tevent.setCanceled(true);\n\t\t\t}\n\t\t\tif (stack.hasTagCompound()) {\n\t\t\t\tfor (String key : Objects.requireNonNull(stack.getTagCompound(), \"nbt for stack must be non-null\").getKeySet()) {\n\t\t\t\t\tif (key.startsWith(\"logisticspipes:routingdata\")) {\n\t\t\t\t\t\tItemRoutingInformation info = ItemRoutingInformation.restoreFromNBT(stack.getTagCompound().getCompoundTag(key));\n\t\t\t\t\t\tinfo.setItemTimedout();\n\t\t\t\t\t\t((EntityItem) event.getEntity()).setItem(info.getItem().getItem().makeNormalStack(stack.getCount()));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void onPlayerLeftClickBlock(final PlayerInteractEvent.LeftClickBlock event) {\n\t\tif (MainProxy.isServer(event.getEntityPlayer().world)) {\n\t\t\tfinal TileEntity tile = event.getEntityPlayer().world.getTileEntity(event.getPos());\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\tif (((LogisticsTileGenericPipe) tile).pipe instanceof CoreRoutedPipe) {\n\t\t\t\t\tif (!((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).canBeDestroyedByPlayer(event.getEntityPlayer())) {\n\t\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t\t\tevent.getEntityPlayer().sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t\t\t((LogisticsTileGenericPipe) tile).scheduleNeighborChange();\n\t\t\t\t\t\tWorld world = event.getEntityPlayer().world;\n\t\t\t\t\t\tBlockPos pos = tile.getPos();\n\t\t\t\t\t\tIBlockState state = world.getBlockState(pos);\n\t\t\t\t\t\tworld.markAndNotifyBlock(tile.getPos(), world.getChunk(pos), state, state, 2);\n\t\t\t\t\t\t((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).delayTo = System.currentTimeMillis() + 200;\n\t\t\t\t\t\t((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).repeatFor = 10;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).setDestroyByPlayer();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void onPlayerLeftClickBlock(final PlayerInteractEvent.RightClickBlock event) {\n\t\tif (MainProxy.isServer(event.getEntityPlayer().world)) {\n\t\t\tWorldCoordinatesWrapper worldCoordinates = new WorldCoordinatesWrapper(event.getEntityPlayer().world, event.getPos());\n\t\t\tTileEntity tileEntity = worldCoordinates.getTileEntity();\n\t\t\tif (tileEntity instanceof TileEntityChest || SimpleServiceLocator.ironChestProxy.isIronChest(tileEntity)) {\n\t\t\t\tList<WeakReference<AsyncQuicksortModule>> list = worldCoordinates.allNeighborTileEntities().stream()\n\t\t\t\t\t\t.filter(NeighborTileEntity::isLogisticsPipe)\n\t\t\t\t\t\t.filter(adjacent -> ((LogisticsTileGenericPipe) adjacent.getTileEntity()).pipe instanceof PipeLogisticsChassis)\n\t\t\t\t\t\t.filter(adjacent -> ((PipeLogisticsChassis) ((LogisticsTileGenericPipe) adjacent.getTileEntity()).pipe).getPointedOrientation()\n\t\t\t\t\t\t\t\t== adjacent.getOurDirection())\n\t\t\t\t\t\t.map(adjacent -> (PipeLogisticsChassis) ((LogisticsTileGenericPipe) adjacent.getTileEntity()).pipe)\n\t\t\t\t\t\t.flatMap(chassis -> chassis.getModules().getModules())\n\t\t\t\t\t\t.filter(logisticsModule -> logisticsModule instanceof AsyncQuicksortModule)\n\t\t\t\t\t\t.map(logisticsModule -> new WeakReference<>((AsyncQuicksortModule) logisticsModule))\n\t\t\t\t\t\t.collect(Collectors.toList());\n\n\t\t\t\tif (!list.isEmpty()) {\n\t\t\t\t\tLogisticsEventListener.chestQuickSortConnection.put(event.getEntityPlayer(), list);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static HashMap<Integer, Long> WorldLoadTime = new HashMap<>();\n\n\t@SubscribeEvent\n\tpublic void WorldLoad(WorldEvent.Load event) {\n\t\tif (MainProxy.isServer(event.getWorld())) {\n\t\t\tint dim = event.getWorld().provider.getDimension();\n\t\t\tif (!LogisticsEventListener.WorldLoadTime.containsKey(dim)) {\n\t\t\t\tLogisticsEventListener.WorldLoadTime.put(dim, System.currentTimeMillis());\n\t\t\t}\n\t\t}\n\t\tif (MainProxy.isClient(event.getWorld())) {\n\t\t\tSimpleServiceLocator.routerManager.clearClientRouters();\n\t\t\tLogisticsHUDRenderer.instance().clear();\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void WorldUnload(WorldEvent.Unload event) {\n\t\tif (MainProxy.isServer(event.getWorld())) {\n\t\t\tint dim = event.getWorld().provider.getDimension();\n\t\t\tSimpleServiceLocator.routerManager.dimensionUnloaded(dim);\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void watchChunk(Watch event) {\n\t\tChunkPos pos = event.getChunkInstance().getPos();\n\t\tif (!LogisticsEventListener.watcherList.containsKey(pos)) {\n\t\t\tLogisticsEventListener.watcherList.put(pos, new PlayerCollectionList());\n\t\t}\n\t\tLogisticsEventListener.watcherList.get(pos).add(event.getPlayer());\n\t}\n\n\t@SubscribeEvent\n\tpublic void unWatchChunk(UnWatch event) {\n\t\tChunkPos pos = event.getChunkInstance().getPos();\n\t\tif (LogisticsEventListener.watcherList.containsKey(pos)) {\n\t\t\tLogisticsEventListener.watcherList.get(pos).remove(event.getPlayer());\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void onPlayerLogin(PlayerLoggedInEvent event) {\n\t\tif (MainProxy.isServer(event.player.world)) {\n\t\t\tSimpleServiceLocator.securityStationManager.sendClientAuthorizationList(event.player);\n\t\t}\n\n\t\tSimpleServiceLocator.serverBufferHandler.clear(event.player);\n\t\tClientConfiguration config = LogisticsPipes.getServerConfigManager().getPlayerConfiguration(PlayerIdentifier.get(event.player));\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PlayerConfigToClientPacket.class).setConfig(config), event.player);\n\t}\n\n\t@SubscribeEvent\n\tpublic void onPlayerLogout(PlayerLoggedOutEvent event) {\n\t\tSimpleServiceLocator.serverBufferHandler.clear(event.player);\n\t}\n\n\t@AllArgsConstructor\n\tprivate static class GuiEntry {\n\n\t\t@Getter\n\t\tprivate final int xCoord;\n\t\t@Getter\n\t\tprivate final int yCoord;\n\t\t@Getter\n\t\tprivate final int zCoord;\n\t\t@Getter\n\t\tprivate final int guiID;\n\t\t@Getter\n\t\t@Setter\n\t\tprivate boolean isActive;\n\t}\n\n\t@Getter(lazy = true)\n\tprivate static final Queue<GuiEntry> guiPos = new LinkedList<>();\n\n\t//Handle GuiRepoen\n\t@SubscribeEvent\n\t@SideOnly(Side.CLIENT)\n\tpublic void onGuiOpen(GuiOpenEvent event) {\n\t\tif (!LogisticsEventListener.getGuiPos().isEmpty()) {\n\t\t\tif (event.getGui() == null) {\n\t\t\t\tGuiEntry part = LogisticsEventListener.getGuiPos().peek();\n\t\t\t\tif (part.isActive()) {\n\t\t\t\t\tpart = LogisticsEventListener.getGuiPos().poll();\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(GuiReopenPacket.class).setGuiID(part.getGuiID()).setPosX(part.getXCoord()).setPosY(part.getYCoord()).setPosZ(part.getZCoord()));\n\t\t\t\t\tGuiOverlay.getInstance().setOverlaySlotActive(false);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tGuiEntry part = LogisticsEventListener.getGuiPos().peek();\n\t\t\t\tpart.setActive(true);\n\t\t\t}\n\t\t}\n\t\tif (event.getGui() == null) {\n\t\t\tGuiOverlay.getInstance().setOverlaySlotActive(false);\n\t\t}\n\t\tif (event.getGui() instanceof GuiChest || (SimpleServiceLocator.ironChestProxy != null && SimpleServiceLocator.ironChestProxy.isChestGui(event.getGui()))) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(ChestGuiOpened.class));\n\t\t} else {\n\t\t\tQuickSortChestMarkerStorage.getInstance().disable();\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(ChestGuiClosed.class));\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic static void addGuiToReopen(int xCoord, int yCoord, int zCoord, int guiID) {\n\t\tLogisticsEventListener.getGuiPos().add(new GuiEntry(xCoord, yCoord, zCoord, guiID, false));\n\t}\n\n\t@SubscribeEvent\n\tpublic void clientLoggedIn(ClientConnectedToServerEvent event) {\n\t\tSimpleServiceLocator.clientBufferHandler.clear();\n\n\t\tif (Configs.CHECK_FOR_UPDATES) {\n\t\t\tLogisticsPipes.singleThreadExecutor.execute(() -> {\n\t\t\t\t// try to get player entity ten times, once a second\n\t\t\t\tint times = 0;\n\t\t\t\tEntityPlayerSP playerEntity;\n\t\t\t\tdo {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tThread.sleep(1000);\n\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tplayerEntity = FMLClientHandler.instance().getClientPlayerEntity();\n\t\t\t\t\t++times;\n\t\t\t\t} while (playerEntity == null && times <= 10);\n\n\t\t\t\tif (times > 10) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tVersionChecker checker = LogisticsPipes.versionChecker;\n\n\t\t\t\t// send player message\n\t\t\t\tString versionMessage = checker.getVersionCheckerStatus();\n\n\t\t\t\tif (checker.isVersionCheckDone() && checker.getVersionInfo().isNewVersionAvailable() && !checker.getVersionInfo().isImcMessageSent()) {\n\t\t\t\t\tplayerEntity.sendMessage(new TextComponentString(versionMessage));\n\t\t\t\t\tplayerEntity.sendMessage(new TextComponentString(\"Use \\\"/logisticspipes changelog\\\" to see a changelog.\"));\n\t\t\t\t} else if (!checker.isVersionCheckDone()) {\n\t\t\t\t\tplayerEntity.sendMessage(new TextComponentString(versionMessage));\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\t@SideOnly(Side.CLIENT)\n\tpublic void onItemStackToolTip(ItemTooltipEvent event) {\n\t\tif (event.getItemStack().hasTagCompound()) {\n\t\t\tfor (String key : event.getItemStack().getTagCompound().getKeySet()) {\n\t\t\t\tif (key.startsWith(\"logisticspipes:routingdata\")) {\n\t\t\t\t\tItemRoutingInformation info = ItemRoutingInformation.restoreFromNBT(event.getItemStack().getTagCompound().getCompoundTag(key));\n\t\t\t\t\tList<String> list = event.getToolTip();\n\t\t\t\t\tlist.set(0, ChatColor.RED + \"!!! \" + ChatColor.WHITE + list.get(0) + ChatColor.RED + \" !!!\" + ChatColor.WHITE);\n\t\t\t\t\tlist.add(1, TextUtil.translate(\"itemstackinfo.lprouteditem\"));\n\t\t\t\t\tlist.add(2, TextUtil.translate(\"itemstackinfo.lproutediteminfo\"));\n\t\t\t\t\tlist.add(3, TextUtil.translate(\"itemstackinfo.lprouteditemtype\") + \": \" + info.getItem().toString());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void onItemCrafting(PlayerEvent.ItemCraftedEvent event) {\n\t\tif (event.player.isServerWorld() && !event.crafting.isEmpty()) {\n\t\t\tif (event.crafting.getItem().getRegistryName().getNamespace().equals(LPConstants.LP_MOD_ID)) {\n\t\t\t\tPlayerIdentifier identifier = PlayerIdentifier.get(event.player);\n\t\t\t\tPlayerConfiguration config = LogisticsPipes.getServerConfigManager().getPlayerConfiguration(identifier);\n\t\t\t\tif (!config.getHasCraftedLPItem() && !LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tItemStack book = new ItemStack(LPItems.itemGuideBook, 1);\n\t\t\t\t\tevent.player.addItemStackToInventory(book);\n\n\t\t\t\t\tconfig.setHasCraftedLPItem(true);\n\t\t\t\t\tLogisticsPipes.getServerConfigManager().setPlayerConfiguration(identifier, config);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/LogisticsPipes.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.Enumeration;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Queue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.function.Consumer;\nimport java.util.function.Function;\nimport java.util.function.Supplier;\nimport java.util.jar.JarFile;\nimport java.util.jar.Manifest;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.CraftingManager;\nimport net.minecraft.item.crafting.Ingredient;\nimport net.minecraft.item.crafting.ShapelessRecipes;\nimport net.minecraft.launchwrapper.IClassTransformer;\nimport net.minecraft.launchwrapper.Launch;\nimport net.minecraft.launchwrapper.LaunchClassLoader;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.client.event.ModelRegistryEvent;\nimport net.minecraftforge.client.event.TextureStitchEvent;\nimport net.minecraftforge.common.MinecraftForge;\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.capabilities.CapabilityInject;\nimport net.minecraftforge.common.crafting.CraftingHelper;\nimport net.minecraftforge.event.RegistryEvent;\nimport net.minecraftforge.fluids.capability.IFluidHandler;\nimport net.minecraftforge.fml.common.Loader;\nimport net.minecraftforge.fml.common.Mod;\nimport net.minecraftforge.fml.common.event.FMLFingerprintViolationEvent;\nimport net.minecraftforge.fml.common.event.FMLInitializationEvent;\nimport net.minecraftforge.fml.common.event.FMLInterModComms;\nimport net.minecraftforge.fml.common.event.FMLPostInitializationEvent;\nimport net.minecraftforge.fml.common.event.FMLPreInitializationEvent;\nimport net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;\nimport net.minecraftforge.fml.common.event.FMLServerStartedEvent;\nimport net.minecraftforge.fml.common.event.FMLServerStartingEvent;\nimport net.minecraftforge.fml.common.event.FMLServerStoppingEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.network.NetworkRegistry;\nimport net.minecraftforge.fml.common.registry.GameRegistry;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\nimport net.minecraftforge.items.IItemHandler;\nimport net.minecraftforge.registries.GameData;\nimport net.minecraftforge.registries.IForgeRegistry;\n\nimport lombok.Getter;\nimport lombok.SneakyThrows;\nimport org.apache.logging.log4j.Logger;\n\nimport logisticspipes.asm.LogisticsPipesClassInjector;\nimport logisticspipes.asm.LogisticsPipesCoreLoader;\nimport logisticspipes.asm.wrapper.LogisticsWrapperHandler;\nimport logisticspipes.blocks.BlockDummy;\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.blocks.LogisticsSolidBlock;\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsIC2PowerProviderTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsRFPowerProviderTileEntity;\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.chathelper.LPChatListener;\nimport logisticspipes.config.Configs;\nimport logisticspipes.datafixer.LPDataFixer;\nimport logisticspipes.items.ItemBlankModule;\nimport logisticspipes.items.ItemDisk;\nimport logisticspipes.items.ItemHUDArmor;\nimport logisticspipes.items.ItemLogisticsChips;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.items.ItemLogisticsProgrammer;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.items.ItemParts;\nimport logisticspipes.items.ItemPipeController;\nimport logisticspipes.items.ItemPipeManager;\nimport logisticspipes.items.ItemPipeSignCreator;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.items.LogisticsBrokenItem;\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.items.LogisticsSolidBlockItem;\nimport logisticspipes.items.RemoteOrderer;\nimport logisticspipes.logistics.LogisticsFluidManager;\nimport logisticspipes.logistics.LogisticsManager;\nimport logisticspipes.network.GuiHandler;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.PipeFluidBasic;\nimport logisticspipes.pipes.PipeFluidExtractor;\nimport logisticspipes.pipes.PipeFluidInsertion;\nimport logisticspipes.pipes.PipeFluidProvider;\nimport logisticspipes.pipes.PipeFluidRequestLogistics;\nimport logisticspipes.pipes.PipeFluidSatellite;\nimport logisticspipes.pipes.PipeFluidSupplierMk2;\nimport logisticspipes.pipes.PipeFluidTerminus;\nimport logisticspipes.pipes.PipeItemsBasicLogistics;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.PipeItemsFirewall;\nimport logisticspipes.pipes.PipeItemsFluidSupplier;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.PipeItemsProviderLogistics;\nimport logisticspipes.pipes.PipeItemsRemoteOrdererLogistics;\nimport logisticspipes.pipes.PipeItemsRequestLogistics;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.PipeItemsSatelliteLogistics;\nimport logisticspipes.pipes.PipeItemsSupplierLogistics;\nimport logisticspipes.pipes.PipeItemsSystemDestinationLogistics;\nimport logisticspipes.pipes.PipeItemsSystemEntranceLogistics;\nimport logisticspipes.pipes.PipeLogisticsChassisMk1;\nimport logisticspipes.pipes.PipeLogisticsChassisMk2;\nimport logisticspipes.pipes.PipeLogisticsChassisMk3;\nimport logisticspipes.pipes.PipeLogisticsChassisMk4;\nimport logisticspipes.pipes.PipeLogisticsChassisMk5;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericSubMultiBlock;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.pipes.tubes.HSTubeCurve;\nimport logisticspipes.pipes.tubes.HSTubeGain;\nimport logisticspipes.pipes.tubes.HSTubeLine;\nimport logisticspipes.pipes.tubes.HSTubeSCurve;\nimport logisticspipes.pipes.tubes.HSTubeSpeedup;\nimport logisticspipes.pipes.unrouted.PipeItemsBasicTransport;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.ProxyManager;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.SpecialInventoryHandlerManager;\nimport logisticspipes.proxy.SpecialTankHandlerManager;\nimport logisticspipes.proxy.computers.objects.LPGlobalCCAccess;\nimport logisticspipes.proxy.endercore.EnderCoreProgressProvider;\nimport logisticspipes.proxy.ic2.IC2ProgressProvider;\nimport logisticspipes.proxy.progressprovider.MachineProgressProvider;\nimport logisticspipes.proxy.recipeproviders.LogisticsCraftingTable;\nimport logisticspipes.proxy.specialconnection.SpecialPipeConnection;\nimport logisticspipes.proxy.specialconnection.SpecialTileConnection;\nimport logisticspipes.proxy.specialtankhandler.SpecialTankHandler;\nimport logisticspipes.proxy.te.ThermalExpansionProgressProvider;\nimport logisticspipes.recipes.CraftingRecipes;\nimport logisticspipes.recipes.LPChipRecipes;\nimport logisticspipes.recipes.ModuleChippedCraftingRecipes;\nimport logisticspipes.recipes.PipeChippedCraftingRecipes;\nimport logisticspipes.recipes.RecipeManager;\nimport logisticspipes.recipes.UpgradeChippedCraftingRecipes;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.renderer.newpipe.LogisticsNewSolidBlockWorldRenderer;\nimport logisticspipes.renderer.newpipe.tube.CurveTubeRenderer;\nimport logisticspipes.renderer.newpipe.tube.GainTubeRenderer;\nimport logisticspipes.renderer.newpipe.tube.LineTubeRenderer;\nimport logisticspipes.renderer.newpipe.tube.SCurveTubeRenderer;\nimport logisticspipes.renderer.newpipe.tube.SpeedupTubeRenderer;\nimport logisticspipes.routing.RouterManager;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.routing.channels.ChannelManagerProvider;\nimport logisticspipes.routing.pathfinder.PipeInformationManager;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.ticks.ClientPacketBufferHandlerThread;\nimport logisticspipes.ticks.HudUpdateTick;\nimport logisticspipes.ticks.LPTickHandler;\nimport logisticspipes.ticks.QueuedTasks;\nimport logisticspipes.ticks.RenderTickHandler;\nimport logisticspipes.ticks.RoutingTableUpdateThread;\nimport logisticspipes.ticks.ServerPacketBufferHandlerThread;\nimport logisticspipes.ticks.VersionChecker;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.InventoryUtilFactory;\nimport logisticspipes.utils.RoutedItemHelper;\nimport logisticspipes.utils.StaticResolverUtil;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.grow.ServerTickDispatcher;\nimport network.rs485.logisticspipes.compat.TheOneProbeIntegration;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.config.ServerConfigurationManager;\nimport network.rs485.logisticspipes.gui.font.LPFontRenderer;\nimport network.rs485.logisticspipes.guidebook.ItemGuideBook;\nimport network.rs485.logisticspipes.property.PropertyUpdaterEventListener;\nimport network.rs485.util.SystemUtilKt;\n\n//@formatter:off\n//CHECKSTYLE:OFF\n\n@Mod(\n\t\tname = \"Logistics Pipes\",\n\t\tmodid = LPConstants.LP_MOD_ID,\n\t\tcertificateFingerprint = \"e0c86912b2f7cc0cc646ad57799574aea43dbd45\",\n\t\tuseMetadata = true)\npublic class LogisticsPipes {\n\t//@formatter:on\n\t//CHECKSTYLE:ON\n\n\tpublic static final String UNKNOWN = \"unknown\";\n\tprivate static boolean DEBUG = true;\n\tprivate Consumer<FMLServerStartedEvent> minecraftTestStartMethod = null;\n\n\tpublic static boolean isDEBUG() {\n\t\treturn DEBUG;\n\t}\n\n\t@Getter\n\tprivate static String VERSION = UNKNOWN;\n\t@Getter\n\tprivate static String VENDOR = UNKNOWN;\n\t@Getter\n\tprivate static String TARGET = UNKNOWN;\n\n\tpublic LogisticsPipes() { //TODO: remove throws\n\t\tfinal LaunchClassLoader loader = Launch.classLoader;\n\t\tloadManifestValues(loader);\n\n\t\tif (!LogisticsPipesCoreLoader.isCoremodLoaded()) {\n\t\t\tif (LogisticsPipes.DEBUG) {\n\t\t\t\tthrow new RuntimeException(\"LogisticsPipes FMLLoadingPlugin wasn't loaded. If you are running MC from an IDE make sure to add '-Dfml.coreMods.load=logisticspipes.asm.LogisticsPipesCoreLoader' to the VM arguments. If you are running MC normal please report this as a bug at 'https://github.com/RS485/LogisticsPipes/issues'.\");\n\t\t\t} else {\n\t\t\t\tthrow new RuntimeException(\"LogisticsPipes FMLLoadingPlugin wasn't loaded. Your download seems to be corrupt/modified. Please redownload LP from our Jenkins [http://ci.rs485.network] and move it into your mods folder.\");\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tField fTransformers = LaunchClassLoader.class.getDeclaredField(\"transformers\");\n\t\t\tfTransformers.setAccessible(true);\n\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\tList<IClassTransformer> transformers = (List<IClassTransformer>) fTransformers.get(loader);\n\t\t\tIClassTransformer lpClassInjector = new LogisticsPipesClassInjector();\n\t\t\ttransformers.add(lpClassInjector);\n\t\t\t// Avoid NPE caused by wrong ClassTransformers\n\t\t\tfor (int i = transformers.size() - 1; i > 0; i--) { // Move everything one up\n\t\t\t\ttransformers.set(i, transformers.get(i - 1));\n\t\t\t}\n\t\t\ttransformers.set(0, lpClassInjector); // So that our injector can be first\n\t\t} catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException e) {\n\t\t\tloader.registerTransformer(\"logisticspipes.asm.LogisticsPipesClassInjector\");\n\t\t\te.printStackTrace();\n\t\t}\n\n\t\tMinecraftForge.EVENT_BUS.register(this);\n\t}\n\n\tprivate static void loadManifestValues(ClassLoader loader) {\n\t\ttry {\n\t\t\tfinal Enumeration<URL> resources = loader.getResources(JarFile.MANIFEST_NAME);\n\t\t\tboolean foundLp;\n\t\t\tdo {\n\t\t\t\tfinal Manifest manifest = new Manifest(resources.nextElement().openStream());\n\t\t\t\tfoundLp = \"LogisticsPipes\".equals(manifest.getMainAttributes().getValue(\"Specification-Title\"));\n\t\t\t\tif (foundLp) {\n\t\t\t\t\tLogisticsPipes.DEBUG = false;\n\t\t\t\t\tLogisticsPipes.VERSION = manifest.getMainAttributes().getValue(\"Implementation-Version\");\n\t\t\t\t\tLogisticsPipes.VENDOR = manifest.getMainAttributes().getValue(\"Implementation-Vendor\");\n\t\t\t\t\tLogisticsPipes.TARGET = manifest.getMainAttributes().getValue(\"Implementation-Target\");\n\t\t\t\t}\n\t\t\t} while (resources.hasMoreElements() && !foundLp);\n\t\t} catch (IOException e) {\n\t\t\tLogisticsPipes.log.error(\"There was a problem loading our MANIFEST file, Logistics Pipes will not know about its origin\");\n\t\t}\n\t}\n\n\t@Mod.Instance(\"logisticspipes\")\n\tpublic static LogisticsPipes instance;\n\n\tprivate static boolean certificateError = false;\n\n\tpublic static String getVersionString() {\n\t\treturn Stream.of(\n\t\t\t\t\"Logistics Pipes \" + LogisticsPipes.VERSION,\n\t\t\t\tLogisticsPipes.certificateError ? \"certificate error\" : \"\",\n\t\t\t\tLogisticsPipes.DEBUG ? \"debug mode\" : \"\",\n\t\t\t\t\"target \" + LogisticsPipes.TARGET,\n\t\t\t\t\"vendor \" + LogisticsPipes.VENDOR)\n\t\t\t\t.filter(str -> !str.isEmpty())\n\t\t\t\t.collect(Collectors.joining(\", \"));\n\t}\n\n\t// other statics\n\tpublic static Textures textures = new Textures();\n\tpublic static Logger log;\n\tpublic static ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();\n\tpublic static VersionChecker versionChecker;\n\n\t// initializes the creative tab\n\tpublic static final CreativeTabs CREATIVE_TAB_LP = new CreativeTabs(\"Logistics_Pipes\") {\n\n\t\t@SideOnly(Side.CLIENT)\n\t\t@Nonnull\n\t\tpublic ItemStack createIcon() {\n\t\t\treturn new ItemStack(LPItems.pipeBasic);\n\t\t}\n\t};\n\n\tprivate Queue<Runnable> postInitRun = new LinkedList<>();\n\tprivate static LPGlobalCCAccess generalAccess;\n\tprivate static ClientConfiguration playerConfig;\n\tprivate static ServerConfigurationManager serverConfigManager;\n\n\tprivate List<Supplier<Pair<Item, Item>>> resetRecipeList = new ArrayList<>();\n\n\t@CapabilityInject(IItemHandler.class)\n\tpublic static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = null;\n\n\t@CapabilityInject(IFluidHandler.class)\n\tpublic static Capability<IFluidHandler> FLUID_HANDLER_CAPABILITY = null;\n\n\tpublic static boolean isDevelopmentEnvironment() {\n\t\tif (!isDEBUG()) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tboolean eclipseCheck = (new File(\".classpath\")).exists();\n\t\t\tboolean ideaCheck = System.getProperty(\"java.class.path\").contains(\"idea_rt.jar\");\n\n\t\t\treturn eclipseCheck || ideaCheck;\n\t\t}\n\t}\n\n\t@Mod.EventHandler\n\tpublic void init(FMLInitializationEvent event) {\n\t\tregisterRecipes(); // TODO data fileS!!!!!\n\n\t\t//Register Network channels\n\t\tMainProxy.createChannels();\n\n\t\tRouterManager manager = new RouterManager();\n\t\tSimpleServiceLocator.setRouterManager(manager);\n\t\tSimpleServiceLocator.setChannelConnectionManager(manager);\n\t\tSimpleServiceLocator.setSecurityStationManager(manager);\n\t\tSimpleServiceLocator.setLogisticsManager(new LogisticsManager());\n\t\tSimpleServiceLocator.setInventoryUtilFactory(new InventoryUtilFactory());\n\t\tSimpleServiceLocator.setSpecialConnectionHandler(new SpecialPipeConnection());\n\t\tSimpleServiceLocator.setSpecialConnectionHandler(new SpecialTileConnection());\n\t\tSimpleServiceLocator.setSpecialTankHandler(new SpecialTankHandler());\n\t\tSimpleServiceLocator.setMachineProgressProvider(new MachineProgressProvider());\n\t\tSimpleServiceLocator.setRoutedItemHelper(new RoutedItemHelper());\n\t\tSimpleServiceLocator.setChannelManagerProvider(new ChannelManagerProvider());\n\n\t\tNetworkRegistry.INSTANCE.registerGuiHandler(LogisticsPipes.instance, new GuiHandler());\n\t\tMinecraftForge.EVENT_BUS.register(new LPTickHandler());\n\n\t\tif (event.getSide().equals(Side.CLIENT)) {\n\t\t\tRenderTickHandler sub = new RenderTickHandler();\n\t\t\tMinecraftForge.EVENT_BUS.register(sub);\n\t\t}\n\t\tMinecraftForge.EVENT_BUS.register(new QueuedTasks());\n\t\tif (event.getSide() == Side.CLIENT) {\n\t\t\tSimpleServiceLocator.setClientPacketBufferHandlerThread(new ClientPacketBufferHandlerThread());\n\t\t}\n\t\tSimpleServiceLocator.setServerPacketBufferHandlerThread(new ServerPacketBufferHandlerThread());\n\t\tfor (int i = 0; i < Configs.MULTI_THREAD_NUMBER; i++) {\n\t\t\tnew RoutingTableUpdateThread(i);\n\t\t}\n\t\tMinecraftForge.EVENT_BUS.register(new LogisticsEventListener());\n\t\tMinecraftForge.EVENT_BUS.register(new LPChatListener());\n\t\tMinecraftForge.EVENT_BUS.register(PropertyUpdaterEventListener.INSTANCE);\n\n\t\tLPDataFixer.INSTANCE.init();\n\n\t\tif (event.getSide() == Side.SERVER) {\n\t\t\tLogisticsPipes.textures.registerBlockIcons(null);\n\t\t} else if (event.getSide() == Side.CLIENT) {\n\t\t\tLPFontRenderer.Factory.asyncPreload();\n\t\t}\n\n\t\t// load all the models so they don't get loaded and crash on concurrent class loading\n\t\t// the OBJParser is a non-sharable static thing\n\t\tLogisticsNewRenderPipe.loadModels();\n\t\tLogisticsNewSolidBlockWorldRenderer.loadModels();\n\t\tCurveTubeRenderer.loadModels();\n\t\tGainTubeRenderer.loadModels();\n\t\tLineTubeRenderer.loadModels();\n\t\tSpeedupTubeRenderer.loadModels();\n\t\tSCurveTubeRenderer.loadModels();\n\n\t\tif (isTesting()) {\n\t\t\tfinal Class<?> testClass;\n\t\t\ttry {\n\t\t\t\ttestClass = Class.forName(\"network.rs485.logisticspipes.integration.MinecraftTest\");\n\t\t\t} catch (ReflectiveOperationException e) {\n\t\t\t\tthrow new RuntimeException(\"Error loading minecraft test class\", e);\n\t\t\t}\n\t\t\tfinal Object minecraftTestInstance;\n\t\t\ttry {\n\t\t\t\tminecraftTestInstance = testClass.getDeclaredField(\"INSTANCE\").get(null);\n\t\t\t\tfinal Method serverStartMethod = testClass\n\t\t\t\t\t\t.getDeclaredMethod(\"serverStart\", FMLServerStartedEvent.class);\n\t\t\t\tminecraftTestStartMethod = (FMLServerStartedEvent serverStartedEvent) -> {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tserverStartMethod.invoke(minecraftTestInstance, serverStartedEvent);\n\t\t\t\t\t} catch (ReflectiveOperationException e) {\n\t\t\t\t\t\tthrow new RuntimeException(\"Could not run server started hook in \" + minecraftTestInstance, e);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t} catch (ReflectiveOperationException e) {\n\t\t\t\tthrow new RuntimeException(\"Error accessing minecraft test instance\", e);\n\t\t\t}\n\n\t\t\tMinecraftForge.EVENT_BUS.register(minecraftTestInstance);\n\t\t}\n\t}\n\n\tpublic static boolean isTesting() {\n\t\treturn SystemUtilKt.checkBooleanProperty(\"logisticspipes.test\");\n\t}\n\n\t@Mod.EventHandler\n\tpublic void preInit(FMLPreInitializationEvent evt) {\n\t\tStaticResolverUtil.useASMDataTable(evt.getAsmData());\n\t\tPacketHandler.initialize();\n\t\tNewGuiHandler.initialize();\n\n\t\tLogisticsPipes.log = evt.getModLog();\n\t\tlog.info(\"====================================================\");\n\t\tlog.info(\" LogisticsPipes Logger initialized, enabled levels: \");\n\t\tlog.info(\"----------------------------------------------------\");\n\t\tlog.info(\"    Fatal: \" + log.isFatalEnabled());\n\t\tlog.info(\"    Error: \" + log.isErrorEnabled());\n\t\tlog.info(\"    Warn:  \" + log.isWarnEnabled());\n\t\tlog.info(\"    Info:  \" + log.isInfoEnabled());\n\t\tlog.info(\"    Trace: \" + log.isTraceEnabled());\n\t\tlog.info(\"    Debug: \" + log.isDebugEnabled());\n\t\tlog.info(\"====================================================\");\n\t\tloadClasses();\n\t\tProxyManager.load();\n\t\tConfigs.load();\n\t\tif (LogisticsPipes.certificateError) {\n\t\t\tLogisticsPipes.log.fatal(\"Certificate not correct\");\n\t\t\tLogisticsPipes.log.fatal(\"This in not a LogisticsPipes version from RS485.\");\n\t\t}\n\n\t\tif (LogisticsPipes.UNKNOWN.equals(LogisticsPipes.VERSION)) {\n\t\t\tLogisticsPipes.log.warn(\"Could not determine Logistics Pipes version, we do need that \" + JarFile.MANIFEST_NAME + \", don't you know?\");\n\t\t}\n\t\tLogisticsPipes.log.info(\"Running \" + getVersionString());\n\n\t\tSimpleServiceLocator.setPipeInformationManager(new PipeInformationManager());\n\t\tSimpleServiceLocator.setLogisticsFluidManager(new LogisticsFluidManager());\n\n\t\tif (Loader.isModLoaded(LPConstants.theOneProbeModID)) {\n\t\t\tFMLInterModComms.sendFunctionMessage(LPConstants.theOneProbeModID, \"getTheOneProbe\",\n\t\t\t\t\tTheOneProbeIntegration.class.getName());\n\t\t}\n\n\t\tMainProxy.proxy.initModelLoader();\n\t}\n\n\t@Mod.EventHandler\n\tpublic void postInit(FMLPostInitializationEvent event) {\n\t\tpostInitRun.forEach(Runnable::run);\n\t\tpostInitRun = null;\n\n\t\tSpecialInventoryHandlerManager.load();\n\t\tSpecialTankHandlerManager.load();\n\n\t\tSimpleServiceLocator.buildCraftProxy.registerPipeInformationProvider();\n\t\tSimpleServiceLocator.buildCraftProxy.initProxy();\n\n\t\tSimpleServiceLocator.thermalDynamicsProxy.registerPipeInformationProvider();\n\n\t\t//SimpleServiceLocator.specialpipeconnection.registerHandler(new TeleportPipes());\n\t\t//SimpleServiceLocator.specialtileconnection.registerHandler(new TesseractConnection());\n\n\t\t//SimpleServiceLocator.addCraftingRecipeProvider(LogisticsWrapperHandler.getWrappedRecipeProvider(\"BuildCraft|Factory\", \"AutoWorkbench\", AutoWorkbench.class));\n\t\t//SimpleServiceLocator.addCraftingRecipeProvider(LogisticsWrapperHandler.getWrappedRecipeProvider(\"BuildCraft|Silicon\", \"AssemblyAdvancedWorkbench\", AssemblyAdvancedWorkbench.class));\n\t\tif (SimpleServiceLocator.buildCraftProxy.getAssemblyTableProviderClass() != null) {\n\t\t\tSimpleServiceLocator.addCraftingRecipeProvider(LogisticsWrapperHandler.getWrappedRecipeProvider(LPConstants.bcSiliconModID, \"AssemblyTable\", SimpleServiceLocator.buildCraftProxy.getAssemblyTableProviderClass()));\n\t\t}\n\t\tSimpleServiceLocator.addCraftingRecipeProvider(new LogisticsCraftingTable());\n\n\t\tSimpleServiceLocator.machineProgressProvider.registerProgressProvider(LogisticsWrapperHandler.getWrappedProgressProvider(LPConstants.thermalExpansionModID, \"Generic\", ThermalExpansionProgressProvider.class));\n\t\tSimpleServiceLocator.machineProgressProvider.registerProgressProvider(LogisticsWrapperHandler.getWrappedProgressProvider(LPConstants.ic2ModID, \"Generic\", IC2ProgressProvider.class));\n\t\t//SimpleServiceLocator.machineProgressProvider.registerProgressProvider(LogisticsWrapperHandler.getWrappedProgressProvider(\"EnderIO\", \"Generic\", EnderIOProgressProvider.class));\n\t\tSimpleServiceLocator.machineProgressProvider.registerProgressProvider(LogisticsWrapperHandler.getWrappedProgressProvider(LPConstants.enderCoreModID, \"Generic\", EnderCoreProgressProvider.class));\n\n\t\tGameRegistry.registerTileEntity(LogisticsPowerJunctionTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"power_junction\"));\n\t\tGameRegistry.registerTileEntity(LogisticsRFPowerProviderTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"power_provider_rf\"));\n\t\tGameRegistry.registerTileEntity(LogisticsIC2PowerProviderTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"power_provider_ic2\"));\n\t\tGameRegistry.registerTileEntity(LogisticsSecurityTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"security_station\"));\n\t\tGameRegistry.registerTileEntity(LogisticsCraftingTableTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"logistics_crafting_table\"));\n\t\tGameRegistry.registerTileEntity(LogisticsTileGenericPipe.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"pipe\"));\n\t\tGameRegistry.registerTileEntity(LogisticsStatisticsTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"statistics_table\"));\n\t\tGameRegistry.registerTileEntity(LogisticsProgramCompilerTileEntity.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"program_compiler\"));\n\t\tGameRegistry.registerTileEntity(LogisticsTileGenericSubMultiBlock.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"submultiblock\"));\n\n\t\tMainProxy.proxy.registerTileEntities();\n\n\t\tSimpleServiceLocator.mcmpProxy.registerTileEntities();\n\n\t\t//Registering special particles\n\t\tMainProxy.proxy.registerParticles();\n\n\t\t//init Fluids\n\t\tFluidIdentifier.initFromForge(false);\n\n\t\tversionChecker = VersionChecker.runVersionCheck();\n\t}\n\n\t@SubscribeEvent\n\t@SideOnly(Side.CLIENT)\n\tpublic void textureLoad(TextureStitchEvent.Pre event) {\n\t\tif (!event.getMap().getBasePath().equals(\"textures\")) {\n\t\t\treturn;\n\t\t}\n\t\tMainProxy.proxy.registerTextures();\n\t}\n\n\t@SubscribeEvent\n\tpublic void initItems(RegistryEvent.Register<Item> event) {\n\t\tIForgeRegistry<Item> registry = event.getRegistry();\n\n\t\tItemPipeSignCreator.registerPipeSignTypes();\n\t\tItemModule.loadModules(registry);\n\t\tItemUpgrade.loadUpgrades(registry);\n\t\tregisterPipes(registry);\n\n\t\tregistry.register(setName(new LogisticsItemCard(), \"item_card\"));\n\t\tregistry.register(setName(new RemoteOrderer(), \"remote_orderer\"));\n\t\tregistry.register(setName(new ItemPipeSignCreator(), \"sign_creator\"));\n\t\tregistry.register(setName(new ItemHUDArmor(), \"hud_glasses\"));\n\t\tregistry.register(setName(new ItemParts(), \"parts\"));\n\t\tregistry.register(setName(new ItemBlankModule(), \"module_blank\"));\n\t\tregistry.register(setName(new ItemDisk(), \"disk\"));\n\t\tregistry.register(setName(new LogisticsFluidContainer(), \"fluid_container\"));\n\t\tregistry.register(setName(new LogisticsBrokenItem(), \"broken_item\"));\n\t\tregistry.register(setName(new ItemGuideBook(), \"guide_book\"));\n\t\tregistry.register(setName(new ItemPipeController(), \"pipe_controller\"));\n\t\tregistry.register(setName(new ItemPipeManager(), \"pipe_manager\"));\n\t\tregistry.register(setName(new ItemLogisticsProgrammer(), \"logistics_programmer\"));\n\t\tregistry.register(setName(new ItemLogisticsChips(ItemLogisticsChips.ITEM_CHIP_BASIC), \"chip_basic\"));\n\t\tregistry.register(setName(new ItemLogisticsChips(ItemLogisticsChips.ITEM_CHIP_BASIC_RAW), \"chip_basic_raw\"));\n\t\tregistry.register(setName(new ItemLogisticsChips(ItemLogisticsChips.ITEM_CHIP_ADVANCED), \"chip_advanced\"));\n\t\tregistry.register(setName(new ItemLogisticsChips(ItemLogisticsChips.ITEM_CHIP_ADVANCED_RAW), \"chip_advanced_raw\"));\n\t\tregistry.register(setName(new ItemLogisticsChips(ItemLogisticsChips.ITEM_CHIP_FPGA), \"chip_fpga\"));\n\t\tregistry.register(setName(new ItemLogisticsChips(ItemLogisticsChips.ITEM_CHIP_FPGA_RAW), \"chip_fpga_raw\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.frame), \"frame\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.powerJunction), \"power_junction\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.securityStation), \"security_station\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.crafter), \"crafting_table\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.crafterFuzzy), \"crafting_table_fuzzy\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.statisticsTable), \"statistics_table\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.powerProviderRF), \"power_provider_rf\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.powerProviderEU), \"power_provider_eu\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.powerProviderMJ), \"power_provider_mj\"));\n\t\tregistry.register(setName(new LogisticsSolidBlockItem(LPBlocks.programCompiler), \"program_compiler\"));\n\t}\n\n\t// TODO move somewhere\n\tpublic static <T extends Item> T setName(T item, String name) {\n\t\treturn setName(item, name, LPConstants.LP_MOD_ID);\n\t}\n\n\tpublic static <T extends Item> T setName(T item, String name, String modID) {\n\t\titem.setRegistryName(modID, name);\n\t\titem.setTranslationKey(String.format(\"%s.%s\", modID, name));\n\t\treturn item;\n\t}\n\n\t// TODO move somewhere\n\tpublic static <T extends Block> T setName(T block, String name) {\n\t\tblock.setRegistryName(LPConstants.LP_MOD_ID, name);\n\t\tblock.setTranslationKey(String.format(\"%s.%s\", LPConstants.LP_MOD_ID, name));\n\t\treturn block;\n\t}\n\n\t@SubscribeEvent\n\tpublic void initBlocks(RegistryEvent.Register<Block> event) {\n\t\tIForgeRegistry<Block> registry = event.getRegistry();\n\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_BLOCK_FRAME), \"frame\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_POWER_JUNCTION), \"power_junction\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_SECURITY_STATION), \"security_station\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_AUTOCRAFTING_TABLE), \"crafting_table\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_FUZZYCRAFTING_TABLE), \"crafting_table_fuzzy\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_STATISTICS_TABLE), \"statistics_table\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_RF_POWERPROVIDER), \"power_provider_rf\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_IC2_POWERPROVIDER), \"power_provider_eu\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_BC_POWERPROVIDER), \"power_provider_mj\"));\n\t\tregistry.register(setName(new LogisticsSolidBlock(LogisticsSolidBlock.Type.LOGISTICS_PROGRAM_COMPILER), \"program_compiler\"));\n\n\t\tregistry.register(setName(new BlockDummy(), \"solid_block\"));\n\n\t\tregistry.register(setName(new LogisticsBlockGenericPipe(), \"pipe\"));\n\t\tregistry.register(setName(new LogisticsBlockGenericSubMultiBlock(), \"sub_multiblock\"));\n\t}\n\n\t@SubscribeEvent\n\tpublic void onModelLoad(ModelRegistryEvent e) {\n\t\tMainProxy.proxy.registerModels();\n\t}\n\n\tprivate void registerRecipes() {\n\t\tRecipeManager.recipeProvider.add(new LPChipRecipes());\n\t\tRecipeManager.recipeProvider.add(new UpgradeChippedCraftingRecipes());\n\t\tRecipeManager.recipeProvider.add(new ModuleChippedCraftingRecipes());\n\t\tRecipeManager.recipeProvider.add(new PipeChippedCraftingRecipes());\n\t\tRecipeManager.recipeProvider.add(new CraftingRecipes());\n\t\tRecipeManager.loadRecipes();\n\n\t\tresetRecipeList.stream()\n\t\t\t\t.map(Supplier::get)\n\t\t\t\t.forEach(itemItemPair -> registerShapelessResetRecipe(itemItemPair.getValue1(), itemItemPair.getValue2()));\n\t}\n\n\t@SneakyThrows\n\tprivate void loadClasses() {\n\t\t//Try to load all classes to let our checksums get generated\n\t\tforName(\"net.minecraft.tileentity.TileEntity\");\n\t\tforName(\"net.minecraft.world.World\");\n\t\tforName(\"net.minecraft.item.ItemStack\");\n\t\tforName(\"net.minecraftforge.fluids.FluidStack\");\n\t\tforName(\"net.minecraftforge.fluids.Fluid\");\n\t\tforName(\"cofh.thermaldynamics.block.TileTDBase\");\n\t\tforName(\"cofh.thermaldynamics.duct.item.TravelingItem\");\n\t\tforName(\"crazypants.enderio.conduit.item.ItemConduit\");\n\t\tforName(\"crazypants.enderio.conduit.item.NetworkedInventory\");\n\t\tforName(\"crazypants.enderio.conduit.liquid.AbstractLiquidConduit\");\n\t\tforName(\"mcmultipart.block.BlockMultipartContainer\");\n\t}\n\n\tprivate void forName(String string) {\n\t\ttry {\n\t\t\tClass.forName(string);\n\t\t} catch (Exception ignore) {}\n\t}\n\n\t@Mod.EventHandler\n\tpublic void beforeStart(FMLServerAboutToStartEvent event) {\n\t\tServerTickDispatcher.INSTANCE.serverStart();\n\t}\n\n\t@Mod.EventHandler\n\tpublic void cleanup(FMLServerStoppingEvent event) {\n\t\tSimpleServiceLocator.routerManager.serverStopClean();\n\t\tQueuedTasks.clearAllTasks();\n\t\tHudUpdateTick.clearUpdateFlags();\n\t\tPipeItemsSatelliteLogistics.cleanup();\n\t\tPipeFluidSatellite.cleanup();\n\t\tServerRouter.cleanup();\n\t\tif (event.getSide().equals(Side.CLIENT)) {\n\t\t\tLogisticsHUDRenderer.instance().clear();\n\t\t}\n\t\tServerTickDispatcher.INSTANCE.cleanup();\n\t\tLogisticsPipes.serverConfigManager = null;\n\t}\n\n\t@Mod.EventHandler\n\tpublic void registerCommands(FMLServerStartingEvent event) {\n\t\tevent.registerServerCommand(new LogisticsPipesCommand());\n\t}\n\n\t@Mod.EventHandler\n\tpublic void serverStarted(FMLServerStartedEvent event) {\n\t\tif (minecraftTestStartMethod != null) minecraftTestStartMethod.accept(event);\n\t}\n\n\t@Mod.EventHandler\n\tpublic void certificateWarning(FMLFingerprintViolationEvent warning) {\n\t\tLogisticsPipes.certificateError = true;\n\t\tif (!LogisticsPipes.isDEBUG()) {\n\t\t\tSystem.out.println(\"[LogisticsPipes|Certificate] Certificate not correct\");\n\t\t\tSystem.out.println(\"[LogisticsPipes|Certificate] Expected: \" + warning.getExpectedFingerprint());\n\t\t\tSystem.out.println(\"[LogisticsPipes|Certificate] File: \" + warning.getSource().getAbsolutePath());\n\t\t\tSystem.out.println(\"[LogisticsPipes|Certificate] This in not a LogisticsPipes version from RS485.\");\n\t\t}\n\t}\n\n\tpublic static Object getComputerLP() {\n\t\tif (LogisticsPipes.generalAccess == null) {\n\t\t\tLogisticsPipes.generalAccess = new LPGlobalCCAccess();\n\t\t}\n\t\treturn LogisticsPipes.generalAccess;\n\t}\n\n\tpublic void registerPipes(IForgeRegistry<Item> registry) {\n\t\tregisterPipe(registry, \"basic\", PipeItemsBasicLogistics::new);\n\t\tregisterPipe(registry, \"request\", PipeItemsRequestLogistics::new);\n\t\tregisterPipe(registry, \"provider\", PipeItemsProviderLogistics::new);\n\t\tregisterPipe(registry, \"crafting\", PipeItemsCraftingLogistics::new);\n\t\tregisterPipe(registry, \"satellite\", PipeItemsSatelliteLogistics::new);\n\t\tregisterPipe(registry, \"supplier\", PipeItemsSupplierLogistics::new);\n\t\tregisterPipe(registry, \"chassis_mk1\", PipeLogisticsChassisMk1::new);\n\t\tregisterPipe(registry, \"chassis_mk2\", PipeLogisticsChassisMk2::new);\n\t\tregisterPipe(registry, \"chassis_mk3\", PipeLogisticsChassisMk3::new);\n\t\tregisterPipe(registry, \"chassis_mk4\", PipeLogisticsChassisMk4::new);\n\t\tregisterPipe(registry, \"chassis_mk5\", PipeLogisticsChassisMk5::new);\n\t\tregisterPipe(registry, \"request_mk2\", PipeItemsRequestLogisticsMk2::new);\n\t\tregisterPipe(registry, \"remote_orderer\", PipeItemsRemoteOrdererLogistics::new);\n\t\tregisterPipe(registry, \"inventory_system_connector\", PipeItemsInvSysConnector::new);\n\t\tregisterPipe(registry, \"system_entrance\", PipeItemsSystemEntranceLogistics::new);\n\t\tregisterPipe(registry, \"system_destination\", PipeItemsSystemDestinationLogistics::new);\n\t\tregisterPipe(registry, \"firewall\", PipeItemsFirewall::new);\n\n\t\tregisterPipe(registry, \"fluid_basic\", PipeFluidBasic::new);\n\t\tregisterPipe(registry, \"fluid_supplier\", PipeItemsFluidSupplier::new);\n\t\tregisterPipe(registry, \"fluid_insertion\", PipeFluidInsertion::new);\n\t\tregisterPipe(registry, \"fluid_provider\", PipeFluidProvider::new);\n\t\tregisterPipe(registry, \"fluid_request\", PipeFluidRequestLogistics::new);\n\t\tregisterPipe(registry, \"fluid_extractor\", PipeFluidExtractor::new);\n\t\tregisterPipe(registry, \"fluid_satellite\", PipeFluidSatellite::new);\n\t\tregisterPipe(registry, \"fluid_supplier_mk2\", PipeFluidSupplierMk2::new);\n\t\tregisterPipe(registry, \"fluid_terminus\", PipeFluidTerminus::new);\n\n\t\tregisterPipe(registry, \"request_table\", PipeBlockRequestTable::new);\n\n\t\tregisterPipe(registry, \"transport_basic\", PipeItemsBasicTransport::new);\n\n\t\tregisterPipe(registry, \"hs_curve\", HSTubeCurve::new);\n\t\tregisterPipe(registry, \"hs_speedup\", HSTubeSpeedup::new);\n\t\tregisterPipe(registry, \"hs_s_curve\", HSTubeSCurve::new);\n\t\tregisterPipe(registry, \"hs_line\", HSTubeLine::new);\n\t\tregisterPipe(registry, \"hs_gain\", HSTubeGain::new);\n\t}\n\n\tprotected void registerPipe(IForgeRegistry<Item> registry, String name, Function<Item, ? extends CoreUnroutedPipe> constructor) {\n\t\tfinal ItemLogisticsPipe res = LogisticsBlockGenericPipe.registerPipe(registry, name, constructor);\n\t\tfinal CoreUnroutedPipe pipe = Objects.requireNonNull(LogisticsBlockGenericPipe.createPipe(res), \"created a null pipe from \" + res);\n\t\tif (pipe instanceof CoreRoutedPipe) {\n\t\t\tpostInitRun.add(() -> res.setPipeIconIndex(((CoreRoutedPipe) pipe).getTextureType(null).normal, ((CoreRoutedPipe) pipe).getTextureType(null).newTexture));\n\t\t}\n\n\t\tif (pipe.getClass() != PipeItemsBasicLogistics.class && CoreRoutedPipe.class.isAssignableFrom(pipe.getClass())) {\n\t\t\tif (pipe.getClass() != PipeFluidBasic.class && FluidRoutedPipe.class.isAssignableFrom(pipe.getClass())) {\n\t\t\t\tresetRecipeList.add(() -> new Pair<>(res, LPItems.pipeFluidBasic));\n\t\t\t} else if (!pipe.isPipeBlock()) {\n\t\t\t\tresetRecipeList.add(() -> new Pair<>(res, LPItems.pipeBasic));\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void registerShapelessResetRecipe(Item fromItem, Item toItem) {\n\t\tNonNullList<Ingredient> list = NonNullList.create();\n\t\tlist.add(CraftingHelper.getIngredient(new ItemStack(fromItem, 1, 0)));\n\n\t\tItemStack output = new ItemStack(toItem, 1, 0);\n\n\t\tResourceLocation baseLoc = new ResourceLocation(LPConstants.LP_MOD_ID, fromItem.getRegistryName().getPath() + \".resetrecipe\");\n\t\tResourceLocation recipeLoc = baseLoc;\n\t\tint index = 0;\n\t\twhile (CraftingManager.REGISTRY.containsKey(recipeLoc)) {\n\t\t\tindex++;\n\t\t\trecipeLoc = new ResourceLocation(LPConstants.LP_MOD_ID, baseLoc.getPath() + \"_\" + index);\n\t\t}\n\n\t\tShapelessRecipes recipe = new ShapelessRecipes(\"logisticspipes.resetrecipe.pipe\", output, list);\n\t\trecipe.setRegistryName(recipeLoc);\n\t\tGameData.register_impl(recipe);\n\t}\n\n\tpublic static ClientConfiguration getClientPlayerConfig() {\n\t\tif (LogisticsPipes.playerConfig == null) {\n\t\t\tLogisticsPipes.playerConfig = new ClientConfiguration();\n\t\t}\n\t\treturn LogisticsPipes.playerConfig;\n\t}\n\n\tpublic static ServerConfigurationManager getServerConfigManager() {\n\t\tif (LogisticsPipes.serverConfigManager == null) {\n\t\t\tLogisticsPipes.serverConfigManager = new ServerConfigurationManager();\n\t\t}\n\t\treturn LogisticsPipes.serverConfigManager;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/api/IHUDArmor.java",
    "content": "package logisticspipes.api;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\npublic interface IHUDArmor {\n\n\tboolean isEnabled(@Nonnull ItemStack item);\n}\n"
  },
  {
    "path": "common/logisticspipes/api/ILPPipe.java",
    "content": "package logisticspipes.api;\n\n/**\n * Public interface implemented by LP's internal Pipe logic\n */\npublic interface ILPPipe {\n\n\t/**\n\t * @return true if the pipe can route items inside the network\n\t */\n\tboolean isRoutedPipe();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/api/ILPPipeConfigTool.java",
    "content": "package logisticspipes.api;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\n/**\n * public interface to be implemented by an item which can open the config GUI for a logistics pipe.\n * Some mod compatibility is already implemented inside LP.\n */\npublic interface ILPPipeConfigTool {\n\n\tboolean canWrench(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe);\n\n\tvoid wrenchUsed(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe);\n}\n"
  },
  {
    "path": "common/logisticspipes/api/ILPPipeTile.java",
    "content": "package logisticspipes.api;\n\nimport net.minecraft.util.math.BlockPos;\n\n/**\n * Public interface implemented by LP's Pipe tile\n */\npublic interface ILPPipeTile {\n\n\t/**\n\t * Used to access the internal pipe logic This also can return the\n\t * IRequestAPI or IRoutedPowerProvider\n\t *\n\t * @return the pipe\n\t */\n\tILPPipe getLPPipe();\n\n\tBlockPos getBlockPos();\n}\n"
  },
  {
    "path": "common/logisticspipes/api/ILogisticsPowerProvider.java",
    "content": "package logisticspipes.api;\n\n/**\n * things which directly provide power to the logsitics network implement this.\n * lists of these objects available to a network will be cached, and the closest\n * one with power preferentially pulled from.\n *\n * @author Andrew\n */\npublic interface ILogisticsPowerProvider extends IRoutedPowerProvider {\n\n\tint getPowerLevel();\n}\n"
  },
  {
    "path": "common/logisticspipes/api/IProgressProvider.java",
    "content": "package logisticspipes.api;\n\n/**\n * Implemented by an TileEntity this will allow LP to access the current\n * progress of an TileEntity connected to a crafting pipe and display the\n * progress inside it's crafting tree view.\n */\npublic interface IProgressProvider {\n\n\t/**\n\t * @return a value between 0 and 100 that indicates the current progress of\n\t * this TileEntity machine\n\t */\n\tbyte getMachineProgressForLP();\n}\n"
  },
  {
    "path": "common/logisticspipes/api/IRoutedPowerProvider.java",
    "content": "package logisticspipes.api;\n\nimport java.util.List;\n\n/**\n * things implementing this interface are capable of providing power, but they\n * draw from another sources Implement ILogisticsPowerProvider if you wish to\n * provide power to the LP network. Losses of energy based on distance may be\n * involved.\n *\n * @author Andrew\n */\npublic interface IRoutedPowerProvider {\n\n\t// typically calls useEnergy(amount,null);\n\tboolean useEnergy(int amount);\n\n\t// typically calls canUseEnergy(amount,null);\n\tboolean canUseEnergy(int amount);\n\n\t// for the case where 1 IRoutedPowerProvider has to check another\n\t// each IRoutedPowerProvider that can recurse should:\n\t//   a) check that it is not already on the list\n\t//   b) add itself to the list (creating it if the list is null),\n\tboolean useEnergy(int amount, List<Object> providersToIgnore);\n\n\tboolean canUseEnergy(int amount, List<Object> providersToIgnore);\n\n\tint getX(); // the coordinates of the associated tile (typically \"this.xCoords\"). needed for sending packets.\n\n\tint getY();\n\n\tint getZ();\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ClientSideOnlyMethodContent.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ClientSideOnlyMethodContent {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/IgnoreDisabledProxy.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface IgnoreDisabledProxy {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/LogisticsASMHookClass.java",
    "content": "package logisticspipes.asm;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport lombok.SneakyThrows;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.routing.pathfinder.changedetection.TEControl;\n\npublic class LogisticsASMHookClass {\n\n\tpublic static void callingClearedMethod() {\n\t\tthrow new RuntimeException(\"This Method should never be called\");\n\t}\n\n\t@SneakyThrows(Exception.class)\n\tpublic static void validate(TileEntity tile) {\n\t\ttry {\n\t\t\tTEControl.validate(tile);\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@SneakyThrows(Exception.class)\n\tpublic static void invalidate(TileEntity tile) {\n\t\ttry {\n\t\t\tTEControl.invalidate(tile);\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/LogisticsClassTransformer.java",
    "content": "package logisticspipes.asm;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Enumeration;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.function.Consumer;\nimport java.util.jar.Manifest;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.launchwrapper.IClassTransformer;\nimport net.minecraft.launchwrapper.Launch;\nimport net.minecraft.launchwrapper.LaunchClassLoader;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\nimport net.minecraftforge.fml.common.Loader;\nimport net.minecraftforge.fml.common.ModContainer;\nimport net.minecraftforge.fml.common.asm.transformers.AccessTransformer;\nimport net.minecraftforge.fml.common.asm.transformers.ModAccessTransformer;\nimport net.minecraftforge.fml.common.versioning.ArtifactVersion;\nimport net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;\nimport net.minecraftforge.fml.common.versioning.VersionParser;\nimport net.minecraftforge.fml.common.versioning.VersionRange;\nimport net.minecraftforge.fml.relauncher.Side;\n\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AnnotationNode;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.FieldNode;\nimport org.objectweb.asm.tree.MethodNode;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.asm.mcmp.ClassBlockMultipartContainerHandler;\nimport logisticspipes.asm.td.ClassRenderDuctItemsHandler;\nimport logisticspipes.asm.td.ClassTravelingItemHandler;\nimport logisticspipes.utils.ModStatusHelper;\n\npublic class LogisticsClassTransformer implements IClassTransformer {\n\n\tpublic List<String> interfacesToClearA = new ArrayList<>();\n\tpublic List<String> interfacesToClearB = new ArrayList<>();\n\tprivate LaunchClassLoader cl = (LaunchClassLoader) LogisticsClassTransformer.class.getClassLoader();\n\tprivate Field negativeResourceCache;\n\tprivate Field invalidClasses;\n\n\tpublic static LogisticsClassTransformer instance;\n\n\tpublic LogisticsClassTransformer() {\n\t\tLogisticsClassTransformer.instance = this;\n\t\ttry {\n\t\t\tnegativeResourceCache = LaunchClassLoader.class.getDeclaredField(\"negativeResourceCache\");\n\t\t\tnegativeResourceCache.setAccessible(true);\n\t\t} catch (Exception e) {\n\t\t\t//e.printStackTrace();\n\t\t}\n\t\ttry {\n\t\t\tinvalidClasses = LaunchClassLoader.class.getDeclaredField(\"invalidClasses\");\n\t\t\tinvalidClasses.setAccessible(true);\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic byte[] transform(String name, String transformedName, byte[] bytes) {\n\t\t// if dev environment and transform on first class is launched, boot the AT remapper\n\t\tif (LogisticsPipesCoreLoader.isDevelopmentEnvironment() && name.equals(\"net.minecraftforge.fml.common.Loader\")) bootATRemapper();\n\n\t\tThread thread = Thread.currentThread();\n\t\tif (thread.getName().equals(\"Minecraft main thread\") || thread.getName().equals(\"main\") || thread.getName().equals(\"Server thread\")) { //Only clear when called from the main thread to avoid ConcurrentModificationException on start\n\t\t\tclearNegativeInterfaceCache();\n\t\t}\n\t\tif (bytes == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (transformedName.startsWith(\"logisticspipes.\") || transformedName.startsWith(\"net.minecraft\")) {\n\t\t\treturn ParamProfiler.handleClass(applyLPTransforms(transformedName, bytes));\n\t\t}\n\t\tbyte[] tmp = bytes.clone();\n\t\tbytes = applyLPTransforms(transformedName, bytes);\n\t\tif (!Arrays.equals(bytes, tmp)) {\n\t\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\t\tfinal ClassNode node = new ClassNode();\n\t\t\treader.accept(node, 0);\n\t\t\tnode.sourceFile = \"[LP|ASM] \" + node.sourceFile;\n\t\t\tClassWriter writer = new ClassWriter(0);\n\t\t\tnode.accept(writer);\n\t\t\tbytes = writer.toByteArray();\n\t\t}\n\t\treturn ParamProfiler.handleClass(bytes);\n\t}\n\n\tprivate void bootATRemapper() {\n\t\tSystem.err.println(\"Fetching ModAccessTransformers\");\n\t\tfinal List<IClassTransformer> modATs = Launch.classLoader.getTransformers().stream().filter(transformer -> transformer instanceof ModAccessTransformer).collect(Collectors.toList());\n\t\tSystem.err.println(\"Found \" + modATs);\n\t\tif (modATs.size() == 0) return;\n\n\t\tSystem.err.println(\"Inserting missing ATs from classpath\");\n\t\ttry {\n\t\t\treadClasspathATs(modATs);\n\t\t} catch (IllegalStateException e) {\n\t\t\tSystem.err.println(\"Could not inject classpath FMLATs\");\n\t\t\te.printStackTrace();\n\t\t}\n\n\t\tSystem.err.println(\"Booting Logistics Pipes ModAccessTransformerRemapper\");\n\t\tfinal ModAccessTransformerRemapper remapper;\n\t\ttry {\n\t\t\tremapper = new ModAccessTransformerRemapper();\n\t\t} catch (IllegalStateException e) {\n\t\t\tSystem.err.println(\"Could not initialize ModAccessTransformerRemapper:\");\n\t\t\te.printStackTrace();\n\t\t\treturn;\n\t\t}\n\n\t\tmodATs.forEach(remapper::apply);\n\t}\n\n\tprivate void readClasspathATs(List<IClassTransformer> modATs) {\n\t\tfinal Method readMapFile;\n\t\ttry {\n\t\t\treadMapFile = AccessTransformer.class.getDeclaredMethod(\"readMapFile\", String.class);\n\t\t} catch (NoSuchMethodException e) {\n\t\t\tthrow new IllegalStateException(\"Could not find method readMapFile on AccessTransformer class\", e);\n\t\t}\n\t\tfinal boolean wasAccessible = readMapFile.isAccessible();\n\t\tif (!wasAccessible) readMapFile.setAccessible(true);\n\t\ttry {\n\t\t\treadClasspathATsInner(path -> {\n\t\t\t\tfinal IClassTransformer classTransformer = modATs.get(0);\n\t\t\t\ttry {\n\t\t\t\t\treadMapFile.invoke(classTransformer, path);\n\t\t\t\t} catch (IllegalAccessException | InvocationTargetException e) {\n\t\t\t\t\tthrow new IllegalStateException(\"Could not access readMapFile method of \" + classTransformer);\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (IOException e) {\n\t\t\tthrow new IllegalArgumentException(\"IO Error when fetching FMLATs\", e);\n\t\t} finally {\n\t\t\tif (!wasAccessible) readMapFile.setAccessible(false);\n\t\t}\n\t}\n\n\tprivate void readClasspathATsInner(Consumer<String> readMapFile) throws IOException {\n\t\tfinal Enumeration<URL> manifestEntries = Launch.classLoader.findResources(\"META-INF/MANIFEST.MF\");\n\t\twhile (manifestEntries.hasMoreElements()) {\n\t\t\tfinal String accessTransformer;\n\t\t\ttry (InputStream manifestInputStream = manifestEntries.nextElement().openStream()) {\n\t\t\t\tfinal Manifest manifest = new Manifest(manifestInputStream);\n\t\t\t\taccessTransformer = manifest.getMainAttributes().getValue(ModAccessTransformer.FMLAT);\n\t\t\t}\n\t\t\tfinal Enumeration<URL> atEntries = Launch.classLoader.findResources(\"META-INF/\" + accessTransformer);\n\t\t\twhile (atEntries.hasMoreElements()) {\n\t\t\t\treadMapFile.accept(atEntries.nextElement().toString());\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate byte[] applyLPTransforms(String name, byte[] bytes) {\n\t\ttry {\n\t\t\tif (name.equals(\"net.minecraft.tileentity.TileEntity\")) {\n\t\t\t\treturn handleTileEntityClass(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"net.minecraft.item.ItemStack\")) {\n\t\t\t\treturn handleItemStackClass(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"net.minecraftforge.fluids.FluidStack\")) {\n\t\t\t\treturn handleFluidStackClass(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"net.minecraftforge.fluids.Fluid\")) {\n\t\t\t\treturn handleFluidClass(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"mcmultipart.block.BlockMultipartContainer\")) {\n\t\t\t\treturn ClassBlockMultipartContainerHandler.handleClass(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"dan200.computercraft.core.lua.LuaJLuaMachine\")) {\n\t\t\t\treturn handleCCLuaJLuaMachine(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"dan200.computercraft.core.lua.CobaltLuaMachine\")) {\n\t\t\t\treturn handleCCLuaJLuaMachine(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"cofh.thermaldynamics.duct.item.TravelingItem\")) {\n\t\t\t\treturn ClassTravelingItemHandler.handleTravelingItemClass(bytes);\n\t\t\t}\n\t\t\tif (name.equals(\"cofh.thermaldynamics.render.RenderDuctItems\")) {\n\t\t\t\treturn ClassRenderDuctItemsHandler.handleRenderDuctItemsClass(bytes);\n\t\t\t}\n\t\t\tif (!name.startsWith(\"logisticspipes.\")) {\n\t\t\t\treturn bytes;\n\t\t\t}\n\t\t\treturn handleLPTransformation(bytes);\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) { //For better Debugging\n\t\t\t\te.printStackTrace();\n\t\t\t\treturn bytes;\n\t\t\t}\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tpublic void clearNegativeInterfaceCache() {\n\t\t//Remove previously not found Classes to Fix ClassNotFound Exceptions for Interfaces.\n\t\t//TODO remove in future version when everybody starts using a ClassTransformer system for Interfaces.\n\t\tif (negativeResourceCache != null) {\n\t\t\tif (!interfacesToClearA.isEmpty()) {\n\t\t\t\thandleField(negativeResourceCache, interfacesToClearA);\n\t\t\t}\n\t\t}\n\t\tif (invalidClasses != null) {\n\t\t\tif (!interfacesToClearB.isEmpty()) {\n\t\t\t\thandleField(invalidClasses, interfacesToClearB);\n\t\t\t}\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void handleField(Field field, List<String> toClear) {\n\t\ttry {\n\t\t\tSet<String> set = (Set<String>) field.get(cl);\n\t\t\tIterator<String> it = toClear.iterator();\n\t\t\twhile (it.hasNext()) {\n\t\t\t\tString content = it.next();\n\t\t\t\tif (set.contains(content)) {\n\t\t\t\t\tset.remove(content);\n\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) { //For better Debugging\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate byte[] handleLPTransformation(byte[] bytes) {\n\t\tfinal ClassNode node = new ClassNode();\n\t\tClassReader reader = new ClassReader(bytes);\n\t\treader.accept(node, 0);\n\t\tboolean changed = false;\n\t\tif (node.visibleAnnotations != null) {\n\t\t\tfor (AnnotationNode a : node.visibleAnnotations) {\n\t\t\t\tif (a.desc.equals(\"Llogisticspipes/asm/ModDependentInterface;\")) {\n\t\t\t\t\tif (a.values.size() == 4 && a.values.get(0).equals(\"modId\") && a.values.get(2).equals(\"interfacePath\")) {\n\t\t\t\t\t\tList<String> modId = (List<String>) a.values.get(1);\n\t\t\t\t\t\tList<String> interfacePath = (List<String>) a.values.get(3);\n\t\t\t\t\t\tif (modId.size() != interfacePath.size()) {\n\t\t\t\t\t\t\tthrow new RuntimeException(\"The Arrays have to be of the same size.\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (int i = 0; i < modId.size(); i++) {\n\t\t\t\t\t\t\tif (!ModStatusHelper.isModLoaded(modId.get(i))) {\n\t\t\t\t\t\t\t\tinterfacesToClearA.add(interfacePath.get(i));\n\t\t\t\t\t\t\t\tinterfacesToClearB.add(interfacePath.get(i));\n\t\t\t\t\t\t\t\tfor (String inter : node.interfaces) {\n\t\t\t\t\t\t\t\t\tif (inter.replace(\"/\", \".\").equals(interfacePath.get(i))) {\n\t\t\t\t\t\t\t\t\t\tnode.interfaces.remove(inter);\n\t\t\t\t\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Can't parse the annotations correctly\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tList<MethodNode> methodsToRemove = new ArrayList<>();\n\t\tfor (MethodNode m : node.methods) {\n\t\t\tif (m.visibleAnnotations != null) {\n\t\t\t\tfor (AnnotationNode a : m.visibleAnnotations) {\n\t\t\t\t\tif (a.desc.equals(\"Llogisticspipes/asm/ModDependentMethod;\")) {\n\t\t\t\t\t\tif (a.values.size() == 2 && a.values.get(0).equals(\"modId\")) {\n\t\t\t\t\t\t\tString modId = a.values.get(1).toString();\n\t\t\t\t\t\t\tif (!ModStatusHelper.isModLoaded(modId)) {\n\t\t\t\t\t\t\t\tmethodsToRemove.add(m);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Can't parse the annotation correctly\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (a.desc.equals(\"Llogisticspipes/asm/ClientSideOnlyMethodContent;\")) {\n\t\t\t\t\t\tif (FMLCommonHandler.instance().getSide().equals(Side.SERVER)) {\n\t\t\t\t\t\t\tm.instructions.clear();\n\t\t\t\t\t\t\tm.localVariables.clear();\n\t\t\t\t\t\t\tm.tryCatchBlocks.clear();\n\t\t\t\t\t\t\tm.visitCode();\n\t\t\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\t\t\tm.visitLabel(l0);\n\t\t\t\t\t\t\tm.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/LogisticsASMHookClass\", \"callingClearedMethod\", \"()V\");\n\t\t\t\t\t\t\tLabel l1 = new Label();\n\t\t\t\t\t\t\tm.visitLabel(l1);\n\t\t\t\t\t\t\tm.visitInsn(Opcodes.RETURN);\n\t\t\t\t\t\t\tLabel l2 = new Label();\n\t\t\t\t\t\t\tm.visitLabel(l2);\n\t\t\t\t\t\t\tm.visitLocalVariable(\"this\", \"Llogisticspipes/network/packets/DummyPacket;\", null, l0, l2, 0);\n\t\t\t\t\t\t\tm.visitLocalVariable(\"player\", \"Lnet/minecraft/entity/player/EntityPlayer;\", null, l0, l2, 1);\n\t\t\t\t\t\t\tm.visitMaxs(0, 2);\n\t\t\t\t\t\t\tm.visitEnd();\n\t\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (a.desc.equals(\"Llogisticspipes/asm/ModDependentMethodName;\")) {\n\t\t\t\t\t\tif (a.values.size() == 6 && a.values.get(0).equals(\"modId\") && a.values.get(2).equals(\"newName\") && a.values.get(4).equals(\"version\")) {\n\t\t\t\t\t\t\tString modId = a.values.get(1).toString();\n\t\t\t\t\t\t\tfinal String newName = a.values.get(3).toString();\n\t\t\t\t\t\t\tfinal String version = a.values.get(5).toString();\n\t\t\t\t\t\t\tboolean loaded = ModStatusHelper.isModLoaded(modId);\n\t\t\t\t\t\t\tif (loaded && !version.equals(\"\")) {\n\t\t\t\t\t\t\t\tModContainer mod = Loader.instance().getIndexedModList().get(modId);\n\t\t\t\t\t\t\t\tif (mod != null) {\n\t\t\t\t\t\t\t\t\tVersionRange range = VersionParser.parseRange(version);\n\t\t\t\t\t\t\t\t\tArtifactVersion artifactVersion = new DefaultArtifactVersion(\"Version\", mod.getVersion());\n\t\t\t\t\t\t\t\t\tloaded = range.containsVersion(artifactVersion);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tloaded = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\t\t\tfinal String oldName = m.name;\n\t\t\t\t\t\t\t\tm.name = newName;\n\t\t\t\t\t\t\t\tMethodNode newM = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\t\t\tpublic void visitMethodInsn(int opcode, String owner, String name, String desc) {\n\t\t\t\t\t\t\t\t\t\tif (name.equals(oldName) && owner.equals(node.superName)) {\n\t\t\t\t\t\t\t\t\t\t\tsuper.visitMethodInsn(opcode, owner, newName, desc);\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tsuper.visitMethodInsn(opcode, owner, name, desc);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tm.accept(newM);\n\t\t\t\t\t\t\t\tnode.methods.set(node.methods.indexOf(m), newM);\n\t\t\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Can't parse the annotation correctly\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (MethodNode m : methodsToRemove) {\n\t\t\tnode.methods.remove(m);\n\t\t}\n\t\tList<FieldNode> fieldsToRemove = new ArrayList<>();\n\t\tfor (FieldNode f : node.fields) {\n\t\t\tif (f.visibleAnnotations != null) {\n\t\t\t\tfor (AnnotationNode a : f.visibleAnnotations) {\n\t\t\t\t\tif (a.desc.equals(\"Llogisticspipes/asm/ModDependentField;\")) {\n\t\t\t\t\t\tif (a.values.size() == 2 && a.values.get(0).equals(\"modId\")) {\n\t\t\t\t\t\t\tString modId = a.values.get(1).toString();\n\t\t\t\t\t\t\tif (!ModStatusHelper.isModLoaded(modId)) {\n\t\t\t\t\t\t\t\tfieldsToRemove.add(f);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Can't parse the annotation correctly\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (FieldNode f : fieldsToRemove) {\n\t\t\tnode.fields.remove(f);\n\t\t}\n\t\tif (!changed && methodsToRemove.isEmpty() && fieldsToRemove.isEmpty()) {\n\t\t\treturn bytes;\n\t\t}\n\t\tClassWriter writer = new ClassWriter(0);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n\n\tprivate byte[] handleCCLuaJLuaMachine(byte[] bytes) {\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\t\tfor (MethodNode m : node.methods) {\n\t\t\tif (m.name.equals(\"wrapLuaObject\") && m.desc.equals(\"(Ldan200/computercraft/api/lua/ILuaObject;)Lorg/luaj/vm2/LuaTable;\")) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitInsn(int opcode) {\n\t\t\t\t\t\tif (opcode == Opcodes.ARETURN) {\n\t\t\t\t\t\t\tsuper.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\t\tsuper.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/proxy/cc/LPASMHookCC\", \"onCCWrappedILuaObject\", \"(Lorg/luaj/vm2/LuaTable;Ldan200/computercraft/api/lua/ILuaObject;)Lorg/luaj/vm2/LuaTable;\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsuper.visitInsn(opcode);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitCode() {\n\t\t\t\t\t\tsuper.visitCode();\n\t\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\t\tsuper.visitLabel(l0);\n\t\t\t\t\t\tsuper.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\tsuper.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/proxy/cc/LPASMHookCC\", \"handleCCWrappedILuaObject\", \"(Ldan200/computercraft/api/lua/ILuaObject;)Z\");\n\t\t\t\t\t\tLabel l1 = new Label();\n\t\t\t\t\t\tsuper.visitJumpInsn(Opcodes.IFEQ, l1);\n\t\t\t\t\t\tLabel l2 = new Label();\n\t\t\t\t\t\tsuper.visitLabel(l2);\n\t\t\t\t\t\tsuper.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\tsuper.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/proxy/cc/LPASMHookCC\", \"returnCCWrappedILuaObject\", \"(Ldan200/computercraft/api/lua/ILuaObject;)Lorg/luaj/vm2/LuaTable;\");\n\t\t\t\t\t\tsuper.visitInsn(Opcodes.ARETURN);\n\t\t\t\t\t\tsuper.visitLabel(l1);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t\tif (m.name.equals(\"toObject\") && (m.desc.equals(\"(Lorg/luaj/vm2/LuaValue;)Ljava/lang/Object;\") || m.desc.equals(\"(Lorg/luaj/vm2/LuaValue;Ljava/util/Map;)Ljava/lang/Object;\"))) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\tboolean added = false;\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitLineNumber(int line, Label start) {\n\t\t\t\t\t\tif (!added) {\n\t\t\t\t\t\t\tadded = true;\n\t\t\t\t\t\t\tsuper.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\t\tsuper.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/proxy/cc/LPASMHookCC\", \"handleCCToObject\", \"(Lorg/luaj/vm2/LuaValue;)Z\");\n\t\t\t\t\t\t\tstart = new Label();\n\t\t\t\t\t\t\tsuper.visitJumpInsn(Opcodes.IFEQ, start);\n\t\t\t\t\t\t\tLabel l5 = new Label();\n\t\t\t\t\t\t\tsuper.visitLabel(l5);\n\t\t\t\t\t\t\tsuper.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\t\tsuper.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/proxy/cc/LPASMHookCC\", \"returnCCToObject\", \"(Lorg/luaj/vm2/LuaValue;)Ljava/lang/Object;\");\n\t\t\t\t\t\t\tsuper.visitInsn(Opcodes.ARETURN);\n\t\t\t\t\t\t\tsuper.visitLabel(start);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsuper.visitLineNumber(line, start);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t}\n\t\tClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {\n\n\t\t\tprotected String getCommonSuperClass(final String type1, final String type2) {\n\t\t\t\tClass<?> c, d;\n\t\t\t\tClassLoader classLoader = Launch.classLoader; // Change Classloader to the MC one\n\t\t\t\ttry {\n\t\t\t\t\tc = Class.forName(type1.replace('/', '.'), false, classLoader);\n\t\t\t\t\td = Class.forName(type2.replace('/', '.'), false, classLoader);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tthrow new RuntimeException(e.toString());\n\t\t\t\t}\n\t\t\t\tif (c.isAssignableFrom(d)) {\n\t\t\t\t\treturn type1;\n\t\t\t\t}\n\t\t\t\tif (d.isAssignableFrom(c)) {\n\t\t\t\t\treturn type2;\n\t\t\t\t}\n\t\t\t\tif (c.isInterface() || d.isInterface()) {\n\t\t\t\t\treturn \"java/lang/Object\";\n\t\t\t\t} else {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tc = c.getSuperclass();\n\t\t\t\t\t} while (!c.isAssignableFrom(d));\n\t\t\t\t\treturn c.getName().replace('.', '/');\n\t\t\t\t}\n\t\t\t}\n\n\t\t};\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n\n\tprivate byte[] handleTileEntityClass(byte[] bytes) {\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\t\tnode.interfaces.add(\"logisticspipes/asm/te/ILPTEInformation\");\n\t\tnode.visitField(Opcodes.ACC_PRIVATE, \"informationObjectLogisticsPipes\", \"Llogisticspipes/asm/te/LPTileEntityObject;\", null, null);\n\t\tfor (MethodNode m : node.methods) {\n\t\t\tif (m.name.equals(\"validate\") || m.name.equals(\"func_145829_t\") || (m.name.equals(\"A\") && m.desc.equals(\"()V\"))) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitCode() {\n\t\t\t\t\t\tsuper.visitCode();\n\t\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\t\tvisitLabel(l0);\n\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\t\tthis.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/LogisticsASMHookClass\", \"validate\", \"(Lnet/minecraft/tileentity/TileEntity;)V\");\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t\tif (m.name.equals(\"invalidate\") || m.name.equals(\"func_145843_s\") || (m.name.equals(\"z\") && m.desc.equals(\"()V\"))) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitCode() {\n\t\t\t\t\t\tsuper.visitCode();\n\t\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\t\tvisitLabel(l0);\n\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\t\tthis.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/LogisticsASMHookClass\", \"invalidate\", \"(Lnet/minecraft/tileentity/TileEntity;)V\");\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t}\n\t\tMethodVisitor mv;\n\t\t{\n\t\t\tmv = node.visitMethod(Opcodes.ACC_PUBLIC, \"getLPTileEntityObject\", \"()Llogisticspipes/asm/te/LPTileEntityObject;\", null, null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, \"net/minecraft/tileentity/TileEntity\", \"informationObjectLogisticsPipes\", \"Llogisticspipes/asm/te/LPTileEntityObject;\");\n\t\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitMaxs(1, 1);\n\t\t\tmv.visitEnd();\n\t\t}\n\t\t{\n\t\t\tmv = node.visitMethod(Opcodes.ACC_PUBLIC, \"setLPTileEntityObject\", \"(Llogisticspipes/asm/te/LPTileEntityObject;)V\", null, null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, \"net/minecraft/tileentity/TileEntity\", \"informationObjectLogisticsPipes\", \"Llogisticspipes/asm/te/LPTileEntityObject;\");\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\tLabel l2 = new Label();\n\t\t\tmv.visitLabel(l2);\n\t\t\tmv.visitMaxs(2, 2);\n\t\t\tmv.visitEnd();\n\t\t}\n\t\tClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n\n\tprivate byte[] handleItemStackClass(byte[] bytes) {\n\t\treturn addAddInfoPart(bytes, \"net/minecraft/item/ItemStack\");\n\t}\n\n\tprivate byte[] handleFluidStackClass(byte[] bytes) {\n\t\treturn addAddInfoPart(bytes, \"net/minecraftforge/fluids/FluidStack\");\n\t}\n\n\tprivate byte[] handleFluidClass(byte[] bytes) {\n\t\treturn addAddInfoPart(bytes, \"net/minecraftforge/fluids/Fluid\");\n\t}\n\n\tprivate byte[] addAddInfoPart(byte[] bytes, String className) {\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\n\t\tnode.interfaces.add(\"logisticspipes/asm/addinfo/IAddInfoProvider\");\n\n\t\t{\n\t\t\tFieldVisitor fv = node.visitField(Opcodes.ACC_PRIVATE, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\", \"Ljava/util/ArrayList<Llogisticspipes/asm/addinfo/IAddInfo;>;\", null);\n\t\t\tfv.visitEnd();\n\t\t}\n\n\t\tMethodVisitor mv;\n\t\t{\n\t\t\tmv = node.visitMethod(Opcodes.ACC_PUBLIC, \"getLogisticsPipesAddInfo\", \"(Ljava/lang/Class;)Llogisticspipes/asm/addinfo/IAddInfo;\", \"<T::Llogisticspipes/asm/addinfo/IAddInfo;>(Ljava/lang/Class<TT;>;)TT;\", null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitLineNumber(11, l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IFNONNULL, l1);\n\t\t\tLabel l2 = new Label();\n\t\t\tmv.visitLabel(l2);\n\t\t\tmv.visitLineNumber(12, l2);\n\t\t\tmv.visitInsn(Opcodes.ACONST_NULL);\n\t\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitLineNumber(14, l1);\n\t\t\tmv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/util/ArrayList\", \"iterator\", \"()Ljava/util/Iterator;\", false);\n\t\t\tmv.visitVarInsn(Opcodes.ASTORE, 2);\n\t\t\tLabel l3 = new Label();\n\t\t\tmv.visitLabel(l3);\n\t\t\tmv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { \"java/util/Iterator\" }, 0, null);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 2);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEINTERFACE, \"java/util/Iterator\", \"hasNext\", \"()Z\", true);\n\t\t\tLabel l4 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IFEQ, l4);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 2);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEINTERFACE, \"java/util/Iterator\", \"next\", \"()Ljava/lang/Object;\", true);\n\t\t\tmv.visitTypeInsn(Opcodes.CHECKCAST, \"logisticspipes/asm/addinfo/IAddInfo\");\n\t\t\tmv.visitVarInsn(Opcodes.ASTORE, 3);\n\t\t\tLabel l5 = new Label();\n\t\t\tmv.visitLabel(l5);\n\t\t\tmv.visitLineNumber(15, l5);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 3);\n\t\t\tLabel l6 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IFNONNULL, l6);\n\t\t\tmv.visitJumpInsn(Opcodes.GOTO, l3);\n\t\t\tmv.visitLabel(l6);\n\t\t\tmv.visitLineNumber(16, l6);\n\t\t\tmv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { \"logisticspipes/asm/addinfo/IAddInfo\" }, 0, null);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 3);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/lang/Object\", \"getClass\", \"()Ljava/lang/Class;\", false);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tLabel l7 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IF_ACMPNE, l7);\n\t\t\tLabel l8 = new Label();\n\t\t\tmv.visitLabel(l8);\n\t\t\tmv.visitLineNumber(17, l8);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 3);\n\t\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\t\tmv.visitLabel(l7);\n\t\t\tmv.visitLineNumber(19, l7);\n\t\t\tmv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);\n\t\t\tmv.visitJumpInsn(Opcodes.GOTO, l3);\n\t\t\tmv.visitLabel(l4);\n\t\t\tmv.visitLineNumber(20, l4);\n\t\t\tmv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);\n\t\t\tmv.visitInsn(Opcodes.ACONST_NULL);\n\t\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\t\tLabel l9 = new Label();\n\t\t\tmv.visitLabel(l9);\n\t\t\tmv.visitLocalVariable(\"info\", \"Llogisticspipes/asm/addinfo/IAddInfo;\", null, l5, l7, 3);\n\t\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l0, l9, 0);\n\t\t\tmv.visitLocalVariable(\"clazz\", \"Ljava/lang/Class;\", \"Ljava/lang/Class<TT;>;\", l0, l9, 1);\n\t\t\tmv.visitMaxs(2, 4);\n\t\t\tmv.visitEnd();\n\t\t}\n\t\t{\n\t\t\tmv = node.visitMethod(Opcodes.ACC_PUBLIC, \"setLogisticsPipesAddInfo\", \"(Llogisticspipes/asm/addinfo/IAddInfo;)V\", null, null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitLineNumber(25, l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IFNONNULL, l1);\n\t\t\tLabel l2 = new Label();\n\t\t\tmv.visitLabel(l2);\n\t\t\tmv.visitLineNumber(26, l2);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitTypeInsn(Opcodes.NEW, \"java/util/ArrayList\");\n\t\t\tmv.visitInsn(Opcodes.DUP);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKESPECIAL, \"java/util/ArrayList\", \"<init>\", \"()V\", false);\n\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitLineNumber(28, l1);\n\t\t\tmv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\n\t\t\tmv.visitInsn(Opcodes.ICONST_0);\n\t\t\tmv.visitVarInsn(Opcodes.ISTORE, 2);\n\t\t\tLabel l3 = new Label();\n\t\t\tmv.visitLabel(l3);\n\t\t\tmv.visitFrame(Opcodes.F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null);\n\t\t\tmv.visitVarInsn(Opcodes.ILOAD, 2);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/util/ArrayList\", \"size\", \"()I\", false);\n\t\t\tLabel l4 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IF_ICMPGE, l4);\n\t\t\tLabel l5 = new Label();\n\t\t\tmv.visitLabel(l5);\n\t\t\tmv.visitLineNumber(29, l5);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitVarInsn(Opcodes.ILOAD, 2);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/util/ArrayList\", \"get\", \"(I)Ljava/lang/Object;\", false);\n\t\t\tLabel l6 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.IFNONNULL, l6);\n\t\t\tLabel l7 = new Label();\n\t\t\tmv.visitJumpInsn(Opcodes.GOTO, l7);\n\t\t\tmv.visitLabel(l6);\n\t\t\tmv.visitLineNumber(30, l6);\n\t\t\tmv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitVarInsn(Opcodes.ILOAD, 2);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/util/ArrayList\", \"get\", \"(I)Ljava/lang/Object;\", false);\n\t\t\tmv.visitTypeInsn(Opcodes.CHECKCAST, \"logisticspipes/asm/addinfo/IAddInfo\");\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/lang/Object\", \"getClass\", \"()Ljava/lang/Class;\", false);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/lang/Object\", \"getClass\", \"()Ljava/lang/Class;\", false);\n\t\t\tmv.visitJumpInsn(Opcodes.IF_ACMPNE, l7);\n\t\t\tLabel l8 = new Label();\n\t\t\tmv.visitLabel(l8);\n\t\t\tmv.visitLineNumber(31, l8);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitVarInsn(Opcodes.ILOAD, 2);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/util/ArrayList\", \"set\", \"(ILjava/lang/Object;)Ljava/lang/Object;\", false);\n\t\t\tmv.visitInsn(Opcodes.POP);\n\t\t\tLabel l9 = new Label();\n\t\t\tmv.visitLabel(l9);\n\t\t\tmv.visitLineNumber(32, l9);\n\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\tmv.visitLabel(l7);\n\t\t\tmv.visitLineNumber(28, l7);\n\t\t\tmv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\n\t\t\tmv.visitIincInsn(2, 1);\n\t\t\tmv.visitJumpInsn(Opcodes.GOTO, l3);\n\t\t\tmv.visitLabel(l4);\n\t\t\tmv.visitLineNumber(35, l4);\n\t\t\tmv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"logisticsPipesAdditionalInformation\", \"Ljava/util/ArrayList;\");\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/util/ArrayList\", \"add\", \"(Ljava/lang/Object;)Z\", false);\n\t\t\tmv.visitInsn(Opcodes.POP);\n\t\t\tLabel l10 = new Label();\n\t\t\tmv.visitLabel(l10);\n\t\t\tmv.visitLineNumber(36, l10);\n\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\tLabel l11 = new Label();\n\t\t\tmv.visitLabel(l11);\n\t\t\tmv.visitLocalVariable(\"i\", \"I\", null, l3, l4, 2);\n\t\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l0, l11, 0);\n\t\t\tmv.visitLocalVariable(\"info\", \"Llogisticspipes/asm/addinfo/IAddInfo;\", null, l0, l11, 1);\n\t\t\tmv.visitMaxs(3, 3);\n\t\t\tmv.visitEnd();\n\t\t}\n\n\t\tClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/LogisticsPipesClassInjector.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeSet;\n\nimport net.minecraft.launchwrapper.IClassTransformer;\nimport net.minecraft.launchwrapper.Launch;\nimport net.minecraft.launchwrapper.LaunchClassLoader;\n\nimport com.google.common.io.BaseEncoding;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.tree.AnnotationNode;\nimport org.objectweb.asm.tree.ClassNode;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\nimport logisticspipes.proxy.opencomputers.asm.ClassCreator;\nimport logisticspipes.utils.ModStatusHelper;\n\npublic class LogisticsPipesClassInjector implements IClassTransformer {\n\n\tprivate Field fResourceCache;\n\tprivate Boolean isObfEnv = null;\n\n\tpublic LogisticsPipesClassInjector() throws NoSuchFieldException, SecurityException {\n\t\tfResourceCache = LaunchClassLoader.class.getDeclaredField(\"resourceCache\");\n\t\tfResourceCache.setAccessible(true);\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic byte[] transform(String name, String transformedName, byte[] bytes) {\n\t\tif (bytes != null) {\n\t\t\tif (name.startsWith(\"logisticspipes.\")) {\n\t\t\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\t\t\tfinal ClassNode node = new ClassNode();\n\t\t\t\treader.accept(node, 0);\n\t\t\t\tif (node.visibleAnnotations != null) {\n\t\t\t\t\tfor (AnnotationNode a : node.visibleAnnotations) {\n\t\t\t\t\t\tif (a.desc.equals(\"Llogisticspipes/asm/ModVersionedClass;\")) {\n\t\t\t\t\t\t\tif (a.values.size() == 8 && a.values.get(0).equals(\"modId\") && a.values.get(2).equals(\"version\") && a.values.get(4).equals(\"classData\") && a.values.get(6).equals(\"classDataDev\")) {\n\t\t\t\t\t\t\t\tString modId = a.values.get(1).toString();\n\t\t\t\t\t\t\t\tString version = a.values.get(3).toString();\n\t\t\t\t\t\t\t\tString classData = a.values.get(5).toString();\n\t\t\t\t\t\t\t\tString classDataDev = a.values.get(7).toString();\n\t\t\t\t\t\t\t\tif (ModStatusHelper.isModLoaded(modId) && !ModStatusHelper.isModVersionEqualsOrHigher(modId, version)) {\n\t\t\t\t\t\t\t\t\tif (isObfEnv == null) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tisObfEnv = (Class.forName(\"net.minecraft.world.World\").getDeclaredField(\"chunkProvider\") == null);\n\t\t\t\t\t\t\t\t\t\t} catch (Throwable e) {\n\t\t\t\t\t\t\t\t\t\t\tisObfEnv = true;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbytes = transform(name, transformedName, BaseEncoding.base64().decode(isObfEnv ? classData : classDataDev));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Can't parse the annotations correctly\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn bytes;\n\t\t}\n\t\ttry {\n\t\t\tif (name.startsWith(\"logisticspipes.proxy.opencomputers.asm.BaseWrapperClass$\") && name.endsWith(\"$OpenComputersWrapper\")) {\n\t\t\t\tString correctName = name.substring(56, name.length() - 21);\n\t\t\t\tClass<?> clazz = Launch.classLoader.findClass(correctName);\n\t\t\t\tbytes = ClassCreator.getWrappedClassAsBytes(CCObjectWrapper.getWrapperInformation(clazz), clazz.getName());\n\t\t\t\tSet<String> set = new TreeSet<>();\n\t\t\t\tset.add(name);\n\t\t\t\tLaunch.classLoader.clearNegativeEntries(set);\n\t\t\t\tMap<String, byte[]> map = (Map<String, byte[]>) fResourceCache.get(Launch.classLoader);\n\t\t\t\tmap.put(name, bytes);\n\t\t\t\treturn bytes;\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) { // For better Debugging\n\t\t\t\te.printStackTrace();\n\t\t\t\treturn bytes;\n\t\t\t}\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\treturn bytes;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/LogisticsPipesCoreLoader.java",
    "content": "package logisticspipes.asm;\n\nimport java.util.Map;\n\nimport net.minecraft.launchwrapper.Launch;\n\nimport net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;\n\nimport lombok.Getter;\n\n@IFMLLoadingPlugin.MCVersion(\"1.12.2\")\n//@IFMLLoadingPlugin.SortingIndex(1001) TODO: For next MC update. Changing this now, will change ASM check sums as well.\npublic class LogisticsPipesCoreLoader implements IFMLLoadingPlugin {\n\n\t@Getter\n\tprivate static boolean coremodLoaded = false;\n\tprivate static boolean developmentEnvironment = false;\n\n\tpublic LogisticsPipesCoreLoader() throws Exception {\n\t\tLaunch.classLoader.addTransformerExclusion(\"logisticspipes.asm.\");\n\t\tcoremodLoaded = true;\n\t}\n\n\t@Override\n\tpublic String[] getASMTransformerClass() {\n\t\treturn new String[] { \"logisticspipes.asm.LogisticsClassTransformer\" };\n\t}\n\n\t@Override\n\tpublic String getModContainerClass() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String getSetupClass() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void injectData(Map<String, Object> data) {\n\t\tif (data.containsKey(\"runtimeDeobfuscationEnabled\")) {\n\t\t\tdevelopmentEnvironment = !((Boolean) data.get(\"runtimeDeobfuscationEnabled\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getAccessTransformerClass() {\n\t\treturn null;\n\t}\n\n\tpublic static boolean isDevelopmentEnvironment() {\n\t\treturn developmentEnvironment;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ModAccessTransformerRemapper.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.launchwrapper.IClassTransformer;\n\nimport net.minecraftforge.fml.common.asm.transformers.AccessTransformer;\nimport net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;\n\nimport com.google.common.collect.Multimap;\n\npublic class ModAccessTransformerRemapper {\n\n\tprivate final Map<String, Map<String, String>> fieldMappings;\n\tprivate final Map<String, Map<String, String>> methodMappings;\n\tprivate final Field modifiersField;\n\n\tprivate Field modifierDesc;\n\tprivate Field modifierName;\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic ModAccessTransformerRemapper() {\n\t\ttry {\n\t\t\tfinal Field rawFieldMaps = FMLDeobfuscatingRemapper.class.getDeclaredField(\"rawFieldMaps\");\n\t\t\tfinal boolean wasAccessible = rawFieldMaps.isAccessible();\n\t\t\tif (!wasAccessible) rawFieldMaps.setAccessible(true);\n\t\t\tfieldMappings = (Map<String, Map<String, String>>) rawFieldMaps.get(FMLDeobfuscatingRemapper.INSTANCE);\n\t\t\tif (!wasAccessible) rawFieldMaps.setAccessible(false);\n\t\t} catch (IllegalAccessException | NoSuchFieldException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access rawFieldMaps of FMLDeobfuscatingRemapper\", e);\n\t\t}\n\n\t\ttry {\n\t\t\tfinal Field rawMethodMaps = FMLDeobfuscatingRemapper.class.getDeclaredField(\"rawMethodMaps\");\n\t\t\tfinal boolean wasAccessible = rawMethodMaps.isAccessible();\n\t\t\tif (!wasAccessible) rawMethodMaps.setAccessible(true);\n\t\t\tmethodMappings = (Map<String, Map<String, String>>) rawMethodMaps.get(FMLDeobfuscatingRemapper.INSTANCE);\n\t\t\tif (!wasAccessible) rawMethodMaps.setAccessible(false);\n\t\t} catch (IllegalAccessException | NoSuchFieldException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access rawMethodMaps of FMLDeobfuscatingRemapper\", e);\n\t\t}\n\n\t\ttry {\n\t\t\tmodifiersField = AccessTransformer.class.getDeclaredField(\"modifiers\");\n\t\t} catch (NoSuchFieldException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access modifiers field of AccessTransformer\", e);\n\t\t}\n\t}\n\n\tpublic void apply(IClassTransformer modAT) {\n\t\tfinal Multimap<String, ?> modifiersMap = getModifiers(modAT);\n\t\tif (modifiersMap.isEmpty()) return;\n\n\t\tmodifiersMap.forEach(this::applySingleModifier);\n\n\t\tif (modifierDesc != null) {\n\t\t\tmodifierDesc.setAccessible(false);\n\t\t\tmodifierDesc = null;\n\t\t}\n\t\tif (modifierName != null) {\n\t\t\tmodifierName.setAccessible(false);\n\t\t\tmodifierName = null;\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\t@Nonnull\n\tprivate Multimap<String, ?> getModifiers(IClassTransformer modAT) {\n\t\tfinal boolean wasAccessible = modifiersField.isAccessible();\n\t\tif (!wasAccessible) modifiersField.setAccessible(true);\n\t\tfinal Multimap<String, ?> modifiersMap; // String to AccessTransformer.Modifier\n\t\ttry {\n\t\t\tmodifiersMap = (Multimap<String, ?>) modifiersField.get(modAT);\n\t\t} catch (IllegalAccessException | ClassCastException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access modifiers field of \" + modAT, e);\n\t\t} finally {\n\t\t\tif (!wasAccessible) modifiersField.setAccessible(false);\n\t\t}\n\t\treturn modifiersMap;\n\t}\n\n\tprivate void applySingleModifier(String className, Object modifier) {\n\t\tfinal String classKey = className.replaceAll(\"\\\\.\", \"/\");\n\t\tfinal String desc, name;\n\t\ttry {\n\t\t\tname = getName(modifier);\n\t\t\tif (name.equals(\"*\")) return; // doesn't need mapping\n\t\t\tdesc = getDesc(modifier);\n\t\t} catch (RuntimeException e) {\n\t\t\te.printStackTrace();\n\t\t\treturn;\n\t\t}\n\n\t\tif (desc.isEmpty() && fieldMappings.containsKey(classKey)) {\n\t\t\tfinal Map<String, String> classFieldMappings = fieldMappings.get(classKey);\n\t\t\tclassFieldMappings.keySet().stream()\n\t\t\t\t\t.filter(obfNameWithType -> obfNameWithType.startsWith(name + \":\"))\n\t\t\t\t\t.findAny()\n\t\t\t\t\t.ifPresent(obfNameWithType -> {\n\t\t\t\t\t\tfinal String newName = classFieldMappings.get(obfNameWithType);\n\t\t\t\t\t\tSystem.out.printf(\"Remapping class %s field %s -> %s%n\", className, name, newName);\n\t\t\t\t\t\tsetName(modifier, newName);\n\t\t\t\t\t});\n\t\t} else if (methodMappings.containsKey(classKey)) {\n\t\t\tfinal Map<String, String> classMethodMappings = methodMappings.get(classKey);\n\t\t\tclassMethodMappings.keySet().stream()\n\t\t\t\t\t.filter(obfNameWithType -> obfNameWithType.startsWith(name + \"(\") && obfNameWithType.endsWith(desc))\n\t\t\t\t\t.findAny()\n\t\t\t\t\t.ifPresent(obfNameWithType -> {\n\t\t\t\t\t\tfinal String newName = classMethodMappings.get(obfNameWithType);\n\t\t\t\t\t\tSystem.out.printf(\"Remapping class %s method %s %s -> %s%n\", className, name, desc, newName);\n\t\t\t\t\t\tsetName(modifier, newName);\n\t\t\t\t\t});\n\t\t}\n\t}\n\n\tprivate String getDesc(Object modifier) {\n\t\tObjects.requireNonNull(modifier, \"Modifier may not be null\");\n\t\tensureModifierDesc(modifier);\n\t\ttry {\n\t\t\treturn (String) modifierDesc.get(modifier);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access desc field\", e);\n\t\t}\n\t}\n\n\tprivate void ensureModifierDesc(@Nonnull Object modifier) {\n\t\tif (modifierDesc == null) {\n\t\t\ttry {\n\t\t\t\tmodifierDesc = modifier.getClass().getDeclaredField(\"desc\");\n\t\t\t} catch (NoSuchFieldException e) {\n\t\t\t\tthrow new IllegalStateException(\"Could not find desc field\", e);\n\t\t\t}\n\t\t}\n\t\tif (!modifierDesc.isAccessible()) modifierDesc.setAccessible(true);\n\t}\n\n\tprivate String getName(Object modifier) {\n\t\tObjects.requireNonNull(modifier, \"Modifier may not be null\");\n\t\tensureModifierName(modifier);\n\t\ttry {\n\t\t\treturn (String) modifierName.get(modifier);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access name field\", e);\n\t\t}\n\t}\n\n\tprivate void setName(Object modifier, String newName) {\n\t\tObjects.requireNonNull(modifier, \"Modifier may not be null\");\n\t\tensureModifierName(modifier);\n\t\ttry {\n\t\t\tmodifierName.set(modifier, newName);\n\t\t} catch (IllegalAccessException e) {\n\t\t\tthrow new IllegalStateException(\"Could not access name field\", e);\n\t\t}\n\t}\n\n\tprivate void ensureModifierName(@Nonnull Object modifier) {\n\t\tif (modifierName == null) {\n\t\t\ttry {\n\t\t\t\tmodifierName = modifier.getClass().getDeclaredField(\"name\");\n\n\t\t\t} catch (NoSuchFieldException e) {\n\t\t\t\tthrow new IllegalStateException(\"Could not find name field\", e);\n\t\t\t}\n\t\t}\n\t\tif (!modifierName.isAccessible()) modifierName.setAccessible(true);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ModDependentField.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.FIELD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ModDependentField {\n\n\tString modId();\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ModDependentInterface.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ModDependentInterface {\n\n\tString[] modId();\n\n\tString[] interfacePath();\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ModDependentMethod.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ModDependentMethod {\n\n\tString modId();\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ModDependentMethodName.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ModDependentMethodName {\n\n\tString modId();\n\n\tString newName();\n\n\tString version();\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ModVersionedClass.java",
    "content": "package logisticspipes.asm;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ModVersionedClass {\n\n\tString modId();\n\n\tString version(); // Everything below this version will cause the fallback\n\n\tString classData(); // Fallback class data Base64 encoded\n\n\tString classDataDev(); // Fallbacl class data Baste64 encoded for dev\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/ParamProfiler.java",
    "content": "package logisticspipes.asm;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Stack;\nimport java.util.WeakHashMap;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.Getter;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.MethodNode;\n\npublic class ParamProfiler {\n\n\tprivate static final boolean isActive = false;\n\n\tprivate static volatile long minMethodId = 0;\n\n\tpublic static byte[] handleClass(byte[] bytes) {\n\t\tif (!isActive) return bytes;\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\t\tfinal String className = node.name;\n\t\tfor (final MethodNode m : node.methods) {\n\t\t\tfinal String methodName = m.name;\n\t\t\tfinal String methodDesc = m.desc;\n\t\t\tfinal boolean isConst = methodName.contains(\"<\") || methodName.contains(\">\");\n\t\t\tif (isConst) continue;\n\t\t\tfinal long methodId = minMethodId++;\n\n\t\t\tfinal List<String> varList = new ArrayList<>();\n\t\t\tif (!methodDesc.startsWith(\"(\")) throw new UnsupportedOperationException(methodDesc);\n\t\t\touter:\n\t\t\tfor (int i = 1; i < methodDesc.length(); i++) {\n\t\t\t\tswitch (methodDesc.charAt(i)) {\n\t\t\t\t\tcase ')':\n\t\t\t\t\t\tbreak outer;\n\t\t\t\t\tcase 'L':\n\t\t\t\t\t\tint startA = i;\n\t\t\t\t\t\twhile (methodDesc.charAt(i) != ';') i++;\n\t\t\t\t\t\tvarList.add(methodDesc.substring(startA, i + 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '[':\n\t\t\t\t\t\tint startB = i;\n\t\t\t\t\t\twhile (methodDesc.charAt(i) == '[') i++;\n\t\t\t\t\t\tif (methodDesc.charAt(i) == 'L') {\n\t\t\t\t\t\t\twhile (methodDesc.charAt(i) != ';') i++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvarList.add(methodDesc.substring(startB, i + 1));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tvarList.add(String.valueOf(methodDesc.charAt(i)));\n\t\t\t\t}\n\t\t\t}\n\t\t\tfinal List<Label> catchStatement = new ArrayList<>();\n\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void visitCode() {\n\t\t\t\t\tsuper.visitCode();\n\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\tvisitLabel(l0);\n\n\t\t\t\t\tvisitLdcInsn(new Long(methodId));\n\t\t\t\t\tvisitLdcInsn(className + \"+\" + methodName + \"+\" + methodDesc);\n\t\t\t\t\tif ((m.access & Opcodes.ACC_STATIC) != 0) {\n\t\t\t\t\t\tvisitInsn(Opcodes.ACONST_NULL);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\t}\n\n\t\t\t\t\tvisitIntInsn(Opcodes.BIPUSH, varList.size());\n\t\t\t\t\tvisitTypeInsn(Opcodes.ANEWARRAY, \"java/lang/Object\");\n\t\t\t\t\tint count = 0;\n\t\t\t\t\tint pos = 0;\n\t\t\t\t\tif ((m.access & Opcodes.ACC_STATIC) == 0) {\n\t\t\t\t\t\tpos = 1;\n\t\t\t\t\t}\n\t\t\t\t\tfor (String varNode : varList) {\n\t\t\t\t\t\tvisitInsn(Opcodes.DUP);\n\t\t\t\t\t\tvisitIntInsn(Opcodes.BIPUSH, count++);\n\t\t\t\t\t\tif (!varNode.startsWith(\"L\") && !varNode.startsWith(\"[\")) {\n\t\t\t\t\t\t\tswitch (varNode.charAt(0)) {\n\t\t\t\t\t\t\t\tcase 'I':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ILOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Integer\", \"valueOf\", \"(I)Ljava/lang/Integer;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'J':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.LLOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Long\", \"valueOf\", \"(J)Ljava/lang/Long;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'Z':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ILOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Boolean\", \"valueOf\", \"(Z)Ljava/lang/Boolean;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'B':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ILOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Byte\", \"valueOf\", \"(B)Ljava/lang/Byte;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'C':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ILOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Character\", \"valueOf\", \"(C)Ljava/lang/Character;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'S':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ILOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Short\", \"valueOf\", \"(S)Ljava/lang/Short;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'F':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.FLOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Float\", \"valueOf\", \"(F)Ljava/lang/Float;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 'D':\n\t\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.DLOAD, pos);\n\t\t\t\t\t\t\t\t\tpos += 2;\n\t\t\t\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"java/lang/Double\", \"valueOf\", \"(D)Ljava/lang/Double;\", false);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"'\" + varNode + \"'\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, pos);\n\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvisitInsn(Opcodes.AASTORE);\n\t\t\t\t\t}\n\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/ParamProfiler\", \"methodStart\", \"(JLjava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V\", false);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void visitInsn(int opcode) {\n\t\t\t\t\tif (opcode == Opcodes.RETURN || opcode == Opcodes.IRETURN || opcode == Opcodes.LRETURN || opcode == Opcodes.FRETURN || opcode == Opcodes.DRETURN || opcode == Opcodes.ARETURN) {\n\t\t\t\t\t\tvisitLdcInsn(new Long(methodId));\n\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/ParamProfiler\", \"methodEnd\", \"(J)V\", false);\n\t\t\t\t\t}\n\t\t\t\t\tsuper.visitInsn(opcode);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void visitTryCatchBlock(Label start, Label end, Label handler, String type) {\n\t\t\t\t\tcatchStatement.add(handler);\n\t\t\t\t\tsuper.visitTryCatchBlock(start, end, handler, type);\n\t\t\t\t}\n\n\t\t\t\tboolean watchForHandling = false;\n\n\t\t\t\t@Override\n\t\t\t\tpublic void visitLabel(Label label) {\n\t\t\t\t\twatchForHandling = false;\n\t\t\t\t\tsuper.visitLabel(label);\n\t\t\t\t\tif (catchStatement.contains(label)) {\n\t\t\t\t\t\twatchForHandling = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void visitVarInsn(int opcode, int var) {\n\t\t\t\t\tsuper.visitVarInsn(opcode, var);\n\t\t\t\t\tif (watchForHandling) {\n\t\t\t\t\t\twatchForHandling = false;\n\t\t\t\t\t\tLabel l = new Label();\n\t\t\t\t\t\tvisitLabel(l);\n\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, var);\n\t\t\t\t\t\tvisitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/ParamProfiler\", \"handleException\", \"(Ljava/lang/Throwable;)V\", false);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t\tm.accept(mv);\n\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\n\t\t}\n\t\tClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n\n\tprivate static Map<Thread, Stack<Entry>> stack = new HashMap<>();\n\n\t@SuppressWarnings(\"unused\") // Used by ASM\n\tpublic static void methodStart(long id, String name, Object root, Object... params) {\n\t\tif (!isActive) return;\n\t\tStack<Entry> access = stack.get(Thread.currentThread());\n\t\tif (access == null) {\n\t\t\taccess = new Stack<>();\n\t\t\tstack.put(Thread.currentThread(), access);\n\t\t}\n\t\taccess.push(new Entry(id, name, root, params));\n\t}\n\n\t@SuppressWarnings(\"unused\") // Used by ASM\n\tpublic static void methodEnd(long id) {\n\t\tif (!isActive) return;\n\t\tStack<Entry> access = stack.get(Thread.currentThread());\n\t\tif (access == null || access.isEmpty()) return;\n\t\tEntry exit = access.pop();\n\t\tif (exit.id != id) {\n\t\t\twhile (!access.isEmpty() && access.peek().id != id) {\n\t\t\t\taccess.pop();\n\t\t\t}\n\t\t\tif (!access.isEmpty()) {\n\t\t\t\taccess.pop();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Getter\n\tprivate static WeakHashMap<Throwable, ArrayList<Entry>> infoLink = new WeakHashMap<>();\n\n\t@SuppressWarnings(\"unused\") // Used by ASM\n\tpublic static void handleException(Throwable t) {\n\t\tStack<Entry> access = stack.get(Thread.currentThread());\n\t\tinfoLink.put(t, new ArrayList<>(access));\n\t}\n\n\t@Data\n\t@AllArgsConstructor\n\tpublic static class Entry {\n\n\t\tprivate final long id;\n\t\tprivate final String name;\n\t\tprivate final Object root;\n\t\tprivate final Object[] params;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/addinfo/IAddInfo.java",
    "content": "package logisticspipes.asm.addinfo;\n\npublic interface IAddInfo {\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/addinfo/IAddInfoProvider.java",
    "content": "package logisticspipes.asm.addinfo;\n\npublic interface IAddInfoProvider {\n\n\t<T extends IAddInfo> T getLogisticsPipesAddInfo(Class<T> clazz);\n\n\tvoid setLogisticsPipesAddInfo(IAddInfo info);\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/mcmp/ClassBlockMultipartContainerHandler.java",
    "content": "package logisticspipes.asm.mcmp;\n\nimport net.minecraft.launchwrapper.Launch;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.MethodNode;\n\nimport logisticspipes.asm.util.ASMHelper;\n\npublic class ClassBlockMultipartContainerHandler {\n\n\tpublic static byte[] handleClass(byte[] bytes) {\n\t\ttry {\n\t\t\tLaunch.classLoader.findClass(\"mcmultipart.api.multipart.ITileMultipartContainerProvider\");\n\t\t\treturn bytes;\n\t\t} catch (ClassNotFoundException ignored) {\n\t\t}\n\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\n\t\tboolean noChecksumMatch = false;\n\t\tfinal String sumHandleEvent = ASMHelper.getCheckSumForMethod(reader, \"getTile\", \"(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Ljava/util/Optional;\");\n\t\tif (!\"C755146A0F8F81CCE6637174E17B6D48EC967D59\".equals(sumHandleEvent) && !\"570C0380BCA4C6B6BBB32CE0D400B8DE13E6D800\".equals(sumHandleEvent) && !\"D5F32B535E068F8D3B355A81B68C2938A2473D6F\".equals(sumHandleEvent)) {\n\t\t\tnoChecksumMatch = true;\n\t\t}\n\t\tif (noChecksumMatch) {\n\t\t\tSystem.out.println(\"getTile: \" + sumHandleEvent);\n\t\t\tnew UnsupportedOperationException(\"This LP version isn't compatible with the installed MCMultipart version.\").printStackTrace();\n\t\t\tFMLCommonHandler.instance().exitJava(1, true);\n\t\t}\n\n\t\tnode.methods.stream()\n\t\t\t\t.filter(m -> m.name.equals(\"getTile\") && m.desc.equals(\"(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Ljava/util/Optional;\"))\n\t\t\t\t.forEach(m -> {\n\t\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t\tboolean inserted = false;\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {\n\t\t\t\t\t\t\tif (!inserted && opcode == Opcodes.INVOKEINTERFACE && owner.equals(\"net/minecraft/world/IBlockAccess\") && (name.equals(\"getTileEntity\") || name.equals(\"func_175625_s\")) && desc.equals(\"(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity;\") && itf) {\n\t\t\t\t\t\t\t\tsuper.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/mcmp/MCMPHooks\", \"getTileEntityForBlockClass\", \"(Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity;\", false);\n\t\t\t\t\t\t\t\tinserted = true;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tsuper.visitMethodInsn(opcode, owner, name, desc, itf);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tm.accept(mv);\n\t\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t\t});\n\n\t\tClassWriter writer = new ClassWriter(0/* ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES */);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/mcmp/MCMPHooks.java",
    "content": "package logisticspipes.asm.mcmp;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\n\npublic class MCMPHooks {\n\n\tpublic interface IMCMPGetTEHook {\n\n\t\tTileEntity apply(IBlockAccess world, BlockPos pos);\n\t}\n\n\tpublic static IMCMPGetTEHook mcmpGetTEHook = IBlockAccess::getTileEntity;\n\n\tpublic static TileEntity getTileEntityForBlockClass(IBlockAccess world, BlockPos pos) {\n\t\treturn mcmpGetTEHook.apply(world, pos);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/td/ClassRenderDuctItemsHandler.java",
    "content": "package logisticspipes.asm.td;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.MethodNode;\n\nimport logisticspipes.asm.util.ASMHelper;\n\npublic class ClassRenderDuctItemsHandler {\n\n\tpublic static byte[] handleRenderDuctItemsClass(byte[] bytes) {\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\n\t\tboolean noChecksumMatch = false;\n\t\tfinal String sumHandleEvent = ASMHelper.getCheckSumForMethod(reader, \"renderTravelingItems\", \"(Ljava/util/Iterator;Lcofh/thermaldynamics/duct/item/DuctUnitItem;Lnet/minecraft/world/World;DDDF)V\");\n\t\tif (!\"2A56C07E15F612A425E4B4D8C16DEB7545947688\".equals(sumHandleEvent) && !\"0D05E26AC037D652294BE9923BAC446C87AA6A1D\".equals(sumHandleEvent)) {\n\t\t\tnoChecksumMatch = true;\n\t\t}\n\t\tif (noChecksumMatch) {\n\t\t\tSystem.out.println(\"renderTravelingItems: \" + sumHandleEvent);\n\t\t\tnew UnsupportedOperationException(\"This LP version isn't compatible with the installed TD version.\").printStackTrace();\n\t\t\tFMLCommonHandler.instance().exitJava(1, true);\n\t\t}\n\n\t\tnode.methods.stream().filter(m -> m.name.equals(\"renderTravelingItems\") && m.desc.equals(\"(Ljava/util/Iterator;Lcofh/thermaldynamics/duct/item/DuctUnitItem;Lnet/minecraft/world/World;DDDF)V\"))\n\t\t\t\t.forEach(m -> {\n\t\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions\n\t\t\t\t\t\t\t.toArray(new String[0])) {\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {\n\t\t\t\t\t\t\tsuper.visitMethodInsn(opcode, owner, name, desc, itf);\n\t\t\t\t\t\t\tif (owner.equals(\"net/minecraft/client/renderer/GlStateManager\") && (name.equals(\"scale\") || name.equals(\"func_179152_a\")) && desc\n\t\t\t\t\t\t\t\t\t.equals(\"(FFF)V\")) {\n\t\t\t\t\t\t\t\tLabel l = new Label();\n\t\t\t\t\t\t\t\tvisitLabel(l);\n\t\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 11);\n\t\t\t\t\t\t\t\tthis.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/td/ThermalDynamicsHooks\", \"renderItemTransportBox\", \"(Lcofh/thermaldynamics/duct/item/TravelingItem;)V\", false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tm.accept(mv);\n\t\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t\t});\n\n\t\tClassWriter writer = new ClassWriter(0/*ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES*/);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/td/ClassTravelingItemHandler.java",
    "content": "package logisticspipes.asm.td;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.MethodNode;\n\nimport logisticspipes.asm.util.ASMHelper;\n\npublic class ClassTravelingItemHandler {\n\n\tpublic static byte[] handleTravelingItemClass(byte[] bytes) {\n\t\tfinal ClassReader reader = new ClassReader(bytes);\n\t\tfinal ClassNode node = new ClassNode();\n\t\treader.accept(node, 0);\n\n\t\tboolean noChecksumMatch = false;\n\t\tString sumHandleEvent1 = ASMHelper.getCheckSumForMethod(reader, \"toNBT\", \"(Lnet/minecraft/nbt/NBTTagCompound;)V\");\n\t\tString sumHandleEvent2 = ASMHelper.getCheckSumForMethod(reader, \"<init>\", \"(Lnet/minecraft/nbt/NBTTagCompound;)V\");\n\t\tString sumHandleEvent3 = ASMHelper.getCheckSumForMethod(reader, \"writePacket\", \"(Lcofh/core/network/PacketBase;)V\");\n\t\tif (!\"512A30E22A9C24032AAE7CE51271339A4F68D344\".equals(sumHandleEvent1) &&\n\t\t\t\t!\"2166AB8FF647A90701787CCCFB4CD1C065BE640D\".equals(sumHandleEvent1)) {\n\t\t\tnoChecksumMatch = true;\n\t\t}\n\t\tif (!\"E8DD6BEB9676D079E6C97FF8206283E766147E45\".equals(sumHandleEvent2) &&\n\t\t\t\t!\"BB4178915C3A10EBAC5158B8742592388E47B181\".equals(sumHandleEvent2) &&\n\t\t\t\t!\"0151577E2B8CF9BF2D528A309D5AE919308ABE03\".equals(sumHandleEvent2) &&\n\t\t\t\t!\"768681BA4851C581B15713ED3FF9CA6530C24931\".equals(sumHandleEvent2)) {\n\t\t\tnoChecksumMatch = true;\n\t\t}\n\t\tif (!\"98A853547FA1771D6D7D63E0458960405DFEE092\".equals(sumHandleEvent3)) {\n\t\t\tnoChecksumMatch = true;\n\t\t}\n\t\tif (noChecksumMatch) {\n\t\t\tSystem.out.println(\"toNBT: \" + sumHandleEvent1);\n\t\t\tSystem.out.println(\"<init>: \" + sumHandleEvent2);\n\t\t\tSystem.out.println(\"writePacket: \" + sumHandleEvent3);\n\t\t\tnew UnsupportedOperationException(\"This LP version isn't compatible with the installed TD version.\").printStackTrace();\n\t\t\tFMLCommonHandler.instance().exitJava(1, true);\n\t\t}\n\n\t\tnode.interfaces.add(\"logisticspipes/asm/td/ILPTravelingItemInfo\");\n\t\t{\n\t\t\tFieldVisitor fv = node.visitField(Opcodes.ACC_PUBLIC, \"lpRoutingInformation\", \"Ljava/lang/Object;\", null, null);\n\t\t\tfv.visitEnd();\n\t\t}\n\t\t{\n\t\t\tMethodVisitor mv;\n\t\t\tmv = node.visitMethod(Opcodes.ACC_PUBLIC, \"getLPRoutingInfoAddition\", \"()Ljava/lang/Object;\", null, null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitLineNumber(23, l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, \"cofh/thermaldynamics/duct/item/TravelingItem\", \"lpRoutingInformation\", \"Ljava/lang/Object;\");\n\t\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitLocalVariable(\"this\", \"Lcofh/thermaldynamics/duct/item/TravelingItem;\", null, l0, l1, 0);\n\t\t\tmv.visitMaxs(1, 1);\n\t\t\tmv.visitEnd();\n\t\t}\n\t\t{\n\t\t\tMethodVisitor mv;\n\t\t\tmv = node.visitMethod(Opcodes.ACC_PUBLIC, \"setLPRoutingInfoAddition\", \"(Ljava/lang/Object;)V\", null, null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitLineNumber(28, l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, \"cofh/thermaldynamics/duct/item/TravelingItem\", \"lpRoutingInformation\", \"Ljava/lang/Object;\");\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitLineNumber(29, l1);\n\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\tLabel l2 = new Label();\n\t\t\tmv.visitLabel(l2);\n\t\t\tmv.visitLocalVariable(\"this\", \"Lcofh/thermaldynamics/duct/item/TravelingItem;\", null, l0, l2, 0);\n\t\t\tmv.visitLocalVariable(\"info\", \"Ljava/lang/Object;\", null, l0, l2, 1);\n\t\t\tmv.visitMaxs(2, 2);\n\t\t\tmv.visitEnd();\n\t\t}\n\t\tfor (MethodNode m : node.methods) {\n\t\t\tif (m.name.equals(\"toNBT\") && m.desc.equals(\"(Lnet/minecraft/nbt/NBTTagCompound;)V\")) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitCode() {\n\t\t\t\t\t\tsuper.visitCode();\n\t\t\t\t\t\tLabel l = new Label();\n\t\t\t\t\t\tvisitLabel(l);\n\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\tthis.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/td/ThermalDynamicsHooks\", \"travelingItemToNBT\", \"(Lcofh/thermaldynamics/duct/item/TravelingItem;Lnet/minecraft/nbt/NBTTagCompound;)V\", false);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t\tif (m.name.equals(\"<init>\") && m.desc.equals(\"(Lnet/minecraft/nbt/NBTTagCompound;)V\")) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitInsn(int opcode) {\n\t\t\t\t\t\tif (opcode == Opcodes.RETURN) {\n\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\t\t\tthis.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/td/ThermalDynamicsHooks\", \"travelingItemNBTContructor\", \"(Lcofh/thermaldynamics/duct/item/TravelingItem;Lnet/minecraft/nbt/NBTTagCompound;)V\", false);\n\t\t\t\t\t\t\tLabel l = new Label();\n\t\t\t\t\t\t\tvisitLabel(l);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsuper.visitInsn(opcode);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t\tif (m.name.equals(\"writePacket\") && m.desc.equals(\"(Lcofh/core/network/PacketBase;)V\")) {\n\t\t\t\tMethodNode mv = new MethodNode(Opcodes.ASM4, m.access, m.name, m.desc, m.signature, m.exceptions.toArray(new String[0])) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {\n\t\t\t\t\t\tif (opcode == Opcodes.INVOKEVIRTUAL && \"cofh/core/network/PacketBase\".equals(owner) && \"addItemStack\".equals(name) && \"(Lnet/minecraft/item/ItemStack;)Lcofh/core/network/PacketBase;\".equals(desc)) {\n\t\t\t\t\t\t\tvisitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\t\t\tthis.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/td/ThermalDynamicsHooks\", \"handleItemSendPacket\", \"(Lnet/minecraft/item/ItemStack;Lcofh/thermaldynamics/duct/item/TravelingItem;)Lnet/minecraft/item/ItemStack;\", false);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsuper.visitMethodInsn(opcode, owner, name, desc, itf);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tm.accept(mv);\n\t\t\t\tnode.methods.set(node.methods.indexOf(m), mv);\n\t\t\t}\n\t\t}\n\n\t\tClassWriter writer = new ClassWriter(0/*ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES*/);\n\t\tnode.accept(writer);\n\t\treturn writer.toByteArray();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/td/ILPTravelingItemInfo.java",
    "content": "package logisticspipes.asm.td;\n\npublic interface ILPTravelingItemInfo {\n\n\tObject getLPRoutingInfoAddition();\n\n\tvoid setLPRoutingInfoAddition(Object info);\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/td/ThermalDynamicsHooks.java",
    "content": "package logisticspipes.asm.td;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport cofh.thermaldynamics.duct.item.TravelingItem;\n\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.routing.ItemRoutingInformation;\n\npublic class ThermalDynamicsHooks {\n\n\tpublic static void travelingItemToNBT(TravelingItem travelingItem, NBTTagCompound paramNBTTagCompound) {\n\t\tif (((ILPTravelingItemInfo) travelingItem).getLPRoutingInfoAddition() != null) {\n\t\t\tNBTTagCompound save = new NBTTagCompound();\n\t\t\t((ItemRoutingInformation) ((ILPTravelingItemInfo) travelingItem).getLPRoutingInfoAddition()).writeToNBT(save);\n\t\t\tparamNBTTagCompound.setTag(\"LPRoutingInformation\", save);\n\t\t}\n\t}\n\n\tpublic static void travelingItemNBTContructor(TravelingItem travelingItem, NBTTagCompound paramNBTTagCompound) {\n\t\tif (!paramNBTTagCompound.hasKey(\"LPRoutingInformation\")) {\n\t\t\treturn;\n\t\t}\n\t\t((ILPTravelingItemInfo) travelingItem).setLPRoutingInfoAddition(new ItemRoutingInformation());\n\t\t((ItemRoutingInformation) ((ILPTravelingItemInfo) travelingItem).getLPRoutingInfoAddition()).readFromNBT(paramNBTTagCompound.getCompoundTag(\"LPRoutingInformation\"));\n\t}\n\n\tpublic static void renderItemTransportBox(TravelingItem item) {\n\t\tif (item.stack.hasTagCompound()) {\n\t\t\tif (item.stack.getTagCompound().getString(\"LogsitcsPipes_ITEM_ON_TRANSPORTATION\").equals(\"YES\")) {\n\t\t\t\tdouble scale = 0.59 / 0.6;\n\t\t\t\tLogisticsRenderPipe.boxRenderer.doRenderItem(ItemStack.EMPTY, 10, 0, 0, 0, scale, 0, 0, 0);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static ItemStack handleItemSendPacket(ItemStack stack, TravelingItem item) {\n\t\tif (item.stack == null || item.stack.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\t\tif (((ILPTravelingItemInfo) item).getLPRoutingInfoAddition() != null) {\n\t\t\tstack = stack.copy();\n\t\t\tif (!stack.hasTagCompound()) {\n\t\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t\t}\n\t\t\tstack.getTagCompound().setString(\"LogsitcsPipes_ITEM_ON_TRANSPORTATION\", \"YES\");\n\t\t}\n\t\treturn stack;\n\t}\n}"
  },
  {
    "path": "common/logisticspipes/asm/te/ILPTEInformation.java",
    "content": "package logisticspipes.asm.te;\n\npublic interface ILPTEInformation {\n\n\tLPTileEntityObject getLPTileEntityObject();\n\n\tvoid setLPTileEntityObject(LPTileEntityObject object);\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/te/ITileEntityChangeListener.java",
    "content": "package logisticspipes.asm.te;\n\nimport net.minecraft.util.EnumFacing;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface ITileEntityChangeListener {\n\n\tvoid pipeRemoved(DoubleCoordinates pos);\n\n\tvoid pipeAdded(DoubleCoordinates pos, EnumFacing side);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/te/LPTileEntityObject.java",
    "content": "package logisticspipes.asm.te;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport logisticspipes.utils.CacheHolder;\nimport logisticspipes.utils.CacheHolder.CacheTypes;\n\npublic class LPTileEntityObject {\n\n\tpublic List<ITileEntityChangeListener> changeListeners = new ArrayList<>();\n\tpublic long initialised = 0;\n\n\tprivate CacheHolder cacheHolder;\n\n\tpublic CacheHolder getCacheHolder() {\n\t\tif (cacheHolder == null) {\n\t\t\tcacheHolder = new CacheHolder();\n\t\t}\n\t\treturn cacheHolder;\n\t}\n\n\tpublic void trigger(CacheTypes type) {\n\t\tif (cacheHolder != null) {\n\t\t\tgetCacheHolder().trigger(type);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/util/ASMHelper.java",
    "content": "package logisticspipes.asm.util;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.io.StringReader;\nimport java.io.StringWriter;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\n\nimport org.objectweb.asm.Attribute;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.util.Printer;\nimport org.objectweb.asm.util.Textifier;\nimport org.objectweb.asm.util.TraceClassVisitor;\n\npublic class ASMHelper {\n\n\tprivate static final String HEXES = \"0123456789ABCDEF\";\n\n\tpublic static String getContentForMethod(ClassReader classReader, String methodName, boolean newLine) {\n\t\treturn ASMHelper.getContentForMethod(classReader, methodName, \"\", newLine);\n\t}\n\n\tpublic static String getContentForMethod(ClassReader classReader, String methodName, String desc, boolean newLine) {\n\t\tStringWriter stringWriter = new StringWriter();\n\t\tPrintWriter printWriter = new PrintWriter(stringWriter);\n\t\tTraceClassVisitor traceClassVisitor = new TraceClassVisitor(null, new MethodTextifier(), printWriter);\n\t\tFilterClassVisitor myClassVisitor = new FilterClassVisitor(traceClassVisitor, methodName, desc);\n\t\tclassReader.accept(myClassVisitor, ClassReader.SKIP_DEBUG);\n\t\tBufferedReader reader = new BufferedReader(new StringReader(stringWriter.toString()));\n\t\tStringBuilder builder = new StringBuilder();\n\t\tString line;\n\t\ttry {\n\t\t\twhile ((line = reader.readLine()) != null) {\n\t\t\t\tline = line.trim();\n\t\t\t\tString oldLine = line;\n\t\t\t\tline += \" \";\n\t\t\t\twhile (!oldLine.equals(line)) {\n\t\t\t\t\toldLine = line;\n\t\t\t\t\tline = line.trim();\n\t\t\t\t\tline = line.replace(\"\\t\", \" \");\n\t\t\t\t\tline = line.replace(\"  \", \" \");\n\t\t\t\t}\n\t\t\t\tbuilder.append(\" \");\n\t\t\t\tbuilder.append(line);\n\t\t\t\tif (newLine) {\n\t\t\t\t\tbuilder.append(System.lineSeparator());\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn builder.toString();\n\t}\n\n\tpublic static String getCheckSumForMethod(ClassReader classReader, String methodName) {\n\t\treturn ASMHelper.getCheckSumForMethod(classReader, methodName, \"\");\n\t}\n\n\tpublic static String getCheckSumForMethod(ClassReader classReader, String methodName, String desc) {\n\t\tString result = ASMHelper.getContentForMethod(classReader, methodName, desc, false);\n\t\tif (result.isEmpty()) {\n\t\t\tthrow new NoSuchMethodError();\n\t\t}\n\t\treturn ASMHelper.toSHA1(result.getBytes());\n\t}\n\n\tpublic static String toSHA1(byte[] convertme) {\n\t\tMessageDigest md = null;\n\t\ttry {\n\t\t\tmd = MessageDigest.getInstance(\"SHA-1\");\n\t\t} catch (NoSuchAlgorithmException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn ASMHelper.getHex(md.digest(convertme));\n\t}\n\n\tprivate static String getHex(byte[] raw) {\n\t\tif (raw == null) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal StringBuilder hex = new StringBuilder(2 * raw.length);\n\t\tfor (final byte b : raw) {\n\t\t\thex.append(ASMHelper.HEXES.charAt((b & 0xF0) >> 4)).append(ASMHelper.HEXES.charAt((b & 0x0F)));\n\t\t}\n\t\treturn hex.toString();\n\t}\n\n\tprivate static class FilterClassVisitor extends ClassVisitor {\n\n\t\tprivate final String methodName;\n\t\tprivate final String methodDesc;\n\n\t\tpublic FilterClassVisitor(TraceClassVisitor traceClassVisitor, String methodName, String desc) {\n\t\t\tsuper(Opcodes.ASM4, traceClassVisitor);\n\t\t\tthis.methodName = methodName;\n\t\t\tmethodDesc = desc;\n\t\t}\n\n\t\t@Override\n\t\tpublic MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {\n\t\t\tif (methodName.equals(name) && (methodDesc.isEmpty() || methodDesc.equals(desc))) {\n\t\t\t\treturn new FilterMaxVisitMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate static class FilterMaxVisitMethodVisitor extends MethodVisitor {\n\n\t\tpublic FilterMaxVisitMethodVisitor(MethodVisitor mv) {\n\t\t\tsuper(Opcodes.ASM4, mv);\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitMaxs(int maxStack, int maxLocals) {}\n\t}\n\n\tprivate static class MethodTextifier extends Printer {\n\n\t\tpublic MethodTextifier() {\n\t\t\tsuper(Opcodes.ASM4);\n\t\t}\n\n\t\t@Override\n\t\tpublic void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {}\n\n\t\t@Override\n\t\tpublic void visitSource(final String file, final String debug) {}\n\n\t\t@Override\n\t\tpublic void visitOuterClass(final String owner, final String name, final String desc) {}\n\n\t\t@Override\n\t\tpublic Textifier visitClassAnnotation(final String desc, final boolean visible) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitClassAttribute(final Attribute attr) {}\n\n\t\t@Override\n\t\tpublic void visitInnerClass(final String name, final String outerName, final String innerName, final int access) {}\n\n\t\t@Override\n\t\tpublic Textifier visitField(final int access, final String name, final String desc, final String signature, final Object value) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic Textifier visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {\n\t\t\tTextifier t = new Textifier();\n\t\t\ttext.add(t.getText());\n\t\t\treturn t;\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitClassEnd() {}\n\n\t\t@Override\n\t\tpublic void visit(final String name, final Object value) {}\n\n\t\t@Override\n\t\tpublic void visitEnum(final String name, final String desc, final String value) {}\n\n\t\t@Override\n\t\tpublic Textifier visitAnnotation(final String name, final String desc) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic Textifier visitArray(final String name) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitAnnotationEnd() {}\n\n\t\t@Override\n\t\tpublic Textifier visitFieldAnnotation(final String desc, final boolean visible) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitFieldAttribute(final Attribute attr) {\n\t\t\tvisitAttribute(attr);\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitFieldEnd() {}\n\n\t\t@Override\n\t\tpublic Textifier visitAnnotationDefault() {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic Textifier visitMethodAnnotation(final String desc, final boolean visible) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic Textifier visitParameterAnnotation(final int parameter, final String desc, final boolean visible) {\n\t\t\treturn new Textifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic void visitMethodAttribute(final Attribute attr) {}\n\n\t\t@Override\n\t\tpublic void visitCode() {}\n\n\t\t@Override\n\t\tpublic void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {}\n\n\t\t@Override\n\t\tpublic void visitInsn(final int opcode) {}\n\n\t\t@Override\n\t\tpublic void visitIntInsn(final int opcode, final int operand) {}\n\n\t\t@Override\n\t\tpublic void visitVarInsn(final int opcode, final int var) {}\n\n\t\t@Override\n\t\tpublic void visitTypeInsn(final int opcode, final String type) {}\n\n\t\t@Override\n\t\tpublic void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {}\n\n\t\t@Override\n\t\tpublic void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {}\n\n\t\t@Override\n\t\tpublic void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {}\n\n\t\t@Override\n\t\tpublic void visitJumpInsn(final int opcode, final Label label) {}\n\n\t\t@Override\n\t\tpublic void visitLabel(final Label label) {}\n\n\t\t@Override\n\t\tpublic void visitLdcInsn(final Object cst) {}\n\n\t\t@Override\n\t\tpublic void visitIincInsn(final int var, final int increment) {}\n\n\t\t@Override\n\t\tpublic void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) {}\n\n\t\t@Override\n\t\tpublic void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {}\n\n\t\t@Override\n\t\tpublic void visitMultiANewArrayInsn(final String desc, final int dims) {}\n\n\t\t@Override\n\t\tpublic void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {}\n\n\t\t@Override\n\t\tpublic void visitLocalVariable(final String name, final String desc, final String signature, final Label start, final Label end, final int index) {}\n\n\t\t@Override\n\t\tpublic void visitLineNumber(final int line, final Label start) {}\n\n\t\t@Override\n\t\tpublic void visitMaxs(final int maxStack, final int maxLocals) {}\n\n\t\t@Override\n\t\tpublic void visitMethodEnd() {}\n\n\t\tpublic void visitAttribute(final Attribute attr) {}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/AbstractSubWrapper.java",
    "content": "package logisticspipes.asm.wrapper;\n\nimport java.util.List;\n\npublic abstract class AbstractSubWrapper extends AbstractWrapper {\n\n\tprivate final AbstractWrapper originalWrapper;\n\n\tpublic AbstractSubWrapper(AbstractWrapper wrapper) {\n\t\toriginalWrapper = wrapper;\n\t}\n\n\t@Override\n\tprotected final boolean isEnabled() {\n\t\treturn originalWrapper.isEnabled();\n\t}\n\n\t@Override\n\tprotected final boolean canTryAnyway() {\n\t\treturn originalWrapper.canTryAnyway();\n\t}\n\n\t@Override\n\tpublic void handleException(Throwable e) {\n\t\toriginalWrapper.handleException(e);\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn originalWrapper.getName();\n\t}\n\n\t@Override\n\tpublic String getTypeName() {\n\t\treturn originalWrapper.getTypeName();\n\t}\n\n\t@Override\n\tpublic WrapperState getState() {\n\t\treturn originalWrapper.getState();\n\t}\n\n\t@Override\n\tpublic Throwable getReason() {\n\t\treturn originalWrapper.getReason();\n\t}\n\n\t@Override\n\tpublic String getModId() {\n\t\treturn originalWrapper.getModId();\n\t}\n\n\t@Override\n\tpublic List<Class<?>> getWrapperInterfaces() {\n\t\treturn originalWrapper.getWrapperInterfaces();\n\t}\n\n\t@Override\n\tpublic void reEnable() {\n\t\toriginalWrapper.reEnable();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/AbstractWrapper.java",
    "content": "package logisticspipes.asm.wrapper;\n\nimport java.util.List;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.SneakyThrows;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.string.ChatColor;\n\npublic abstract class AbstractWrapper {\n\n\t@Getter\n\t@Setter(value = AccessLevel.PACKAGE)\n\tprotected WrapperState state = WrapperState.Enabled;\n\t@Getter\n\t@Setter(value = AccessLevel.PACKAGE)\n\tprivate Throwable reason;\n\t@Getter\n\t@Setter(value = AccessLevel.PACKAGE)\n\tprivate String modId;\n\t@Getter\n\t@Setter(value = AccessLevel.PACKAGE)\n\tprivate List<Class<?>> wrapperInterfaces;\n\n\t@SneakyThrows(Throwable.class)\n\tpublic void handleException(Throwable e) {\n\t\tif (!isEnabled()) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tthrow e;\n\t\t}\n\t\te.printStackTrace();\n\t\tstate = WrapperState.Exception;\n\t\treason = e;\n\t\tString message = \"Disabled \" + getName() + getTypeName() + (modId != null ? (\" for Mod: \" + modId) : \"\") + \". Cause was an Exception\";\n\t\tLogisticsPipes.log.fatal(message);\n\t\tMainProxy.proxy.sendBroadCast(ChatColor.RED + message);\n\t}\n\n\tpublic void reEnable() {\n\t\tif (state != WrapperState.Exception) {\n\t\t\treturn;\n\t\t}\n\t\tstate = WrapperState.Enabled;\n\t\treason = null;\n\t}\n\n\tprotected boolean isEnabled() {\n\t\treturn state == WrapperState.Enabled;\n\t}\n\n\tprotected boolean canTryAnyway() {\n\t\treturn state != WrapperState.ModMissing;\n\t}\n\n\tpublic abstract String getName();\n\n\tpublic abstract String getTypeName();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/CraftingRecipeProviderWrapper.java",
    "content": "package logisticspipes.asm.wrapper;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\nclass CraftingRecipeProviderWrapper extends AbstractWrapper implements ICraftingRecipeProvider {\n\n\tprivate ICraftingRecipeProvider provider;\n\tprivate final String name;\n\n\tCraftingRecipeProviderWrapper(ICraftingRecipeProvider provider, String name) {\n\t\tthis.provider = provider;\n\t\tthis.name = name;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic String getTypeName() {\n\t\treturn \"RecipeProvider\";\n\t}\n\n\t@Override\n\tpublic boolean canOpenGui(TileEntity tile) {\n\t\tif (isEnabled()) {\n\t\t\ttry {\n\t\t\t\treturn provider.canOpenGui(tile);\n\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\thandleException(e);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean importRecipe(TileEntity tile, IItemIdentifierInventory inventory) {\n\t\tif (isEnabled()) {\n\t\t\ttry {\n\t\t\t\treturn provider.importRecipe(tile, inventory);\n\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\thandleException(e);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/GenericLPPipeConfigToolWrapper.java",
    "content": "package logisticspipes.asm.wrapper;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.api.ILPPipeConfigTool;\nimport logisticspipes.api.ILPPipeTile;\nimport logisticspipes.proxy.interfaces.ILPPipeConfigToolWrapper;\n\npublic class GenericLPPipeConfigToolWrapper extends AbstractWrapper implements ILPPipeConfigToolWrapper {\n\n\tprivate ILPPipeConfigToolWrapper wrapper;\n\tprivate final String name;\n\n\tGenericLPPipeConfigToolWrapper(ILPPipeConfigToolWrapper wrapper, String name) {\n\t\tthis.wrapper = wrapper;\n\t\tthis.name = name;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic String getTypeName() {\n\t\treturn \"LPPipeConfigToolWrapper\";\n\t}\n\n\t@Override\n\tpublic ILPPipeConfigTool getWrappedTool(@Nonnull ItemStack stack) {\n\t\tif (isEnabled()) {\n\t\t\ttry {\n\t\t\t\tILPPipeConfigTool tool = wrapper.getWrappedTool(stack);\n\t\t\t\tif (tool != null) {\n\t\t\t\t\treturn new GenericLPPipeConfigTool(tool, this);\n\t\t\t\t}\n\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\thandleException(e);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tstatic class GenericLPPipeConfigTool extends AbstractSubWrapper implements ILPPipeConfigTool {\n\n\t\tILPPipeConfigTool tool;\n\n\t\tpublic GenericLPPipeConfigTool(ILPPipeConfigTool tool, AbstractWrapper wrapper) {\n\t\t\tsuper(wrapper);\n\t\t\tthis.tool = tool;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canWrench(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\t\tif (isEnabled()) {\n\t\t\t\ttry {\n\t\t\t\t\treturn tool.canWrench(player, wrench, pipe);\n\t\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\t\thandleException(e);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic void wrenchUsed(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\t\tif (isEnabled()) {\n\t\t\t\ttry {\n\t\t\t\t\ttool.wrenchUsed(player, wrench, pipe);\n\t\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\t\thandleException(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/GenericProgressProviderWrapper.java",
    "content": "package logisticspipes.asm.wrapper;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.proxy.interfaces.IGenericProgressProvider;\n\npublic class GenericProgressProviderWrapper extends AbstractWrapper implements IGenericProgressProvider {\n\n\tprivate IGenericProgressProvider provider;\n\tprivate final String name;\n\n\tGenericProgressProviderWrapper(IGenericProgressProvider provider, String name) {\n\t\tthis.provider = provider;\n\t\tthis.name = name;\n\t}\n\n\t@Override\n\tpublic boolean isType(TileEntity tile) {\n\t\tif (isEnabled()) {\n\t\t\ttry {\n\t\t\t\treturn provider.isType(tile);\n\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\thandleException(e);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic byte getProgress(TileEntity tile) {\n\t\tif (isEnabled()) {\n\t\t\ttry {\n\t\t\t\treturn provider.getProgress(tile);\n\t\t\t} catch (Exception | NoClassDefFoundError e) {\n\t\t\t\thandleException(e);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic String getTypeName() {\n\t\treturn \"ProgressProvider\";\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/LogisticsWrapperHandler.java",
    "content": "package logisticspipes.asm.wrapper;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.io.PrintWriter;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.launchwrapper.Launch;\nimport net.minecraft.launchwrapper.LogWrapper;\n\nimport org.apache.logging.log4j.Level;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.asm.IgnoreDisabledProxy;\nimport logisticspipes.proxy.DontLoadProxy;\nimport logisticspipes.proxy.VersionNotSupportedException;\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.proxy.interfaces.IGenericProgressProvider;\nimport logisticspipes.proxy.interfaces.ILPPipeConfigToolWrapper;\nimport logisticspipes.utils.ModStatusHelper;\n\npublic class LogisticsWrapperHandler {\n\n\tprivate static final boolean DUMP = false;\n\n\tprivate static Map<String, Class<?>> lookupMap = new HashMap<>();\n\tpublic static List<AbstractWrapper> wrapperController = new ArrayList<>();\n\n\tprivate static Method m_defineClass = null;\n\n\tprivate LogisticsWrapperHandler() {}\n\n\tpublic static ILPPipeConfigToolWrapper getWrappedPipeConfigToolWrapper(String clazz, String name, Class<? extends ILPPipeConfigToolWrapper> providerClass) {\n\t\tILPPipeConfigToolWrapper wrapper = null;\n\t\tThrowable e = null;\n\t\ttry {\n\t\t\tClass.forName(clazz);\n\t\t\ttry {\n\t\t\t\twrapper = providerClass.newInstance();\n\t\t\t} catch (Exception e1) {\n\t\t\t\tif (e1 instanceof VersionNotSupportedException) {\n\t\t\t\t\tthrow (VersionNotSupportedException) e1;\n\t\t\t\t}\n\t\t\t\te1.printStackTrace();\n\t\t\t\te = e1;\n\t\t\t} catch (NoClassDefFoundError e1) {\n\t\t\t\te1.printStackTrace();\n\t\t\t\te = e1;\n\t\t\t}\n\t\t} catch (NoClassDefFoundError | ClassNotFoundException ignored) {}\n\t\tGenericLPPipeConfigToolWrapper instance = new GenericLPPipeConfigToolWrapper(wrapper, name);\n\t\tif (wrapper != null) {\n\t\t\tLogisticsPipes.log.info(\"Loaded \" + name + \" PipeConfigToolWrapper\");\n\t\t} else {\n\t\t\tif (e != null) {\n\t\t\t\tinstance.setState(WrapperState.Exception);\n\t\t\t\tinstance.setReason(e);\n\t\t\t\tLogisticsPipes.log.info(\"Couldn't load \" + name + \" PipeConfigToolWrapper\");\n\t\t\t} else {\n\t\t\t\tLogisticsPipes.log.info(\"Didn't load \" + name + \" PipeConfigToolWrapper\");\n\t\t\t\tinstance.setState(WrapperState.ModMissing);\n\t\t\t}\n\t\t}\n\t\tLogisticsWrapperHandler.wrapperController.add(instance);\n\t\treturn instance;\n\t}\n\n\tpublic static IGenericProgressProvider getWrappedProgressProvider(String modId, String name, Class<? extends IGenericProgressProvider> providerClass) {\n\t\tIGenericProgressProvider provider = null;\n\t\tThrowable e = null;\n\t\tif (ModStatusHelper.isModLoaded(modId)) {\n\t\t\ttry {\n\t\t\t\tprovider = providerClass.newInstance();\n\t\t\t} catch (Exception e1) {\n\t\t\t\tif (e1 instanceof VersionNotSupportedException) {\n\t\t\t\t\tthrow (VersionNotSupportedException) e1;\n\t\t\t\t}\n\t\t\t\te1.printStackTrace();\n\t\t\t\te = e1;\n\t\t\t} catch (NoClassDefFoundError e1) {\n\t\t\t\te1.printStackTrace();\n\t\t\t\te = e1;\n\t\t\t}\n\t\t}\n\t\tGenericProgressProviderWrapper instance = new GenericProgressProviderWrapper(provider, modId + \": \" + name);\n\t\tif (provider != null) {\n\t\t\tLogisticsPipes.log.info(\"Loaded \" + modId + \", \" + name + \" ProgressProvider\");\n\t\t} else {\n\t\t\tif (e != null) {\n\t\t\t\tinstance.setState(WrapperState.Exception);\n\t\t\t\tinstance.setReason(e);\n\t\t\t\tLogisticsPipes.log.info(\"Couldn't load \" + modId + \", \" + name + \" ProgressProvider\");\n\t\t\t} else {\n\t\t\t\tLogisticsPipes.log.info(\"Didn't load \" + modId + \", \" + name + \" ProgressProvider\");\n\t\t\t\tinstance.setState(WrapperState.ModMissing);\n\t\t\t}\n\t\t}\n\t\tinstance.setModId(modId);\n\t\tLogisticsWrapperHandler.wrapperController.add(instance);\n\t\treturn instance;\n\t}\n\n\tpublic static ICraftingRecipeProvider getWrappedRecipeProvider(String modId, String name, Class<? extends ICraftingRecipeProvider> providerClass) {\n\t\tICraftingRecipeProvider provider = null;\n\t\tThrowable e = null;\n\t\tif (ModStatusHelper.isModLoaded(modId)) {\n\t\t\ttry {\n\t\t\t\tprovider = providerClass.newInstance();\n\t\t\t} catch (Exception e1) {\n\t\t\t\tif (e1 instanceof VersionNotSupportedException) {\n\t\t\t\t\tthrow (VersionNotSupportedException) e1;\n\t\t\t\t}\n\t\t\t\te1.printStackTrace();\n\t\t\t\te = e1;\n\t\t\t} catch (NoClassDefFoundError e1) {\n\t\t\t\te1.printStackTrace();\n\t\t\t\te = e1;\n\t\t\t}\n\t\t}\n\t\tCraftingRecipeProviderWrapper instance = new CraftingRecipeProviderWrapper(provider, name);\n\t\tif (provider != null) {\n\t\t\tLogisticsPipes.log.info(\"Loaded \" + name + \" RecipeProvider\");\n\t\t} else {\n\t\t\tif (e != null) {\n\t\t\t\tinstance.setState(WrapperState.Exception);\n\t\t\t\tinstance.setReason(e);\n\t\t\t\tLogisticsPipes.log.info(\"Couldn't load \" + name + \" RecipeProvider\");\n\t\t\t} else {\n\t\t\t\tLogisticsPipes.log.info(\"Didn't load \" + name + \" RecipeProvider\");\n\t\t\t\tinstance.setState(WrapperState.ModMissing);\n\t\t\t}\n\t\t}\n\t\tinstance.setModId(modId);\n\t\tLogisticsWrapperHandler.wrapperController.add(instance);\n\t\treturn instance;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <T> T getWrappedProxy(String modId, Class<T> interfaze, Class<? extends T> proxyClazz, T dummyProxy, Class<?>... wrapperInterfaces) throws SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException,\n\t\t\tInvocationTargetException, NoSuchMethodException {\n\t\tString proxyName = interfaze.getSimpleName().substring(1);\n\t\tif (!proxyName.endsWith(\"Proxy\")) {\n\t\t\tthrow new RuntimeException(\"UnuportedProxyName: \" + proxyName);\n\t\t}\n\t\tproxyName = proxyName.substring(0, proxyName.length() - 5);\n\t\tString className = \"logisticspipes/asm/wrapper/generated/\" + proxyName + \"ProxyWrapper\";\n\t\tboolean ignoreModLoaded = false;\n\t\tif (modId.startsWith(\"!\")) {\n\t\t\tignoreModLoaded = true;\n\t\t\tmodId = modId.substring(1);\n\t\t}\n\t\tList<Class<?>> wrapperInterfacesList = Arrays.asList(wrapperInterfaces);\n\t\tClass<?> clazz;\n\t\tsynchronized (lookupMap) {\n\t\t\tclazz = LogisticsWrapperHandler.lookupMap.get(className);\n\t\t\tif (clazz == null) {\n\t\t\t\tString fieldName = interfaze.getName().replace('.', '/');\n\t\t\t\t//String classFile = interfaze.getSimpleName().substring(1) + \"Wrapper.java\";\n\t\t\t\tClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n\n\t\t\t\tcw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className, null, \"logisticspipes/asm/wrapper/AbstractWrapper\", new String[] { fieldName });\n\n\t\t\t\tcw.visitSource(\".LP|ASM.dynamic\", null);\n\n\t\t\t\t{\n\t\t\t\t\tFieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, \"proxy\", \"L\" + fieldName + \";\", null, null);\n\t\t\t\t\tfv.visitEnd();\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tFieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, \"dummyProxy\", \"L\" + fieldName + \";\", null, null);\n\t\t\t\t\tfv.visitEnd();\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, \"<init>\", \"(L\" + fieldName + \";L\" + fieldName + \";)V\", null, null);\n\t\t\t\t\tmv.visitCode();\n\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\tmv.visitLabel(l0);\n\t\t\t\t\tmv.visitLineNumber(11, l0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\tmv.visitMethodInsn(Opcodes.INVOKESPECIAL, \"logisticspipes/asm/wrapper/AbstractWrapper\", \"<init>\", \"()V\");\n\t\t\t\t\tLabel l1 = new Label();\n\t\t\t\t\tmv.visitLabel(l1);\n\t\t\t\t\tmv.visitLineNumber(12, l1);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, className, \"dummyProxy\", \"L\" + fieldName + \";\");\n\t\t\t\t\tLabel l2 = new Label();\n\t\t\t\t\tmv.visitLabel(l2);\n\t\t\t\t\tmv.visitLineNumber(13, l2);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 2);\n\t\t\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, className, \"proxy\", \"L\" + fieldName + \";\");\n\t\t\t\t\tLabel l3 = new Label();\n\t\t\t\t\tmv.visitLabel(l3);\n\t\t\t\t\tmv.visitLineNumber(14, l3);\n\t\t\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\t\t\tLabel l4 = new Label();\n\t\t\t\t\tmv.visitLabel(l4);\n\t\t\t\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l0, l4, 0);\n\t\t\t\t\tmv.visitLocalVariable(\"dProxy\", \"L\" + fieldName + \";\", null, l0, l4, 1);\n\t\t\t\t\tmv.visitLocalVariable(\"iProxy\", \"L\" + fieldName + \";\", null, l0, l4, 2);\n\t\t\t\t\tmv.visitMaxs(2, 3);\n\t\t\t\t\tmv.visitEnd();\n\t\t\t\t}\n\t\t\t\tint lineAddition = 100;\n\t\t\t\tfor (Method method : interfaze.getMethods()) {\n\t\t\t\t\tLogisticsWrapperHandler.addProxyMethod(cw, method, fieldName, className, lineAddition, !wrapperInterfacesList.contains(method.getReturnType()));\n\t\t\t\t\tlineAddition += 10;\n\t\t\t\t}\n\t\t\t\tLogisticsWrapperHandler.addGetName(cw, className, proxyName);\n\t\t\t\tLogisticsWrapperHandler.addGetTypeName(cw, className, \"Proxy\");\n\t\t\t\tcw.visitEnd();\n\n\t\t\t\tString lookfor = className.replace('/', '.');\n\n\t\t\t\tbyte[] bytes = cw.toByteArray();\n\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tif (LogisticsWrapperHandler.DUMP) {\n\t\t\t\t\t\tLogisticsWrapperHandler.saveGeneratedClass(bytes, lookfor, \"LP_WRAPPER_CLASSES\");\n\t\t\t\t\t}\n\t\t\t\t\tClassReader cr = new ClassReader(bytes);\n\t\t\t\t\torg.objectweb.asm.util.CheckClassAdapter.verify(cr, Launch.classLoader, false, new PrintWriter(System.err));\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tclazz = LogisticsWrapperHandler.loadClass(bytes, lookfor);\n\t\t\t\t} catch (LinkageError e) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (e.getMessage().contains(\"attempted\") && e.getMessage().contains(\"duplicate class definition\")) {\n\t\t\t\t\t\t\tClass<?> prev = Class.forName(className);\n\t\t\t\t\t\t\tSystem.err.println(e.getMessage());\n\t\t\t\t\t\t\tSystem.err.printf(\"Already loaded: %s%n\", prev);\n\t\t\t\t\t\t\tString resourcePath = className.replace('.', '/').concat(\".class\");\n\t\t\t\t\t\t\tURL classResource = Launch.classLoader.findResource(resourcePath);\n\t\t\t\t\t\t\tif (classResource != null) {\n\t\t\t\t\t\t\t\tString path = classResource.getPath();\n\t\t\t\t\t\t\t\tSystem.err.println(\"Class source: \" + path);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSystem.err.println(\"Class source: Null\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e2) {\n\t\t\t\t\t\te2.printStackTrace();\n\t\t\t\t\t}\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t\tLogisticsWrapperHandler.lookupMap.put(className, clazz);\n\t\t\t}\n\t\t}\n\n\t\tT proxy = null;\n\t\tThrowable e = null;\n\t\tif ((ModStatusHelper.areModsLoaded(modId) || ignoreModLoaded) && proxyClazz != null) {\n\t\t\ttry {\n\t\t\t\tproxy = proxyClazz.newInstance();\n\t\t\t} catch (Exception e1) {\n\t\t\t\tif (e1 instanceof VersionNotSupportedException) {\n\t\t\t\t\tthrow (VersionNotSupportedException) e1;\n\t\t\t\t}\n\t\t\t\tif (!(e1 instanceof DontLoadProxy)) {\n\t\t\t\t\te1.printStackTrace();\n\t\t\t\t\te = e1;\n\t\t\t\t}\n\t\t\t} catch (NoClassDefFoundError e1) {\n\t\t\t\tif (!ignoreModLoaded) {\n\t\t\t\t\te1.printStackTrace();\n\t\t\t\t\te = e1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tT instance = (T) clazz.getConstructor(new Class<?>[] { interfaze, interfaze }).newInstance(dummyProxy, proxy);\n\t\tif (proxy != null) {\n\t\t\tLogisticsPipes.log.info(\"Loaded \" + proxyName + \"Proxy\");\n\t\t} else {\n\t\t\tLogisticsPipes.log.info(\"Loaded \" + proxyName + \" DummyProxy\");\n\t\t\tif (e != null) {\n\t\t\t\t((AbstractWrapper) instance).setState(WrapperState.Exception);\n\t\t\t\t((AbstractWrapper) instance).setReason(e);\n\t\t\t} else {\n\t\t\t\t((AbstractWrapper) instance).setState(WrapperState.ModMissing);\n\t\t\t}\n\t\t}\n\t\t((AbstractWrapper) instance).setModId(modId);\n\t\t((AbstractWrapper) instance).setWrapperInterfaces(Collections.unmodifiableList(wrapperInterfacesList));\n\t\tLogisticsWrapperHandler.wrapperController.add((AbstractWrapper) instance);\n\t\treturn instance;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <T> T getWrappedSubProxy(AbstractWrapper wrapper, Class<T> interfaze, T proxy, T dummyProxy) throws SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {\n\t\tif (proxy == null) {\n\t\t\treturn null;\n\t\t}\n\t\tString proxyName = interfaze.getSimpleName().substring(1);\n\t\tString className = \"logisticspipes/asm/wrapper/generated/\" + proxyName + \"ProxyWrapper\";\n\n\t\tClass<?> clazz;\n\t\tsynchronized (lookupMap) {\n\t\t\tclazz = LogisticsWrapperHandler.lookupMap.get(className);\n\t\t\tif (clazz == null) {\n\t\t\t\tString fieldName = interfaze.getName().replace('.', '/');\n\t\t\t\t//String classFile = interfaze.getSimpleName().substring(1) + \"Wrapper.java\";\n\t\t\t\tClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n\n\t\t\t\tcw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, className, null, \"logisticspipes/asm/wrapper/AbstractSubWrapper\", new String[] { fieldName });\n\n\t\t\t\tcw.visitSource(\".LP|ASM.dynamic\", null);\n\n\t\t\t\t{\n\t\t\t\t\tFieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, \"proxy\", \"L\" + fieldName + \";\", null, null);\n\t\t\t\t\tfv.visitEnd();\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tFieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, \"dummyProxy\", \"L\" + fieldName + \";\", null, null);\n\t\t\t\t\tfv.visitEnd();\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, \"<init>\", \"(Llogisticspipes/asm/wrapper/AbstractWrapper;L\" + fieldName + \";L\" + fieldName + \";)V\", null, null);\n\t\t\t\t\tmv.visitCode();\n\t\t\t\t\tLabel l0 = new Label();\n\t\t\t\t\tmv.visitLabel(l0);\n\t\t\t\t\tmv.visitLineNumber(11, l0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\t\t\tmv.visitMethodInsn(Opcodes.INVOKESPECIAL, \"logisticspipes/asm/wrapper/AbstractSubWrapper\", \"<init>\", \"(Llogisticspipes/asm/wrapper/AbstractWrapper;)V\");\n\t\t\t\t\tLabel l1 = new Label();\n\t\t\t\t\tmv.visitLabel(l1);\n\t\t\t\t\tmv.visitLineNumber(12, l1);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 2);\n\t\t\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, className, \"dummyProxy\", \"L\" + fieldName + \";\");\n\t\t\t\t\tLabel l2 = new Label();\n\t\t\t\t\tmv.visitLabel(l2);\n\t\t\t\t\tmv.visitLineNumber(13, l2);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 3);\n\t\t\t\t\tmv.visitFieldInsn(Opcodes.PUTFIELD, className, \"proxy\", \"L\" + fieldName + \";\");\n\t\t\t\t\tLabel l3 = new Label();\n\t\t\t\t\tmv.visitLabel(l3);\n\t\t\t\t\tmv.visitLineNumber(14, l3);\n\t\t\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\t\t\tLabel l4 = new Label();\n\t\t\t\t\tmv.visitLabel(l4);\n\t\t\t\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l0, l4, 0);\n\t\t\t\t\tmv.visitLocalVariable(\"wrapper\", \"Llogisticspipes/asm/wrapper/AbstractWrapper;\", null, l0, l4, 1);\n\t\t\t\t\tmv.visitLocalVariable(\"dProxy\", \"L\" + fieldName + \";\", null, l0, l4, 2);\n\t\t\t\t\tmv.visitLocalVariable(\"iProxy\", \"L\" + fieldName + \";\", null, l0, l4, 3);\n\t\t\t\t\tmv.visitMaxs(2, 3);\n\t\t\t\t\tmv.visitEnd();\n\t\t\t\t}\n\t\t\t\tint lineAddition = 100;\n\t\t\t\tfor (Method method : interfaze.getMethods()) {\n\t\t\t\t\tLogisticsWrapperHandler.addProxyMethod(cw, method, fieldName, className, lineAddition, !wrapper.getWrapperInterfaces().contains(method.getReturnType()));\n\t\t\t\t\tlineAddition += 10;\n\t\t\t\t}\n\t\t\t\tcw.visitEnd();\n\n\t\t\t\tString lookfor = className.replace('/', '.');\n\n\t\t\t\tbyte[] bytes = cw.toByteArray();\n\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tif (LogisticsWrapperHandler.DUMP) {\n\t\t\t\t\t\tLogisticsWrapperHandler.saveGeneratedClass(bytes, lookfor, \"LP_WRAPPER_CLASSES\");\n\t\t\t\t\t}\n\t\t\t\t\tClassReader cr = new ClassReader(bytes);\n\t\t\t\t\torg.objectweb.asm.util.CheckClassAdapter.verify(cr, Launch.classLoader, false, new PrintWriter(System.err));\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tclazz = LogisticsWrapperHandler.loadClass(bytes, lookfor);\n\t\t\t\t} catch (LinkageError e) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (e.getMessage().contains(\"attempted\") && e.getMessage().contains(\"duplicate class definition\")) {\n\t\t\t\t\t\t\tClass<?> prev = Class.forName(className);\n\t\t\t\t\t\t\tSystem.err.println(e.getMessage());\n\t\t\t\t\t\t\tSystem.err.printf(\"Already loaded: %s%n\", prev);\n\t\t\t\t\t\t\tString resourcePath = className.replace('.', '/').concat(\".class\");\n\t\t\t\t\t\t\tURL classResource = Launch.classLoader.findResource(resourcePath);\n\t\t\t\t\t\t\tif (classResource != null) {\n\t\t\t\t\t\t\t\tString path = classResource.getPath();\n\t\t\t\t\t\t\t\tSystem.err.println(\"Class source: \" + path);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tSystem.err.println(\"Class source: Null\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (Exception e2) {\n\t\t\t\t\t\te2.printStackTrace();\n\t\t\t\t\t}\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t\tLogisticsWrapperHandler.lookupMap.put(className, clazz);\n\t\t\t}\n\t\t}\n\n\t\tT instance = (T) clazz.getConstructor(new Class<?>[] { AbstractWrapper.class, interfaze, interfaze }).newInstance(wrapper, dummyProxy, proxy);\n\t\t((AbstractWrapper) instance).setWrapperInterfaces(wrapper.getWrapperInterfaces());\n\t\treturn instance;\n\t}\n\n\tprivate static Class<?> loadClass(byte[] data, String lookfor) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n\t\tif (LogisticsWrapperHandler.m_defineClass == null) {\n\t\t\tLogisticsWrapperHandler.m_defineClass = ClassLoader.class.getDeclaredMethod(\"defineClass\", byte[].class, int.class, int.class);\n\t\t\tLogisticsWrapperHandler.m_defineClass.setAccessible(true);\n\t\t}\n\t\treturn (Class<?>) LogisticsWrapperHandler.m_defineClass.invoke(Launch.classLoader, data, 0, data.length);\n\t}\n\n\tprivate static void addGetTypeName(ClassWriter cw, String className, String type) {\n\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, \"getTypeName\", \"()Ljava/lang/String;\", null, null);\n\t\tmv.visitCode();\n\t\tLabel l0 = new Label();\n\t\tmv.visitLabel(l0);\n\t\tmv.visitLineNumber(31, l0);\n\t\tmv.visitLdcInsn(type);\n\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\tLabel l1 = new Label();\n\t\tmv.visitLabel(l1);\n\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l0, l1, 0);\n\t\tmv.visitMaxs(1, 1);\n\t\tmv.visitEnd();\n\t}\n\n\tprivate static void addGetName(ClassWriter cw, String className, String proxyName) {\n\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, \"getName\", \"()Ljava/lang/String;\", null, null);\n\t\tmv.visitCode();\n\t\tLabel l0 = new Label();\n\t\tmv.visitLabel(l0);\n\t\tmv.visitLineNumber(41, l0);\n\t\tmv.visitLdcInsn(proxyName);\n\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\tLabel l1 = new Label();\n\t\tmv.visitLabel(l1);\n\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l0, l1, 0);\n\t\tmv.visitMaxs(1, 1);\n\t\tmv.visitEnd();\n\t}\n\n\tprivate static void addProxyMethod(ClassWriter cw, Method method, String fieldName, String className, int lineAddition, boolean normalResult) {\n\t\tClass<?> retclazz = method.getReturnType();\n\t\tint eIndex = 1;\n\t\tStringBuilder desc = new StringBuilder(\"(\");\n\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\tdesc.append(LogisticsWrapperHandler.getClassSignature(clazz));\n\t\t\tif (clazz == long.class || clazz == double.class) {\n\t\t\t\teIndex += 2;\n\t\t\t} else {\n\t\t\t\teIndex += 1;\n\t\t\t}\n\t\t}\n\t\teIndex++;\n\t\tdesc.append(\")\");\n\t\tString resultClassL = null;\n\t\tString resultClass = null;\n\t\tint returnType;\n\t\tif (retclazz == null || retclazz == void.class) {\n\t\t\tdesc.append(\"V\");\n\t\t\treturnType = Opcodes.RETURN;\n\t\t} else if (retclazz.isPrimitive()) {\n\t\t\tdesc.append(LogisticsWrapperHandler.getPrimitiveMapping(retclazz));\n\t\t\treturnType = LogisticsWrapperHandler.getPrimitiveReturnMapping(retclazz);\n\t\t} else if (retclazz.isArray()) {\n\t\t\t// Arrays in bytecode are always typeless, like primitives\n\t\t\t// e.g. Object[] = [Ljava/lang/Object; (not L[Ljava/lang/Object;;)\n\t\t\tresultClassL = retclazz.getName().replace('.', '/');\n\t\t\tresultClass = resultClassL;\n\t\t\tdesc.append(resultClassL);\n\t\t\treturnType = Opcodes.ARETURN;\n\t\t} else {\n\t\t\tresultClassL = \"L\" + retclazz.getName().replace('.', '/') + \";\";\n\t\t\tresultClass = retclazz.getName().replace('.', '/');\n\t\t\tdesc.append(resultClassL);\n\t\t\treturnType = Opcodes.ARETURN;\n\t\t}\n\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), desc.toString(), null, null);\n\t\tmv.visitCode();\n\t\tLabel l0 = new Label();\n\t\tLabel l1 = new Label();\n\t\tLabel l2 = new Label();\n\t\tmv.visitTryCatchBlock(l0, l1, l2, \"java/lang/Exception\");\n\t\tLabel l3 = new Label();\n\t\tmv.visitTryCatchBlock(l0, l1, l3, \"java/lang/NoClassDefFoundError\");\n\t\tLabel l4 = new Label();\n\t\tmv.visitLabel(l4);\n\t\tmv.visitLineNumber(lineAddition + 1, l4);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\tif (method.isAnnotationPresent(IgnoreDisabledProxy.class) || !normalResult) {\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, \"canTryAnyway\", \"()Z\");\n\t\t} else {\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, \"isEnabled\", \"()Z\");\n\t\t}\n\t\tLabel l5 = new Label();\n\t\tmv.visitJumpInsn(Opcodes.IFEQ, l5);\n\t\tmv.visitLabel(l0);\n\t\tmv.visitLineNumber(lineAddition + 2, l0);\n\t\tif (normalResult) {\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"proxy\", \"L\" + fieldName + \";\");\n\t\t\tLogisticsWrapperHandler.addMethodParameterLoad(mv, method);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEINTERFACE, fieldName, method.getName(), desc.toString());\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitInsn(returnType);\n\t\t} else {\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitLdcInsn(Type.getType(resultClassL));\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"proxy\", \"L\" + fieldName + \";\");\n\t\t\tLogisticsWrapperHandler.addMethodParameterLoad(mv, method);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEINTERFACE, fieldName, method.getName(), desc.toString());\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"dummyProxy\", \"L\" + fieldName + \";\");\n\t\t\tLogisticsWrapperHandler.addMethodParameterLoad(mv, method);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKEINTERFACE, fieldName, method.getName(), desc.toString());\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKESTATIC, \"logisticspipes/asm/wrapper/LogisticsWrapperHandler\", \"getWrappedSubProxy\", \"(Llogisticspipes/asm/wrapper/AbstractWrapper;Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;\");\n\t\t\tmv.visitTypeInsn(Opcodes.CHECKCAST, resultClass);\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\t}\n\t\tmv.visitLabel(l2);\n\t\tmv.visitLineNumber(lineAddition + 3, l2);\n\t\tmv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { \"java/lang/Exception\" });\n\t\tmv.visitVarInsn(Opcodes.ASTORE, eIndex);\n\t\tLabel l6 = new Label();\n\t\tmv.visitLabel(l6);\n\t\tmv.visitLineNumber(lineAddition + 4, l6);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, eIndex);\n\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, \"handleException\", \"(Ljava/lang/Throwable;)V\");\n\t\tLabel l7 = new Label();\n\t\tmv.visitLabel(l7);\n\t\tmv.visitJumpInsn(Opcodes.GOTO, l5);\n\t\tmv.visitLabel(l3);\n\t\tmv.visitLineNumber(lineAddition + 5, l3);\n\t\tmv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] { \"java/lang/NoClassDefFoundError\" });\n\t\tmv.visitVarInsn(Opcodes.ASTORE, eIndex);\n\t\tLabel l8 = new Label();\n\t\tmv.visitLabel(l8);\n\t\tmv.visitLineNumber(lineAddition + 6, l8);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, eIndex);\n\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, \"handleException\", \"(Ljava/lang/Throwable;)V\");\n\t\tmv.visitLabel(l5);\n\t\tmv.visitLineNumber(lineAddition + 7, l5);\n\t\tmv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\tmv.visitFieldInsn(Opcodes.GETFIELD, className, \"dummyProxy\", \"L\" + fieldName + \";\");\n\t\tLogisticsWrapperHandler.addMethodParameterLoad(mv, method);\n\t\tmv.visitMethodInsn(Opcodes.INVOKEINTERFACE, fieldName, method.getName(), desc.toString());\n\t\tmv.visitInsn(returnType);\n\t\tLabel l9 = new Label();\n\t\tmv.visitLabel(l9);\n\t\tmv.visitLocalVariable(\"this\", \"L\" + className + \";\", null, l4, l9, 0);\n\t\tLogisticsWrapperHandler.addParameterVars(mv, method, l4, l9);\n\t\tmv.visitLocalVariable(\"e\", \"Ljava/lang/Exception;\", null, l6, l7, eIndex);\n\t\tmv.visitLocalVariable(\"e\", \"Ljava/lang/NoClassDefFoundError;\", null, l8, l5, eIndex);\n\t\tmv.visitMaxs(0, 0);\n\t\tmv.visitEnd();\n\t}\n\n\tprivate static void addMethodParameterLoad(MethodVisitor mv, Method method) {\n\t\tint i = 1;\n\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\tif (clazz.isPrimitive()) {\n\t\t\t\tif (clazz == int.class || clazz == boolean.class || clazz == short.class || clazz == byte.class) {\n\t\t\t\t\tmv.visitVarInsn(Opcodes.ILOAD, i);\n\t\t\t\t\ti++;\n\t\t\t\t} else if (clazz == long.class) {\n\t\t\t\t\tmv.visitVarInsn(Opcodes.LLOAD, i);\n\t\t\t\t\ti += 2;\n\t\t\t\t} else if (clazz == float.class) {\n\t\t\t\t\tmv.visitVarInsn(Opcodes.FLOAD, i);\n\t\t\t\t\ti++;\n\t\t\t\t} else if (clazz == double.class) {\n\t\t\t\t\tmv.visitVarInsn(Opcodes.DLOAD, i);\n\t\t\t\t\ti += 2;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new UnsupportedOperationException(\"Unmapped clazz: \" + clazz.getName());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmv.visitVarInsn(Opcodes.ALOAD, i);\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static void addParameterVars(MethodVisitor mv, Method method, Label l3, Label l8) {\n\t\tint i = 1;\n\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\tmv.visitLocalVariable(\"par\" + i, LogisticsWrapperHandler.getClassSignature(clazz), null, l3, l8, i);\n\t\t\tif (clazz == long.class || clazz == double.class) {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t}\n\n\tprivate static String getPrimitiveMapping(Class<?> clazz) {\n\t\tif (clazz == int.class) {\n\t\t\treturn \"I\";\n\t\t} else if (clazz == long.class) {\n\t\t\treturn \"J\";\n\t\t} else if (clazz == float.class) {\n\t\t\treturn \"F\";\n\t\t} else if (clazz == double.class) {\n\t\t\treturn \"D\";\n\t\t} else if (clazz == boolean.class) {\n\t\t\treturn \"Z\";\n\t\t} else if (clazz == short.class) {\n\t\t\treturn \"S\";\n\t\t} else if (clazz == byte.class) {\n\t\t\treturn \"B\";\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(\"Unmapped clazz: \" + clazz.getName());\n\t\t}\n\t}\n\n\tprivate static int getPrimitiveReturnMapping(Class<?> clazz) {\n\t\tif (clazz == int.class || clazz == boolean.class || clazz == short.class || clazz == byte.class) {\n\t\t\treturn Opcodes.IRETURN;\n\t\t} else if (clazz == long.class) {\n\t\t\treturn Opcodes.LRETURN;\n\t\t} else if (clazz == float.class) {\n\t\t\treturn Opcodes.FRETURN;\n\t\t} else if (clazz == double.class) {\n\t\t\treturn Opcodes.DRETURN;\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(\"Unmapped clazz: \" + clazz.getName());\n\t\t}\n\t}\n\n\tprivate static String getClassSignature(Class<?> clazz) {\n\t\tif (clazz.isPrimitive()) {\n\t\t\treturn LogisticsWrapperHandler.getPrimitiveMapping(clazz);\n\t\t} else {\n\t\t\tif (clazz.isArray()) {\n\t\t\t\treturn clazz.getName().replace('.', '/');\n\t\t\t} else {\n\t\t\t\treturn \"L\" + clazz.getName().replace('.', '/') + \";\";\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static File tempFolder = null;\n\n\tpublic static void saveGeneratedClass(final byte[] data, final String transformedName, final String folder) {\n\t\tif (LogisticsWrapperHandler.tempFolder == null) {\n\t\t\tLogisticsWrapperHandler.tempFolder = new File(Launch.minecraftHome, folder);\n\t\t}\n\n\t\tfinal File outFile = new File(LogisticsWrapperHandler.tempFolder, transformedName.replace('.', File.separatorChar) + \".class\");\n\t\tfinal File outDir = outFile.getParentFile();\n\n\t\tif (!outDir.exists()) {\n\t\t\toutDir.mkdirs();\n\t\t}\n\n\t\tif (outFile.exists()) {\n\t\t\toutFile.delete();\n\t\t}\n\n\t\ttry {\n\t\t\tLogWrapper.fine(\"Saving transformed class \\\"%s\\\" to \\\"%s\\\"\", transformedName, outFile.getAbsolutePath().replace('\\\\', '/'));\n\n\t\t\tfinal OutputStream output = new FileOutputStream(outFile);\n\t\t\toutput.write(data);\n\t\t\toutput.close();\n\t\t} catch (IOException ex) {\n\t\t\tLogWrapper.log(Level.WARN, ex, \"Could not save transformed class \\\"%s\\\"\", transformedName);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/asm/wrapper/WrapperState.java",
    "content": "package logisticspipes.asm.wrapper;\n\npublic enum WrapperState {\n\tEnabled,\n\tModMissing,\n\tException\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/BlockDummy.java",
    "content": "package logisticspipes.blocks;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.properties.PropertyInteger;\nimport net.minecraft.block.state.BlockStateContainer;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport logisticspipes.items.LogisticsSolidBlockItem;\n\n/**\n * A dummy block used for backwards compat to before the {@link LogisticsSolidBlock} split.\n * TODO remove in 1.13\n */\npublic class BlockDummy extends Block {\n\n\tpublic static final PropertyInteger PROP_BLOCKTYPE = PropertyInteger.create(\"block_sub_type\", 0, 11);\n\n\tstatic final Map<Integer, LogisticsSolidBlock> updateBlockMap = new HashMap<>();\n\tpublic static final Map<Integer, LogisticsSolidBlockItem> updateItemMap = new HashMap<>();\n\n\tpublic BlockDummy() {\n\t\tsuper(Material.IRON);\n\t\tsetBlockUnbreakable();\n\t}\n\n\t@Nonnull\n\t@Override\n\tprotected BlockStateContainer createBlockState() {\n\t\treturn new BlockStateContainer(this, PROP_BLOCKTYPE);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBlockState getStateFromMeta(int meta) {\n\t\treturn getDefaultState().withProperty(PROP_BLOCKTYPE, meta);\n\t}\n\n\t@Override\n\tpublic int getMetaFromState(IBlockState state) {\n\t\treturn state.getValue(PROP_BLOCKTYPE);\n\t}\n\n\t@Override\n\tpublic boolean hasTileEntity(IBlockState state) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void breakBlock(@Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state) {}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/LogisticsProgramCompilerTileEntity.java",
    "content": "package logisticspipes.blocks;\n\nimport java.util.HashSet;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Set;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagString;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\n\nimport lombok.Getter;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.items.ItemLogisticsProgrammer;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.guis.block.ProgramCompilerGui;\nimport logisticspipes.network.packets.block.CompilerStatusPacket;\nimport logisticspipes.pipes.PipeItemsBasicLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.SimpleStackInventory;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsProgramCompilerTileEntity extends LogisticsSolidTileEntity implements IGuiTileEntity, IGuiOpenControler {\n\n\tpublic static class ProgrammCategories {\n\n\t\tpublic static final ResourceLocation BASIC = new ResourceLocation(\"logisticspipes\", \"compilercategory.basic\");\n\t\tpublic static final ResourceLocation TIER_2 = new ResourceLocation(\"logisticspipes\", \"compilercategory.tier_2\");\n\t\tpublic static final ResourceLocation FLUID = new ResourceLocation(\"logisticspipes\", \"compilercategory.fluid\");\n\t\tpublic static final ResourceLocation TIER_3 = new ResourceLocation(\"logisticspipes\", \"compilercategory.tier_3\");\n\t\tpublic static final ResourceLocation CHASSIS = new ResourceLocation(\"logisticspipes\", \"compilercategory.chassis\");\n\t\tpublic static final ResourceLocation CHASSIS_2 = new ResourceLocation(\"logisticspipes\", \"compilercategory.chassis_2\");\n\t\tpublic static final ResourceLocation CHASSIS_3 = new ResourceLocation(\"logisticspipes\", \"compilercategory.chassis_3\");\n\t\tpublic static final ResourceLocation MODDED = new ResourceLocation(\"logisticspipes\", \"compilercategory.modded\");\n\n\t\tstatic {\n\t\t\t//Force the order of keys\n\t\t\tprogramByCategory.put(BASIC, new HashSet<>());\n\t\t\tprogramByCategory.put(TIER_2, new HashSet<>());\n\t\t\tprogramByCategory.put(FLUID, new HashSet<>());\n\t\t\tprogramByCategory.put(TIER_3, new HashSet<>());\n\t\t\tprogramByCategory.put(CHASSIS, new HashSet<>());\n\t\t\tprogramByCategory.put(CHASSIS_2, new HashSet<>());\n\t\t\tprogramByCategory.put(CHASSIS_3, new HashSet<>());\n\t\t\tprogramByCategory.put(MODDED, new HashSet<>());\n\t\t}\n\t}\n\n\tpublic static final Map<ResourceLocation, Set<ResourceLocation>> programByCategory = new LinkedHashMap<>();\n\tprivate final PlayerCollectionList playerList = new PlayerCollectionList();\n\tprivate String taskType = \"\";\n\t@Getter\n\tprivate ResourceLocation currentTask = null;\n\t@Getter\n\tprivate double taskProgress = 0;\n\t@Getter\n\tprivate boolean wasAbleToConsumePower = false;\n\n\t@Getter\n\tprivate SimpleStackInventory inventory = new SimpleStackInventory(2, \"programcompilerinv\", 64);\n\n\t@Override\n\tpublic CoordinatesGuiProvider getGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ProgramCompilerGui.class);\n\t}\n\n\tpublic NBTTagList getNBTTagListForKey(String key) {\n\t\tNBTTagCompound nbt = this.getInventory().getStackInSlot(0).getTagCompound();\n\t\tif (nbt == null) {\n\t\t\tthis.getInventory().getStackInSlot(0).setTagCompound(new NBTTagCompound());\n\t\t\tnbt = this.getInventory().getStackInSlot(0).getTagCompound();\n\t\t}\n\n\t\tif (!nbt.hasKey(key)) {\n\t\t\tNBTTagList list = new NBTTagList();\n\t\t\tnbt.setTag(key, list);\n\t\t}\n\t\treturn nbt.getTagList(key, 8 /* String */);\n\t}\n\n\tpublic void triggerNewTask(ResourceLocation category, String taskType) {\n\t\tif (currentTask != null) return;\n\t\tthis.taskType = taskType;\n\t\tcurrentTask = category;\n\t\ttaskProgress = 0;\n\t\twasAbleToConsumePower = true;\n\t\tupdateClient();\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tplayerList.add(player);\n\t\tMainProxy.sendPacketToPlayer(getClientUpdatePacket(), player);\n\t}\n\n\tprivate CoordinatesPacket getClientUpdatePacket() {\n\t\treturn PacketHandler.getPacket(CompilerStatusPacket.class)\n\t\t\t\t.setCategory(currentTask)\n\t\t\t\t.setProgress(taskProgress)\n\t\t\t\t.setWasAbleToConsumePower(wasAbleToConsumePower)\n\t\t\t\t.setDisk(getInventory().getStackInSlot(0))\n\t\t\t\t.setProgrammer(getInventory().getStackInSlot(1))\n\t\t\t\t.setTilePos(this);\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tplayerList.remove(player);\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tsuper.update();\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tif (currentTask != null) {\n\t\t\t\twasAbleToConsumePower = false;\n\t\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\t\tif (dir == EnumFacing.UP) continue;\n\t\t\t\t\tDoubleCoordinates pos = CoordinateUtils.add(new DoubleCoordinates(this), dir);\n\t\t\t\t\tTileEntity tile = pos.getTileEntity(getWorld());\n\t\t\t\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tLogisticsTileGenericPipe tPipe = (LogisticsTileGenericPipe) tile;\n\t\t\t\t\tif (!(tPipe.pipe.getClass() == PipeItemsBasicLogistics.class)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tCoreRoutedPipe pipe = (CoreRoutedPipe) tPipe.pipe;\n\t\t\t\t\tif (pipe.useEnergy(10)) {\n\t\t\t\t\t\tswitch (taskType) {\n\t\t\t\t\t\t\tcase \"category\":\n\t\t\t\t\t\t\t\ttaskProgress += 0.0005 * Configs.COMPILER_SPEED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"program\":\n\t\t\t\t\t\t\t\ttaskProgress += 0.0025 * Configs.COMPILER_SPEED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"flash\":\n\t\t\t\t\t\t\t\ttaskProgress += 0.01 * Configs.COMPILER_SPEED;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\ttaskProgress = 1;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\twasAbleToConsumePower = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (taskProgress >= 1) {\n\t\t\t\t\tswitch (taskType) {\n\t\t\t\t\t\tcase \"category\": {\n\t\t\t\t\t\t\tNBTTagList list = getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\t\t\t\tlist.appendTag(new NBTTagString(currentTask.toString()));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase \"program\": {\n\t\t\t\t\t\t\tNBTTagList list = getNBTTagListForKey(\"compilerPrograms\");\n\t\t\t\t\t\t\tlist.appendTag(new NBTTagString(currentTask.toString()));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase \"flash\":\n\t\t\t\t\t\t\tif (!getInventory().getStackInSlot(1).isEmpty()) {\n\t\t\t\t\t\t\t\tItemStack programmer = getInventory().getStackInSlot(1);\n\t\t\t\t\t\t\t\tif (!programmer.hasTagCompound()) {\n\t\t\t\t\t\t\t\t\tprogrammer.setTagCompound(new NBTTagCompound());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tassert programmer.getTagCompound() != null;\n\t\t\t\t\t\t\t\tprogrammer.getTagCompound()\n\t\t\t\t\t\t\t\t\t\t.setString(ItemLogisticsProgrammer.RECIPE_TARGET, currentTask.toString());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow new UnsupportedOperationException(taskType);\n\t\t\t\t\t}\n\n\t\t\t\t\ttaskType = \"\";\n\t\t\t\t\tcurrentTask = null;\n\t\t\t\t\ttaskProgress = 0;\n\t\t\t\t\twasAbleToConsumePower = false;\n\t\t\t\t}\n\t\t\t\tupdateClient();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void updateClient() {\n\t\tMainProxy.sendToPlayerList(getClientUpdatePacket(), playerList);\n\t}\n\n\t@Override\n\tpublic void onBlockBreak() {\n\t\tinventory.dropContents(world, getPos());\n\t}\n\n\tpublic void setStateOnClient(CompilerStatusPacket compilerStatusPacket) {\n\t\tgetInventory().setInventorySlotContents(0, compilerStatusPacket.getDisk());\n\t\tgetInventory().setInventorySlotContents(1, compilerStatusPacket.getProgrammer());\n\t\tcurrentTask = compilerStatusPacket.getCategory();\n\t\ttaskProgress = compilerStatusPacket.getProgress();\n\t\twasAbleToConsumePower = compilerStatusPacket.isWasAbleToConsumePower();\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tinventory.readFromNBT(nbt, \"programcompilerinv\");\n\t\tsuper.readFromNBT(nbt);\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tinventory.writeToNBT(nbt, \"programcompilerinv\");\n\t\treturn super.writeToNBT(nbt);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/LogisticsSecurityTileEntity.java",
    "content": "package logisticspipes.blocks;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.crash.CrashReportCategory;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTBase;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagInt;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.IRoutedPowerProvider;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.interfaces.ISecurityProvider;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.guis.block.SecurityStationGui;\nimport logisticspipes.network.packets.block.SecurityStationAutoDestroy;\nimport logisticspipes.network.packets.block.SecurityStationCC;\nimport logisticspipes.network.packets.block.SecurityStationCCIDs;\nimport logisticspipes.network.packets.block.SecurityStationId;\nimport logisticspipes.network.packets.block.SecurityStationOpenPlayer;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\npublic class LogisticsSecurityTileEntity extends LogisticsSolidTileEntity implements IGuiOpenControler, ISecurityProvider, IGuiTileEntity {\n\n\tpublic ItemIdentifierInventory inv = new ItemIdentifierInventory(1, \"ID Slots\", 64);\n\tprivate PlayerCollectionList listener = new PlayerCollectionList();\n\tprivate UUID secId = null;\n\tprivate Map<String, SecuritySettings> settingsList = new HashMap<>();\n\tpublic List<Integer> excludedCC = new ArrayList<>();\n\tpublic boolean allowCC = false;\n\tpublic boolean allowAutoDestroy = false;\n\n\tpublic static PlayerCollectionList byPassed = new PlayerCollectionList();\n\tpublic static final SecuritySettings allowAll = new SecuritySettings(\"\");\n\n\tstatic {\n\t\tLogisticsSecurityTileEntity.allowAll.openGui = true;\n\t\tLogisticsSecurityTileEntity.allowAll.openRequest = true;\n\t\tLogisticsSecurityTileEntity.allowAll.openUpgrades = true;\n\t\tLogisticsSecurityTileEntity.allowAll.openNetworkMonitor = true;\n\t\tLogisticsSecurityTileEntity.allowAll.removePipes = true;\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tSimpleServiceLocator.securityStationManager.remove(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tSimpleServiceLocator.securityStationManager.add(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tSimpleServiceLocator.securityStationManager.remove(this);\n\t\t}\n\t}\n\n\tpublic void deauthorizeStation() {\n\t\tSimpleServiceLocator.securityStationManager.deauthorizeUUID(getSecId());\n\t}\n\n\tpublic void authorizeStation() {\n\t\tSimpleServiceLocator.securityStationManager.authorizeUUID(getSecId());\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SecurityStationCC.class).setInteger(allowCC ? 1 : 0).setBlockPos(pos), player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SecurityStationAutoDestroy.class).setInteger(allowAutoDestroy ? 1 : 0).setBlockPos(pos), player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SecurityStationId.class).setUuid(getSecId()).setBlockPos(pos), player);\n\t\tSimpleServiceLocator.securityStationManager.sendClientAuthorizationList();\n\t\tlistener.add(player);\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tlistener.remove(player);\n\t}\n\n\tpublic UUID getSecId() {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (secId == null) {\n\t\t\t\tsecId = UUID.randomUUID();\n\t\t\t}\n\t\t}\n\t\treturn secId;\n\t}\n\n\tpublic void setClientUUID(UUID id) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tsecId = id;\n\t\t}\n\t}\n\n\tpublic void setClientCC(boolean flag) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tallowCC = flag;\n\t\t}\n\t}\n\n\tpublic void setClientDestroy(boolean flag) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tallowAutoDestroy = flag;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tsuper.readFromNBT(par1nbtTagCompound);\n\t\tif (par1nbtTagCompound.hasKey(\"UUID\")) {\n\t\t\tsecId = UUID.fromString(par1nbtTagCompound.getString(\"UUID\"));\n\t\t}\n\t\tallowCC = par1nbtTagCompound.getBoolean(\"allowCC\");\n\t\tallowAutoDestroy = par1nbtTagCompound.getBoolean(\"allowAutoDestroy\");\n\t\tinv.readFromNBT(par1nbtTagCompound);\n\t\tsettingsList.clear();\n\t\tNBTTagList list = par1nbtTagCompound.getTagList(\"settings\", 10);\n\t\twhile (list.tagCount() > 0) {\n\t\t\tNBTBase base = list.removeTag(0);\n\t\t\tString name = ((NBTTagCompound) base).getString(\"name\");\n\t\t\tNBTTagCompound value = ((NBTTagCompound) base).getCompoundTag(\"content\");\n\t\t\tSecuritySettings settings = new SecuritySettings(name);\n\t\t\tsettings.readFromNBT(value);\n\t\t\tsettingsList.put(name, settings);\n\t\t}\n\t\texcludedCC.clear();\n\t\tlist = par1nbtTagCompound.getTagList(\"excludedCC\", 3);\n\t\twhile (list.tagCount() > 0) {\n\t\t\tNBTBase base = list.removeTag(0);\n\t\t\texcludedCC.add(((NBTTagInt) base).getInt());\n\t\t}\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tpar1nbtTagCompound = super.writeToNBT(par1nbtTagCompound);\n\t\tpar1nbtTagCompound.setString(\"UUID\", getSecId().toString());\n\t\tpar1nbtTagCompound.setBoolean(\"allowCC\", allowCC);\n\t\tpar1nbtTagCompound.setBoolean(\"allowAutoDestroy\", allowAutoDestroy);\n\t\tinv.writeToNBT(par1nbtTagCompound);\n\t\tNBTTagList list = new NBTTagList();\n\t\tfor (Entry<String, SecuritySettings> entry : settingsList.entrySet()) {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tnbt.setString(\"name\", entry.getKey());\n\t\t\tNBTTagCompound value = new NBTTagCompound();\n\t\t\tentry.getValue().writeToNBT(value);\n\t\t\tnbt.setTag(\"content\", value);\n\t\t\tlist.appendTag(nbt);\n\t\t}\n\t\tpar1nbtTagCompound.setTag(\"settings\", list);\n\t\tlist = new NBTTagList();\n\t\tfor (Integer i : excludedCC) {\n\t\t\tlist.appendTag(new NBTTagInt(i));\n\t\t}\n\t\tpar1nbtTagCompound.setTag(\"excludedCC\", list);\n\t\treturn par1nbtTagCompound;\n\t}\n\n\tpublic void buttonFreqCard(int integer, EntityPlayer player) {\n\t\tswitch (integer) {\n\t\t\tcase 0: //--\n\t\t\t\tinv.clearInventorySlotContents(0);\n\t\t\t\tbreak;\n\t\t\tcase 1: //-\n\t\t\t\tinv.decrStackSize(0, 1);\n\t\t\t\tbreak;\n\t\t\tcase 2: //+\n\t\t\t\tif (!useEnergy(10)) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (inv.getIDStackInSlot(0) == null) {\n\t\t\t\t\tItemStack stack = new ItemStack(LPItems.itemCard, 1, LogisticsItemCard.SEC_CARD);\n\t\t\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t\t\t\tObjects.requireNonNull(stack.getTagCompound()).setString(\"UUID\", getSecId().toString());\n\t\t\t\t\tinv.setInventorySlotContents(0, stack);\n\t\t\t\t} else {\n\t\t\t\t\tItemStack slot = inv.getStackInSlot(0);\n\t\t\t\t\tif (slot.getCount() < 64) {\n\t\t\t\t\t\tslot.grow(1);\n\t\t\t\t\t\tslot.setTagCompound(new NBTTagCompound());\n\t\t\t\t\t\tObjects.requireNonNull(slot.getTagCompound()).setString(\"UUID\", getSecId().toString());\n\t\t\t\t\t\tinv.setInventorySlotContents(0, slot);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3: //++\n\t\t\t\tif (!useEnergy(640)) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tItemStack stack = new ItemStack(LPItems.itemCard, 64, LogisticsItemCard.SEC_CARD);\n\t\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t\t\tObjects.requireNonNull(stack.getTagCompound()).setString(\"UUID\", getSecId().toString());\n\t\t\t\tinv.setInventorySlotContents(0, stack);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tpublic void handleOpenSecurityPlayer(EntityPlayer player, @Nonnull String string) {\n\t\tSecuritySettings setting = settingsList.get(string);\n\t\tif (setting == null) {\n\t\t\tif (string.isEmpty()) return;\n\t\t\tsetting = new SecuritySettings(string);\n\t\t\tsettingsList.put(string, setting);\n\t\t}\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\tsetting.writeToNBT(nbt);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SecurityStationOpenPlayer.class).setTag(nbt), player);\n\t}\n\n\tpublic void saveNewSecuritySettings(NBTTagCompound tag) {\n\t\tSecuritySettings setting = settingsList.get(tag.getString(\"name\"));\n\t\tif (setting == null) {\n\t\t\tsetting = new SecuritySettings(tag.getString(\"name\"));\n\t\t\tsettingsList.put(tag.getString(\"name\"), setting);\n\t\t}\n\t\tsetting.readFromNBT(tag);\n\t}\n\n\tpublic SecuritySettings getSecuritySettingsForPlayer(EntityPlayer entityplayer, boolean usePower) {\n\t\tif (LogisticsSecurityTileEntity.byPassed.contains(entityplayer)) {\n\t\t\treturn LogisticsSecurityTileEntity.allowAll;\n\t\t}\n\t\tif (usePower && !useEnergy(10)) {\n\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\treturn new SecuritySettings(\"No Energy\");\n\t\t}\n\t\tSecuritySettings setting = settingsList.get(entityplayer.getDisplayNameString());\n\t\t//TODO Change to GameProfile based Authentication\n\t\tif (setting == null) {\n\t\t\tsetting = new SecuritySettings(entityplayer.getDisplayNameString());\n\t\t\tsettingsList.put(entityplayer.getDisplayNameString(), setting);\n\t\t}\n\t\treturn setting;\n\t}\n\n\tpublic void changeCC() {\n\t\tallowCC = !allowCC;\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(SecurityStationCC.class).setInteger(allowCC ? 1 : 0).setBlockPos(pos), listener);\n\t}\n\n\tpublic void changeDestroy() {\n\t\tallowAutoDestroy = !allowAutoDestroy;\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(SecurityStationAutoDestroy.class).setInteger(allowAutoDestroy ? 1 : 0).setBlockPos(pos), listener);\n\t}\n\n\tpublic void addCCToList(Integer id) {\n\t\tif (!excludedCC.contains(id)) {\n\t\t\texcludedCC.add(id);\n\t\t}\n\t\tCollections.sort(excludedCC);\n\t}\n\n\tpublic void removeCCFromList(Integer id) {\n\t\texcludedCC.remove(id);\n\t}\n\n\tpublic void requestList(EntityPlayer player) {\n\t\tNBTTagCompound tag = new NBTTagCompound();\n\t\tNBTTagList list = new NBTTagList();\n\t\tfor (Integer i : excludedCC) {\n\t\t\tlist.appendTag(new NBTTagInt(i));\n\t\t}\n\t\ttag.setTag(\"list\", list);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SecurityStationCCIDs.class).setTag(tag).setBlockPos(pos), player);\n\t}\n\n\tpublic void handleListPacket(NBTTagCompound tag) {\n\t\texcludedCC.clear();\n\t\tNBTTagList list = tag.getTagList(\"list\", 3);\n\t\twhile (list.tagCount() > 0) {\n\t\t\tNBTBase base = list.removeTag(0);\n\t\t\texcludedCC.add(((NBTTagInt) base).getInt());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean getAllowCC(int id) {\n\t\tif (!useEnergy(10)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn allowCC != excludedCC.contains(id);\n\t}\n\n\t@Override\n\tpublic boolean canAutomatedDestroy() {\n\t\tif (!useEnergy(10)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn allowAutoDestroy;\n\t}\n\n\tprivate boolean useEnergy(int amount) {\n\t\tfor (int i = 0; i < 4; i++) {\n\t\t\tTileEntity tile = getWorld().getTileEntity(getPos().offset(EnumFacing.VALUES[i + 2]));\n\t\t\tif (tile instanceof IRoutedPowerProvider) {\n\t\t\t\tif (((IRoutedPowerProvider) tile).useEnergy(amount)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\tif (((LogisticsTileGenericPipe) tile).pipe instanceof IRoutedPowerProvider) {\n\t\t\t\t\tif (((IRoutedPowerProvider) ((LogisticsTileGenericPipe) tile).pipe).useEnergy(amount)) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void addInfoToCrashReport(CrashReportCategory par1CrashReportCategory) {\n\t\tsuper.addInfoToCrashReport(par1CrashReportCategory);\n\t\tpar1CrashReportCategory.addCrashSection(\"LP-Version\", LogisticsPipes.getVersionString());\n\t}\n\n\t@Override\n\tpublic CoordinatesGuiProvider getGuiProvider() {\n\t\treturn NewGuiHandler.getGui(SecurityStationGui.class);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/LogisticsSolidBlock.java",
    "content": "package logisticspipes.blocks;\n\nimport java.util.Arrays;\nimport java.util.Map;\nimport java.util.function.Supplier;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.properties.IProperty;\nimport net.minecraft.block.properties.PropertyBool;\nimport net.minecraft.block.properties.PropertyInteger;\nimport net.minecraft.block.state.BlockStateContainer;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsIC2PowerProviderTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsRFPowerProviderTileEntity;\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.interfaces.IRotationProvider;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\n\npublic class LogisticsSolidBlock extends Block {\n\n\tpublic static final PropertyInteger rotationProperty = PropertyInteger.create(\"rotation\", 0, 3);\n\tpublic static final PropertyBool active = PropertyBool.create(\"active\");\n\tpublic static final Map<EnumFacing, PropertyBool> connectionPropertys = Arrays.stream(EnumFacing.values()).collect(Collectors.toMap(key -> key, key -> PropertyBool.create(\"connection_\" + key.ordinal())));\n\n\t@Getter\n\tprivate final Type type;\n\n\tpublic enum Type {\n\t\tLOGISTICS_POWER_JUNCTION(1, LogisticsPowerJunctionTileEntity::new),\n\t\tLOGISTICS_SECURITY_STATION(2, LogisticsSecurityTileEntity::new),\n\t\tLOGISTICS_AUTOCRAFTING_TABLE(3, LogisticsCraftingTableTileEntity::new),\n\t\tLOGISTICS_FUZZYCRAFTING_TABLE(4, LogisticsCraftingTableTileEntity::new),\n\t\tLOGISTICS_STATISTICS_TABLE(5, LogisticsStatisticsTileEntity::new),\n\n\t\t// Power Provider\n\t\tLOGISTICS_RF_POWERPROVIDER(10, LogisticsRFPowerProviderTileEntity::new),\n\t\tLOGISTICS_IC2_POWERPROVIDER(11, LogisticsIC2PowerProviderTileEntity::new),\n\t\tLOGISTICS_BC_POWERPROVIDER(12),\n\n\t\tLOGISTICS_PROGRAM_COMPILER(14, LogisticsProgramCompilerTileEntity::new),\n\n\t\tLOGISTICS_BLOCK_FRAME(15);\n\n\t\t// TODO backwards compat, remove with 1.13\n\t\t@Getter\n\t\tint meta;\n\n\t\t@Getter\n\t\tboolean hasActiveTexture;\n\n\t\t@Nullable\n\t\tprivate final Supplier<TileEntity> teConstructor;\n\n\t\tType(int meta) {\n\t\t\tthis(meta, null, false);\n\t\t}\n\n\t\tType(int meta, @Nullable Supplier<TileEntity> teConstructor) {\n\t\t\tthis(meta, teConstructor, false);\n\t\t}\n\n\t\tType(int meta, @Nullable Supplier<TileEntity> teConstructor, boolean hasActiveTexture) {\n\t\t\tthis.meta = meta;\n\t\t\tthis.teConstructor = teConstructor;\n\t\t\tthis.hasActiveTexture = hasActiveTexture;\n\t\t}\n\n\t\tpublic boolean hasTE() {\n\t\t\treturn teConstructor != null;\n\t\t}\n\n\t\tpublic TileEntity createTE() {\n\t\t\tif (!hasTE()) throw new UnsupportedOperationException(\"This block type has no tile entity!\");\n\n\t\t\tassert teConstructor != null;\n\t\t\treturn teConstructor.get();\n\t\t}\n\n\t}\n\n\tpublic LogisticsSolidBlock(Type type) {\n\t\tsuper(Material.IRON);\n\t\tthis.type = type;\n\t\tsetHardness(6.0F);\n\t\tsetCreativeTab(LogisticsPipes.CREATIVE_TAB_LP);\n\t\tBlockDummy.updateBlockMap.put(type.getMeta(), this);\n\t}\n\n\t@Override\n\tpublic void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) {\n\t\tsuper.onNeighborChange(world, pos, neighbor);\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsSolidTileEntity) {\n\t\t\t((LogisticsSolidTileEntity) tile).notifyOfBlockChange();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {\n\t\tif (!playerIn.isSneaking()) {\n\t\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\t\tif (tile instanceof IGuiTileEntity) {\n\t\t\t\tif (MainProxy.isServer(playerIn.world)) {\n\t\t\t\t\t((IGuiTileEntity) tile).getGuiProvider().setTilePos(tile).open(playerIn);\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, @Nonnull ItemStack stack) {\n\t\tsuper.onBlockPlacedBy(world, pos, state, placer, stack);\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsCraftingTableTileEntity) {\n\t\t\t((LogisticsCraftingTableTileEntity) tile).placedBy(placer);\n\t\t}\n\t\tif (tile instanceof IRotationProvider) {\n\t\t\t((IRotationProvider) tile).setFacing(placer.getHorizontalFacing().getOpposite());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void breakBlock(World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state) {\n\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsSolidTileEntity) {\n\t\t\t((LogisticsSolidTileEntity) tile).onBlockBreak();\n\t\t}\n\t\tsuper.breakBlock(worldIn, pos, state);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic TileEntity createTileEntity(@Nonnull World world, @Nonnull IBlockState state) {\n\t\tif (!type.hasTE()) return null;\n\t\treturn type.createTE();\n\t}\n\n\t@Override\n\tpublic boolean hasTileEntity(IBlockState state) {\n\t\treturn type.hasTE();\n\t}\n\n\t@Nonnull\n\t@Override\n\tprotected BlockStateContainer createBlockState() {\n\t\treturn new BlockStateContainer.Builder(this)\n\t\t\t\t.add(rotationProperty)\n\t\t\t\t.add(active)\n\t\t\t\t.add(connectionPropertys.values().toArray(new IProperty[0]))\n\t\t\t\t.build();\n\t}\n\n\t@Override\n\tpublic int getMetaFromState(IBlockState state) {\n\t\treturn 0;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess worldIn, BlockPos pos) {\n\t\tstate = super.getActualState(state, worldIn, pos);\n\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsSolidTileEntity) {\n\t\t\tLogisticsSolidTileEntity ste = (LogisticsSolidTileEntity) tile;\n\t\t\tint rotation = ste.getRotation();\n\t\t\tstate = state\n\t\t\t\t\t.withProperty(rotationProperty, Math.min(Math.max(rotation, 0), 3))\n\t\t\t\t\t.withProperty(active, ste.isActive());\n\t\t}\n\n\t\tif (tile != null) {\n\t\t\tfor (EnumFacing side : EnumFacing.VALUES) {\n\t\t\t\tboolean render = true;\n\t\t\t\tTileEntity sideTile = worldIn.getTileEntity(pos.offset(side));\n\t\t\t\tif (sideTile instanceof LogisticsTileGenericPipe) {\n\t\t\t\t\tLogisticsTileGenericPipe tilePipe = (LogisticsTileGenericPipe) sideTile;\n\t\t\t\t\tif (tilePipe.renderState.pipeConnectionMatrix.isConnected(side.getOpposite())) {\n\t\t\t\t\t\trender = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstate = state.withProperty(connectionPropertys.get(side), render);\n\t\t\t}\n\t\t}\n\n\t\treturn state;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/LogisticsSolidTileEntity.java",
    "content": "package logisticspipes.blocks;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ITickable;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport li.cil.oc.api.machine.Arguments;\nimport li.cil.oc.api.machine.Context;\nimport li.cil.oc.api.network.Environment;\nimport li.cil.oc.api.network.ManagedPeripheral;\nimport li.cil.oc.api.network.Message;\nimport li.cil.oc.api.network.Node;\nimport li.cil.oc.api.network.SidedEnvironment;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.ModDependentField;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.interfaces.IRotationProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.RequestRotationPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\nimport logisticspipes.proxy.opencomputers.IOCTile;\nimport logisticspipes.proxy.opencomputers.asm.BaseWrapperClass;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\n@ModDependentInterface(modId = { LPConstants.openComputersModID, LPConstants.openComputersModID, LPConstants.openComputersModID }, interfacePath = { \"li.cil.oc.api.network.ManagedPeripheral\", \"li.cil.oc.api.network.Environment\", \"li.cil.oc.api.network.SidedEnvironment\" })\n@CCType(name = \"LogisticsSolidBlock\")\npublic class LogisticsSolidTileEntity extends TileEntity implements ITickable, ILPCCTypeHolder, IRotationProvider, ManagedPeripheral, Environment, SidedEnvironment, IOCTile {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate boolean addedToNetwork = false;\n\tprivate boolean init = false;\n\tpublic int rotation = 0;\n\n\tprivate boolean doneBackwardsCompatCheck = false;\n\n\t@ModDependentField(modId = LPConstants.openComputersModID)\n\tpublic Node node;\n\n\tpublic LogisticsSolidTileEntity() {\n\t\tSimpleServiceLocator.openComputersProxy.initLogisticsSolidTileEntity(this);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tsuper.readFromNBT(nbt);\n\t\trotation = nbt.getInteger(\"rotation\");\n\t\tSimpleServiceLocator.openComputersProxy.handleReadFromNBT(this, nbt);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tnbt = super.writeToNBT(nbt);\n\t\tnbt.setInteger(\"rotation\", rotation);\n\t\tSimpleServiceLocator.openComputersProxy.handleWriteToNBT(this, nbt);\n\t\treturn nbt;\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tSimpleServiceLocator.openComputersProxy.handleChunkUnload(this);\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\ttryUpdateBlockFormat();\n\n\t\tif (!addedToNetwork) {\n\t\t\taddedToNetwork = true;\n\t\t\tSimpleServiceLocator.openComputersProxy.addToNetwork(this);\n\t\t}\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tif (!init) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestRotationPacket.class).setBlockPos(pos));\n\t\t\t\tinit = true;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// backwards compat; TODO remove in 1.13\n\tprotected void tryUpdateBlockFormat() {\n\t\tif (getWorld().isRemote) return;\n\t\tif (doneBackwardsCompatCheck) return;\n\n\t\tif (getBlockType() == LPBlocks.dummy) {\n\t\t\tgetWorld().setBlockState(getPos(), BlockDummy.updateBlockMap.get(getWorld().getBlockState(getPos()).getValue(BlockDummy.PROP_BLOCKTYPE)).getDefaultState());\n\t\t}\n\n\t\tdoneBackwardsCompatCheck = true;\n\t}\n\n\t@Override\n\tpublic boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, @Nonnull IBlockState newSate) {\n\t\t// backwards compat; TODO remove in 1.13\n\t\tif (oldState.getBlock() == LPBlocks.dummy && newSate.getBlock() instanceof LogisticsSolidBlock) return false;\n\n\t\treturn super.shouldRefresh(world, pos, oldState, newSate);\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tSimpleServiceLocator.openComputersProxy.handleInvalidate(this);\n\t}\n\n\tpublic void onBlockBreak() {\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the LP rotation value for this block\")\n\tpublic int getRotation() {\n\t\treturn rotation;\n\t}\n\n\tpublic boolean isActive() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void setRotation(int rotation) {\n\t\tthis.rotation = rotation;\n\t}\n\n\tpublic void notifyOfBlockChange() {\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic Node node() {\n\t\treturn node;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic void onConnect(Node node1) {\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic void onDisconnect(Node node1) {\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic void onMessage(Message message) {\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic Object[] invoke(String s, Context context, Arguments arguments) {\n\t\tBaseWrapperClass object = (BaseWrapperClass) CCObjectWrapper.getWrappedObject(this, BaseWrapperClass.WRAPPER);\n\t\tobject.isDirectCall = true;\n\t\treturn CCObjectWrapper.createArray(object);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic String[] methods() {\n\t\treturn new String[] { \"getBlock\" };\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic Node sidedNode(EnumFacing side) {\n\t\tfinal NeighborTileEntity<TileEntity> neighbor = new WorldCoordinatesWrapper(this).getNeighbor(side);\n\t\tif (neighbor == null || neighbor.isLogisticsPipe() || neighbor.getTileEntity() instanceof LogisticsSolidTileEntity) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn node();\n\t\t}\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic boolean canConnect(EnumFacing side) {\n\t\tfinal NeighborTileEntity<TileEntity> neighbor = new WorldCoordinatesWrapper(this).getNeighbor(side);\n\t\treturn neighbor != null && !neighbor.isLogisticsPipe() && !(neighbor.getTileEntity() instanceof LogisticsSolidTileEntity);\n\t}\n\n\t@Override\n\tpublic Object getOCNode() {\n\t\treturn node();\n\t}\n\n\tpublic DoubleCoordinates getLPPosition() {\n\t\treturn new DoubleCoordinates(this);\n\t}\n\n\tpublic World getWorldForHUD() {\n\t\treturn getWorld();\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/crafting/AutoCraftingInventory.java",
    "content": "package logisticspipes.blocks.crafting;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.InventoryCrafting;\n\nimport logisticspipes.utils.PlayerIdentifier;\n\npublic class AutoCraftingInventory extends InventoryCrafting {\n\n\tpublic final PlayerIdentifier placedByPlayer;\n\n\tpublic AutoCraftingInventory(PlayerIdentifier playerID) {\n\t\tsuper(new Container() {\n\n\t\t\t@Override\n\t\t\tpublic boolean canInteractWith(@Nonnull EntityPlayer entityplayer) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void onCraftMatrixChanged(IInventory par1iInventory) {}\n\t\t}, 3, 3);\n\t\tplacedByPlayer = playerID;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/crafting/LogisticsCraftingTableTileEntity.java",
    "content": "package logisticspipes.blocks.crafting;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.InventoryCraftResult;\nimport net.minecraft.inventory.SlotCrafting;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.IRecipe;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.text.ITextComponent;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.util.Constants;\nimport net.minecraftforge.event.world.WorldEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.items.CapabilityItemHandler;\nimport net.minecraftforge.items.wrapper.InvWrapper;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.api.IRoutedPowerProvider;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.guis.block.AutoCraftingGui;\nimport logisticspipes.network.packets.block.CraftingSetType;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.CraftingUtil;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.property.BitSetProperty;\nimport network.rs485.logisticspipes.property.IBitSet;\nimport network.rs485.logisticspipes.util.FuzzyUtil;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\n\npublic class LogisticsCraftingTableTileEntity extends LogisticsSolidTileEntity\n\t\timplements IInventory, IGuiTileEntity, ISimpleInventoryEventHandler, IGuiOpenControler {\n\n\tpublic final BitSetProperty fuzzyFlags = new BitSetProperty(new BitSet(4 * (9 + 1)), \"fuzzyBitSet\");\n\tpublic ItemIdentifierInventory inv = new ItemIdentifierInventory(18, \"Crafting Resources\", 64);\n\tpublic ItemIdentifierInventory matrix = new ItemIdentifierInventory(9, \"Crafting Matrix\", 1);\n\tpublic ItemIdentifierInventory resultInv = new ItemIdentifierInventory(1, \"Crafting Result\", 1);\n\tpublic ItemIdentifier targetType = null;\n\n\tprivate InventoryCraftResult vanillaResult = new InventoryCraftResult();\n\tprivate IRecipe cache;\n\tprivate EntityPlayerMP fake;\n\tprivate PlayerIdentifier placedBy = null;\n\n\tprivate InvWrapper invWrapper = new InvWrapper(this);\n\n\tprivate PlayerCollectionList guiWatcher = new PlayerCollectionList();\n\n\tpublic LogisticsCraftingTableTileEntity() {\n\t\tmatrix.addListener(this);\n\t}\n\n\tpublic void cacheRecipe() {\n\t\tItemIdentifier oldTargetType = targetType;\n\t\tcache = null;\n\t\tresultInv.clearInventorySlotContents(0);\n\t\tAutoCraftingInventory craftInv = new AutoCraftingInventory(placedBy);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t}\n\t\tList<IRecipe> list = new ArrayList<>();\n\t\tfor (IRecipe r : CraftingUtil.getRecipeList()) {\n\t\t\tif (r.matches(craftInv, getWorld())) {\n\t\t\t\tlist.add(r);\n\t\t\t}\n\t\t}\n\t\tif (list.size() == 1) {\n\t\t\tcache = list.get(0);\n\t\t\tresultInv.setInventorySlotContents(0, cache.getCraftingResult(craftInv));\n\t\t\ttargetType = null;\n\t\t} else if (list.size() > 1) {\n\t\t\tif (targetType != null) {\n\t\t\t\tfor (IRecipe recipe : list) {\n\t\t\t\t\tcraftInv = new AutoCraftingInventory(placedBy);\n\t\t\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t\t\t\t}\n\t\t\t\t\tItemStack result = recipe.getCraftingResult(craftInv);\n\t\t\t\t\tif (!result.isEmpty() && targetType.equals(ItemIdentifier.get(result))) {\n\t\t\t\t\t\tresultInv.setInventorySlotContents(0, result);\n\t\t\t\t\t\tcache = recipe;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (cache == null) {\n\t\t\t\tfor (IRecipe r : list) {\n\t\t\t\t\tItemStack result = r.getCraftingResult(craftInv);\n\t\t\t\t\tif (!result.isEmpty()) {\n\t\t\t\t\t\tcache = r;\n\t\t\t\t\t\tresultInv.setInventorySlotContents(0, result);\n\t\t\t\t\t\ttargetType = ItemIdentifier.get(result);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\ttargetType = null;\n\t\t}\n\t\tif (((targetType == null && oldTargetType != null) || (targetType != null && !targetType.equals(oldTargetType)))\n\t\t\t\t&& !guiWatcher.isEmpty() && MainProxy.isServer(getWorld())) {\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\tPacketHandler.getPacket(CraftingSetType.class).setTargetType(targetType).setTilePos(this),\n\t\t\t\t\tguiWatcher);\n\t\t}\n\t}\n\n\tpublic void cycleRecipe(boolean down) {\n\t\tcacheRecipe();\n\t\tif (targetType == null) return;\n\n\t\tcache = null;\n\t\tAutoCraftingInventory craftInv = new AutoCraftingInventory(placedBy);\n\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t}\n\n\t\tList<IRecipe> list = new ArrayList<>();\n\t\tfor (IRecipe r : CraftingUtil.getRecipeList()) {\n\t\t\tif (r.matches(craftInv, getWorld())) {\n\t\t\t\tlist.add(r);\n\t\t\t}\n\t\t}\n\n\t\tif (list.size() > 1) {\n\t\t\tboolean found = false;\n\t\t\tIRecipe prev = null;\n\t\t\tfor (IRecipe recipe : list) {\n\t\t\t\tif (found) {\n\t\t\t\t\tcache = recipe;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcraftInv = new AutoCraftingInventory(placedBy);\n\t\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t\t\t}\n\t\t\t\tif (targetType != null && targetType.equals(ItemIdentifier.get(recipe.getCraftingResult(craftInv)))) {\n\t\t\t\t\tif (down) {\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (prev == null) {\n\t\t\t\t\t\t\tcache = list.get(list.size() - 1);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcache = prev;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprev = recipe;\n\t\t\t}\n\n\t\t\tif (cache == null) {\n\t\t\t\tcache = list.get(0);\n\t\t\t}\n\n\t\t\tcraftInv = new AutoCraftingInventory(placedBy);\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t\t}\n\n\t\t\ttargetType = ItemIdentifier.get(cache.getCraftingResult(craftInv));\n\t\t}\n\n\t\tif (!guiWatcher.isEmpty() && MainProxy.isServer(getWorld())) {\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\tPacketHandler.getPacket(CraftingSetType.class).setTargetType(targetType).setTilePos(this),\n\t\t\t\t\tguiWatcher);\n\t\t}\n\n\t\tcacheRecipe();\n\t}\n\n\tpublic IBitSet outputFuzzy() {\n\t\tfinal int startIdx = 4 * 9; // after the 9th slot\n\t\treturn fuzzyFlags.get(startIdx, startIdx + 3);\n\t}\n\n\tpublic IBitSet inputFuzzy(int slot) {\n\t\tfinal int startIdx = 4 * slot;\n\t\treturn fuzzyFlags.get(startIdx, startIdx + 3);\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getOutput(IResource wanted, IRoutedPowerProvider power) {\n\t\tboolean isFuzzy = isFuzzy();\n\t\tif (cache == null) {\n\t\t\tcacheRecipe();\n\t\t\tif (cache == null) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t}\n\t\tint[] toUse = new int[9];\n\t\tint[] used = new int[inv.getSizeInventory()];\n\t\touter:\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tItemIdentifierStack item = matrix.getIDStackInSlot(i);\n\t\t\tif (item == null) {\n\t\t\t\ttoUse[i] = -1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemIdentifier ident = item.getItem();\n\t\t\tfor (int j = 0; j < inv.getSizeInventory(); j++) {\n\t\t\t\titem = inv.getIDStackInSlot(j);\n\t\t\t\tif (item == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tfinal boolean doItemsEqual = isFuzzy ?\n\t\t\t\t\t\t(FuzzyUtil.INSTANCE\n\t\t\t\t\t\t\t\t.fuzzyMatches(FuzzyUtil.INSTANCE.getter(inputFuzzy(i)), ident, item.getItem())) :\n\t\t\t\t\t\tident.equalsForCrafting(item.getItem());\n\n\t\t\t\tif (doItemsEqual && item.getStackSize() > used[j]) {\n\t\t\t\t\tused[j]++;\n\t\t\t\t\ttoUse[i] = j;\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\t//Not enough material\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tAutoCraftingInventory crafter = new AutoCraftingInventory(placedBy);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tint j = toUse[i];\n\t\t\tif (j != -1) {\n\t\t\t\tcrafter.setInventorySlotContents(i, inv.getStackInSlot(j));\n\t\t\t}\n\t\t}\n\t\tIRecipe recipe = cache;\n\t\tfinal ItemIdentifierStack outStack = Objects.requireNonNull(resultInv.getIDStackInSlot(0));\n\t\tif (!recipe.matches(crafter, getWorld())) {\n\t\t\tif (isFuzzy && outputFuzzy().nextSetBit(0) != -1) {\n\t\t\t\trecipe = null;\n\t\t\t\tfor (IRecipe r : CraftingUtil.getRecipeList()) {\n\n\t\t\t\t\tif (r.matches(crafter, getWorld()) && FuzzyUtil.INSTANCE\n\t\t\t\t\t\t\t.fuzzyMatches(FuzzyUtil.INSTANCE.getter(outputFuzzy()), outStack.getItem(),\n\t\t\t\t\t\t\t\t\tItemIdentifier.get(r.getRecipeOutput()))) {\n\t\t\t\t\t\trecipe = r;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (recipe == null) {\n\t\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn ItemStack.EMPTY; //Fix MystCraft\n\t\t\t}\n\t\t}\n\t\tItemStack result = recipe.getCraftingResult(crafter);\n\t\tif (result.isEmpty()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tif (isFuzzy && outputFuzzy().nextSetBit(0) != -1) {\n\t\t\tif (!FuzzyUtil.INSTANCE.fuzzyMatches(FuzzyUtil.INSTANCE.getter(outputFuzzy()), outStack.getItem(),\n\t\t\t\t\tItemIdentifier.get(result))) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t\tif (!FuzzyUtil.INSTANCE.fuzzyMatches(FuzzyUtil.INSTANCE.getter(outputFuzzy()), wanted.getAsItem(),\n\t\t\t\t\tItemIdentifier.get(result))) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t} else {\n\t\t\tif (!outStack.getItem().equalsWithoutNBT(ItemIdentifier.get(result))) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t\tif (!wanted.matches(outStack.getItem(), IResource.MatchSettings.WITHOUT_NBT)) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t}\n\t\tif (!power.useEnergy(Configs.LOGISTICS_CRAFTING_TABLE_POWER_USAGE)) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tcrafter = new AutoCraftingInventory(placedBy);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tint j = toUse[i];\n\t\t\tif (j != -1) {\n\t\t\t\tcrafter.setInventorySlotContents(i, inv.decrStackSize(j, 1));\n\t\t\t}\n\t\t}\n\t\tresult = recipe.getCraftingResult(crafter);\n\t\tif (fake == null) {\n\t\t\tfake = MainProxy.getFakePlayer(this.world);\n\t\t}\n\t\tresult = result.copy();\n\t\tSlotCrafting craftingSlot = new SlotCrafting(fake, crafter, resultInv, 0, 0, 0) {\n\n\t\t\t@Override\n\t\t\tprotected void onCrafting(@Nonnull ItemStack stack) {\n\t\t\t\tIInventory tmp = this.inventory;\n\t\t\t\tvanillaResult.setRecipeUsed(cache);\n\t\t\t\tthis.inventory = vanillaResult;\n\t\t\t\tsuper.onCrafting(stack);\n\t\t\t\tthis.inventory = tmp;\n\t\t\t}\n\t\t};\n\t\tresult = craftingSlot.onTake(fake, result);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tItemStack left = crafter.getStackInSlot(i);\n\t\t\tcrafter.setInventorySlotContents(i, ItemStack.EMPTY);\n\t\t\tif (!left.isEmpty()) {\n\t\t\t\tleft.setCount(inv.addCompressed(left, false));\n\t\t\t\tif (left.getCount() > 0) {\n\t\t\t\t\tItemIdentifierInventory.dropItems(world, left, getPos());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < fake.inventory.getSizeInventory(); i++) {\n\t\t\tItemStack left = fake.inventory.getStackInSlot(i);\n\t\t\tfake.inventory.setInventorySlotContents(i, ItemStack.EMPTY);\n\t\t\tif (!left.isEmpty()) {\n\t\t\t\tleft.setCount(inv.addCompressed(left, false));\n\t\t\t\tif (left.getCount() > 0) {\n\t\t\t\t\tItemIdentifierInventory.dropItems(world, left, getPos());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void onBlockBreak() {\n\t\tinv.dropContents(world, getPos());\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tif (inventory == matrix) {\n\t\t\tcacheRecipe();\n\t\t}\n\t}\n\n\tpublic void handleNEIRecipePacket(NonNullList<ItemStack> content) {\n\t\tif (matrix.getSizeInventory() != content.size())\n\t\t\tthrow new IllegalStateException(\"Different sizes of matrix and inventory from packet\");\n\t\tfor (int i = 0; i < content.size(); i++) {\n\t\t\tmatrix.setInventorySlotContents(i, content.get(i));\n\t\t}\n\t\tcacheRecipe();\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tsuper.readFromNBT(par1nbtTagCompound);\n\t\tinv.readFromNBT(par1nbtTagCompound, \"inv\");\n\t\tmatrix.readFromNBT(par1nbtTagCompound, \"matrix\");\n\t\tif (par1nbtTagCompound.hasKey(\"placedBy\")) {\n\t\t\tString name = par1nbtTagCompound.getString(\"placedBy\");\n\t\t\tplacedBy = PlayerIdentifier.convertFromUsername(name);\n\t\t} else {\n\t\t\tplacedBy = PlayerIdentifier.readFromNBT(par1nbtTagCompound, \"placedBy\");\n\t\t}\n\t\tfuzzyFlags.readFromNBT(par1nbtTagCompound);\n\t\t// FIXME: remove after 1.12\n\t\tif (par1nbtTagCompound.hasKey(\"fuzzyFlags\")) {\n\t\t\tNBTTagList lst = par1nbtTagCompound.getTagList(\"fuzzyFlags\", Constants.NBT.TAG_COMPOUND);\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tFuzzyUtil.INSTANCE.readFromNBT(inputFuzzy(i), lst.getCompoundTagAt(i));\n\t\t\t}\n\t\t}\n\t\t// FIXME: remove after 1.12\n\t\tif (par1nbtTagCompound.hasKey(\"outputFuzzyFlags\")) {\n\t\t\tFuzzyUtil.INSTANCE.readFromNBT(outputFuzzy(), par1nbtTagCompound.getCompoundTag(\"outputFuzzyFlags\"));\n\t\t}\n\t\tif (par1nbtTagCompound.hasKey(\"targetType\")) {\n\t\t\ttargetType = ItemIdentifier\n\t\t\t\t\t.get(ItemStackLoader.loadAndFixItemStackFromNBT(par1nbtTagCompound.getCompoundTag(\"targetType\")));\n\t\t}\n\t\tcacheRecipe();\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tpar1nbtTagCompound = super.writeToNBT(par1nbtTagCompound);\n\t\tinv.writeToNBT(par1nbtTagCompound, \"inv\");\n\t\tmatrix.writeToNBT(par1nbtTagCompound, \"matrix\");\n\t\tif (placedBy != null) {\n\t\t\tplacedBy.writeToNBT(par1nbtTagCompound, \"placedBy\");\n\t\t}\n\t\tfuzzyFlags.writeToNBT(par1nbtTagCompound);\n\t\tif (targetType != null) {\n\t\t\tNBTTagCompound type = new NBTTagCompound();\n\t\t\ttargetType.makeNormalStack(1).writeToNBT(type);\n\t\t\tpar1nbtTagCompound.setTag(\"targetType\", type);\n\t\t} else {\n\t\t\tpar1nbtTagCompound.removeTag(\"targetType\");\n\t\t}\n\t\treturn par1nbtTagCompound;\n\t}\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {\n\t\t\treturn true;\n\t\t}\n\t\treturn super.hasCapability(capability, facing);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {\n\t\t\treturn (T) invWrapper;\n\t\t}\n\t\treturn super.getCapability(capability, facing);\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn inv.getSizeInventory();\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn inv.isEmpty();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getStackInSlot(int i) {\n\t\treturn inv.getStackInSlot(i);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack decrStackSize(int i, int j) {\n\t\treturn inv.decrStackSize(i, j);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack removeStackFromSlot(int i) {\n\t\treturn inv.removeStackFromSlot(i);\n\t}\n\n\t@Override\n\tpublic void setInventorySlotContents(int i, @Nonnull ItemStack itemstack) {\n\t\tinv.setInventorySlotContents(i, itemstack);\n\t}\n\n\t@Override\n\tpublic int getInventoryStackLimit() {\n\t\treturn inv.getInventoryStackLimit();\n\t}\n\n\t@Override\n\tpublic boolean isUsableByPlayer(@Nonnull EntityPlayer entityplayer) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void openInventory(@Nonnull EntityPlayer player) {\n\t}\n\n\t@Override\n\tpublic void closeInventory(@Nonnull EntityPlayer player) {\n\t}\n\n\t@Override\n\tpublic boolean isItemValidForSlot(int i, @Nonnull ItemStack itemstack) {\n\t\tif (i < 9 && i >= 0) {\n\t\t\tItemIdentifierStack stack = matrix.getIDStackInSlot(i);\n\t\t\tif (stack != null && !itemstack.isEmpty()) {\n\t\t\t\tif (isFuzzy() && inputFuzzy(i).nextSetBit(0) != -1) {\n\t\t\t\t\treturn FuzzyUtil.INSTANCE.fuzzyMatches(FuzzyUtil.INSTANCE.getter(inputFuzzy(i)),\n\t\t\t\t\t\t\tstack.getItem(),\n\t\t\t\t\t\t\tItemIdentifier.get(itemstack));\n\t\t\t\t}\n\t\t\t\treturn stack.getItem().equalsWithoutNBT(ItemIdentifier.get(itemstack));\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int getField(int id) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void setField(int id, int value) {\n\n\t}\n\n\t@Override\n\tpublic int getFieldCount() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void clear() {\n\n\t}\n\n\tpublic void placedBy(EntityLivingBase par5EntityLivingBase) {\n\t\tif (par5EntityLivingBase instanceof EntityPlayer) {\n\t\t\tplacedBy = PlayerIdentifier.get((EntityPlayer) par5EntityLivingBase);\n\t\t}\n\t}\n\n\tpublic boolean isFuzzy() {\n\t\treturn world.getBlockState(pos).getBlock() == LPBlocks.crafterFuzzy;\n\t}\n\n\t@Override\n\tpublic CoordinatesGuiProvider getGuiProvider() {\n\t\treturn NewGuiHandler.getGui(AutoCraftingGui.class).setCraftingTable(this);\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tguiWatcher.add(player);\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tguiWatcher.remove(player);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getName() {\n\t\treturn \"LogisticsCraftingTable\";\n\t}\n\n\t@Override\n\tpublic boolean hasCustomName() {\n\t\treturn true;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic ITextComponent getDisplayName() {\n\t\treturn null;\n\t}\n\n\t@SubscribeEvent\n\tpublic void onWorldUnload(WorldEvent.Unload worldEvent) {\n\t\tif (fake.world == worldEvent.getWorld()) fake = null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/powertile/LogisticsIC2PowerProviderTileEntity.java",
    "content": "package logisticspipes.blocks.powertile;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport ic2.api.energy.tile.IEnergyEmitter;\nimport ic2.api.energy.tile.IEnergySink;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\n\n@ModDependentInterface(modId = { LPConstants.ic2ModID }, interfacePath = { \"ic2.api.energy.tile.IEnergySink\" })\npublic class LogisticsIC2PowerProviderTileEntity extends LogisticsPowerProviderTileEntity implements IEnergySink {\n\n\tpublic static final int MAX_STORAGE = 40000000;\n\tpublic static final int MAX_MAXMODE = 8;\n\tpublic static final int MAX_PROVIDE_PER_TICK = 2048 * 6; //TODO\n\n\tprivate boolean addedToEnergyNet = false;\n\tprivate boolean init = false;\n\n\tpublic LogisticsIC2PowerProviderTileEntity() {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tsuper.update();\n\t\tif (!init) {\n\t\t\tif (!addedToEnergyNet) {\n\t\t\t\tSimpleServiceLocator.IC2Proxy.registerToEneryNet(this);\n\t\t\t\taddedToEnergyNet = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tLogisticsHUDRenderer.instance().remove(this);\n\t\t}\n\t\tif (addedToEnergyNet) {\n\t\t\tSimpleServiceLocator.IC2Proxy.unregisterToEneryNet(this);\n\t\t\taddedToEnergyNet = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tinit = false;\n\t\t}\n\t\tif (!addedToEnergyNet) {\n\t\t\tinit = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tLogisticsHUDRenderer.instance().remove(this);\n\t\t}\n\t\tif (addedToEnergyNet) {\n\t\t\tSimpleServiceLocator.IC2Proxy.unregisterToEneryNet(this);\n\t\t\taddedToEnergyNet = false;\n\t\t}\n\t}\n\n\tpublic void addEnergy(double amount) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tinternalStorage += amount;\n\t\tif (internalStorage > LogisticsIC2PowerProviderTileEntity.MAX_STORAGE) {\n\t\t\tinternalStorage = LogisticsIC2PowerProviderTileEntity.MAX_STORAGE;\n\t\t}\n\t\tif (internalStorage >= getMaxStorage()) {\n\t\t\tneedMorePowerTriggerCheck = false;\n\t\t}\n\t}\n\n\tpublic double freeSpace() {\n\t\treturn getMaxStorage() - internalStorage;\n\t}\n\n\t@Override\n\tpublic int getMaxStorage() {\n\t\tmaxMode = Math.min(LogisticsIC2PowerProviderTileEntity.MAX_MAXMODE, Math.max(1, maxMode));\n\t\treturn (LogisticsIC2PowerProviderTileEntity.MAX_STORAGE / maxMode);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tsuper.readFromNBT(nbt);\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\treturn super.writeToNBT(nbt);\n\t}\n\n\t@Override\n\tpublic String getBrand() {\n\t\treturn \"EU\";\n\t}\n\n\t@Override\n\tprotected double getMaxProvidePerTick() {\n\t\treturn LogisticsIC2PowerProviderTileEntity.MAX_PROVIDE_PER_TICK;\n\t}\n\n\t@Override\n\tprotected void handlePower(CoreRoutedPipe pipe, double toSend) {\n\t\tpipe.handleIC2PowerArival(toSend);\n\t}\n\n\t@Override\n\tprotected int getLaserColor() {\n\t\treturn LogisticsPowerProviderTileEntity.IC2_COLOR;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic boolean acceptsEnergyFrom(IEnergyEmitter tile, EnumFacing dir) {\n\t\treturn true;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic double getDemandedEnergy() {\n\t\treturn freeSpace();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic int getSinkTier() {\n\t\treturn Integer.MAX_VALUE;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic double injectEnergy(EnumFacing directionFrom, double amount, double voltage) {\n\t\taddEnergy(amount);\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/powertile/LogisticsPowerJunctionTileEntity.java",
    "content": "package logisticspipes.blocks.powertile;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.crash.CrashReportCategory;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.capabilities.CapabilityInject;\nimport net.minecraftforge.energy.CapabilityEnergy;\nimport net.minecraftforge.energy.IEnergyStorage;\n\nimport buildcraft.api.mj.IMjConnector;\nimport buildcraft.api.mj.IMjReceiver;\nimport ic2.api.energy.tile.IEnergyEmitter;\nimport ic2.api.energy.tile.IEnergySink;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.config.Configs;\nimport logisticspipes.gui.hud.HUDPowerLevel;\nimport logisticspipes.interfaces.IBlockWatchingHandler;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.interfaces.IHeadUpDisplayBlockRendererProvider;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IPowerLevelDisplay;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.guis.block.PowerJunctionGui;\nimport logisticspipes.network.packets.block.PowerJunctionLevel;\nimport logisticspipes.network.packets.hud.HUDStartBlockWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopBlockWatchingPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.utils.PlayerCollectionList;\n\n@ModDependentInterface(modId = { LPConstants.ic2ModID }, interfacePath = { \"ic2.api.energy.tile.IEnergySink\" })\n@CCType(name = \"LogisticsPowerJunction\")\npublic class LogisticsPowerJunctionTileEntity extends LogisticsSolidTileEntity implements IGuiTileEntity, ILogisticsPowerProvider, IPowerLevelDisplay, IGuiOpenControler, IHeadUpDisplayBlockRendererProvider, IBlockWatchingHandler, IEnergySink {\n\n\tpublic Object OPENPERIPHERAL_IGNORE; //Tell OpenPeripheral to ignore this class\n\n\t@CapabilityInject(IMjConnector.class)\n\tprivate static Capability<IMjConnector> MJ_CONN = null;\n\n\t@CapabilityInject(IMjReceiver.class)\n\tprivate static Capability<IMjReceiver> MJ_RECV = null;\n\n\t// true if it needs more power, turns off at full, turns on at 50%.\n\tpublic boolean needMorePowerTriggerCheck = true;\n\n\tpublic final static int IC2Multiplier = 2;\n\tpublic final static int RFDivisor = 2;\n\tpublic final static int MJMultiplier = 5;\n\tpublic final static int MAX_STORAGE = 2000000;\n\n\tprivate int internalStorage = 0;\n\tprivate int lastUpdateStorage = 0;\n\tprivate double internalBuffer = 0;\n\n\t//small buffer to hold a fractional LP worth of RF\n\tprivate int internalRFbuffer = 0;\n\n\tprivate boolean addedToEnergyNet = false;\n\n\tprivate boolean init = false;\n\tprivate PlayerCollectionList guiListener = new PlayerCollectionList();\n\tprivate PlayerCollectionList watcherList = new PlayerCollectionList();\n\tprivate IHeadUpDisplayRenderer HUD;\n\n\tprivate IEnergyStorage energyInterface = new IEnergyStorage() {\n\n\t\t@Override\n\t\tpublic int receiveEnergy(int maxReceive, boolean simulate) {\n\t\t\tif (freeSpace() < 1) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tint RFspace = freeSpace() * LogisticsPowerJunctionTileEntity.RFDivisor - internalRFbuffer;\n\t\t\tint RFtotake = Math.min(maxReceive, RFspace);\n\t\t\tif (!simulate) {\n\t\t\t\taddEnergy(RFtotake / LogisticsPowerJunctionTileEntity.RFDivisor);\n\t\t\t\tinternalRFbuffer += RFtotake % LogisticsPowerJunctionTileEntity.RFDivisor;\n\t\t\t\tif (internalRFbuffer >= LogisticsPowerJunctionTileEntity.RFDivisor) {\n\t\t\t\t\taddEnergy(1);\n\t\t\t\t\tinternalRFbuffer -= LogisticsPowerJunctionTileEntity.RFDivisor;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn RFtotake;\n\t\t}\n\n\t\t@Override\n\t\tpublic int extractEnergy(int maxExtract, boolean simulate) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getEnergyStored() {\n\t\t\treturn internalStorage * LogisticsPowerJunctionTileEntity.RFDivisor + internalRFbuffer;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getMaxEnergyStored() {\n\t\t\treturn LogisticsPowerJunctionTileEntity.MAX_STORAGE * LogisticsPowerJunctionTileEntity.RFDivisor;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canExtract() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canReceive() {\n\t\t\treturn true;\n\t\t}\n\t};\n\n\tprivate Object mjReceiver;\n\n\tpublic LogisticsPowerJunctionTileEntity() {\n\t\tHUD = new HUDPowerLevel(this);\n\t\tmjReceiver = SimpleServiceLocator.buildCraftProxy.createMjReceiver(this);\n\t}\n\n\t@Override\n\tpublic boolean useEnergy(int amount, List<Object> providersToIgnore) {\n\t\tif (providersToIgnore != null && providersToIgnore.contains(this)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (canUseEnergy(amount, null)) {\n\t\t\tthis.markDirty();\n\t\t\tinternalStorage -= (int) ((amount * Configs.POWER_USAGE_MULTIPLIER) + 0.5D);\n\t\t\tif (internalStorage < LogisticsPowerJunctionTileEntity.MAX_STORAGE / 2) {\n\t\t\t\tneedMorePowerTriggerCheck = true;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canUseEnergy(int amount, List<Object> providersToIgnore) {\n\t\tif (providersToIgnore != null && providersToIgnore.contains(this)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn internalStorage >= (int) ((amount * Configs.POWER_USAGE_MULTIPLIER) + 0.5D);\n\t}\n\n\t@Override\n\tpublic boolean useEnergy(int amount) {\n\t\treturn useEnergy(amount, null);\n\t}\n\n\tpublic int freeSpace() {\n\t\treturn LogisticsPowerJunctionTileEntity.MAX_STORAGE - internalStorage;\n\t}\n\n\tpublic void updateClients() {\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(PowerJunctionLevel.class).setInteger(internalStorage).setBlockPos(pos), guiListener);\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(PowerJunctionLevel.class).setInteger(internalStorage).setBlockPos(pos), watcherList);\n\t\tlastUpdateStorage = internalStorage;\n\t}\n\n\t@Override\n\tpublic boolean canUseEnergy(int amount) {\n\t\treturn canUseEnergy(amount, null);\n\t}\n\n\tpublic void addEnergy(float amount) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tinternalStorage += amount;\n\t\tif (internalStorage > LogisticsPowerJunctionTileEntity.MAX_STORAGE) {\n\t\t\tinternalStorage = LogisticsPowerJunctionTileEntity.MAX_STORAGE;\n\t\t}\n\t\tif (internalStorage == LogisticsPowerJunctionTileEntity.MAX_STORAGE) {\n\t\t\tneedMorePowerTriggerCheck = false;\n\t\t}\n\t\tthis.markDirty();\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tsuper.readFromNBT(par1nbtTagCompound);\n\t\tinternalStorage = par1nbtTagCompound.getInteger(\"powerLevel\");\n\t\tif (par1nbtTagCompound.hasKey(\"needMorePowerTriggerCheck\")) {\n\t\t\tneedMorePowerTriggerCheck = par1nbtTagCompound.getBoolean(\"needMorePowerTriggerCheck\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tpar1nbtTagCompound = super.writeToNBT(par1nbtTagCompound);\n\t\tpar1nbtTagCompound.setInteger(\"powerLevel\", internalStorage);\n\t\tpar1nbtTagCompound.setBoolean(\"needMorePowerTriggerCheck\", needMorePowerTriggerCheck);\n\t\treturn par1nbtTagCompound;\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tsuper.update();\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (internalStorage != lastUpdateStorage) {\n\t\t\t\tupdateClients();\n\t\t\t}\n\t\t}\n\t\tif (!init) {\n\t\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\t\tLogisticsHUDRenderer.instance().add(this);\n\t\t\t}\n\t\t\tif (!addedToEnergyNet) {\n\t\t\t\tSimpleServiceLocator.IC2Proxy.registerToEneryNet(this);\n\t\t\t\taddedToEnergyNet = true;\n\t\t\t}\n\t\t\tinit = true;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tLogisticsHUDRenderer.instance().remove(this);\n\t\t}\n\t\tif (addedToEnergyNet) {\n\t\t\tSimpleServiceLocator.IC2Proxy.unregisterToEneryNet(this);\n\t\t\taddedToEnergyNet = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tinit = false;\n\t\t}\n\t\tif (!addedToEnergyNet) {\n\t\t\tinit = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tLogisticsHUDRenderer.instance().remove(this);\n\t\t}\n\t\tif (addedToEnergyNet) {\n\t\t\tSimpleServiceLocator.IC2Proxy.unregisterToEneryNet(this);\n\t\t\taddedToEnergyNet = false;\n\t\t}\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the currently stored power\")\n\tpublic int getPowerLevel() {\n\t\treturn internalStorage;\n\t}\n\n\t@Override\n\tpublic int getDisplayPowerLevel() {\n\t\treturn getPowerLevel();\n\t}\n\n\t@Override\n\tpublic String getBrand() {\n\t\treturn \"LP\";\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the max. storable power\")\n\tpublic int getMaxStorage() {\n\t\treturn LogisticsPowerJunctionTileEntity.MAX_STORAGE;\n\t}\n\n\t@Override\n\tpublic int getChargeState() {\n\t\treturn internalStorage * 100 / LogisticsPowerJunctionTileEntity.MAX_STORAGE;\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tguiListener.add(player);\n\t\tupdateClients();\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tguiListener.remove(player);\n\t}\n\n\tpublic void handlePowerPacket(int integer) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tinternalStorage = integer;\n\t\t}\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn pos.getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn pos.getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn pos.getZ();\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartBlockWatchingPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopBlockWatchingPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player) {\n\t\twatcherList.add(player);\n\t\tupdateClients();\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player) {\n\t\twatcherList.remove(player);\n\t}\n\n\t@Override\n\tpublic boolean isHUDExistent() {\n\t\treturn getWorld().getTileEntity(pos) == this;\n\t}\n\n\t@Override\n\tpublic void addInfoToCrashReport(CrashReportCategory par1CrashReportCategory) {\n\t\tsuper.addInfoToCrashReport(par1CrashReportCategory);\n\t\tpar1CrashReportCategory.addCrashSection(\"LP-Version\", LogisticsPipes.getVersionString());\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic boolean acceptsEnergyFrom(IEnergyEmitter tile, EnumFacing dir) {\n\t\treturn true;\n\t}\n\n\tprivate void transferFromIC2Buffer() {\n\t\tif (freeSpace() > 0 && internalBuffer >= 1) {\n\t\t\tint addAmount = Math.min((int) Math.floor(internalBuffer), freeSpace());\n\t\t\taddEnergy(addAmount);\n\t\t\tinternalBuffer -= addAmount;\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic double getDemandedEnergy() {\n\t\tif (!addedToEnergyNet) {\n\t\t\treturn 0;\n\t\t}\n\t\ttransferFromIC2Buffer();\n\t\t//round up so we demand enough to completely fill visible storage\n\t\treturn (freeSpace() + LogisticsPowerJunctionTileEntity.IC2Multiplier - 1) / LogisticsPowerJunctionTileEntity.IC2Multiplier;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic double injectEnergy(EnumFacing directionFrom, double amount, double voltage) {\n\t\tinternalBuffer += amount * LogisticsPowerJunctionTileEntity.IC2Multiplier;\n\t\ttransferFromIC2Buffer();\n\t\treturn 0;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.ic2ModID)\n\tpublic int getSinkTier() {\n\t\treturn Integer.MAX_VALUE;\n\t}\n\n\t@Override\n\tpublic boolean isHUDInvalid() {\n\t\treturn isInvalid();\n\t}\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == CapabilityEnergy.ENERGY) {\n\t\t\treturn true;\n\t\t}\n\t\tif (capability == MJ_CONN || capability == MJ_RECV) {\n\t\t\treturn true;\n\t\t}\n\t\treturn super.hasCapability(capability, facing);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == CapabilityEnergy.ENERGY) {\n\t\t\treturn (T) energyInterface;\n\t\t}\n\t\tif (capability == MJ_CONN || capability == MJ_RECV) {\n\t\t\treturn (T) mjReceiver;\n\t\t}\n\t\treturn super.getCapability(capability, facing);\n\t}\n\n\t@Override\n\tpublic CoordinatesGuiProvider getGuiProvider() {\n\t\treturn NewGuiHandler.getGui(PowerJunctionGui.class);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/powertile/LogisticsPowerProviderTileEntity.java",
    "content": "package logisticspipes.blocks.powertile;\n\nimport java.util.BitSet;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\nimport java.util.stream.Stream;\n\nimport net.minecraft.crash.CrashReportCategory;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagFloat;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.gui.hud.HUDPowerLevel;\nimport logisticspipes.interfaces.IBlockWatchingHandler;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.interfaces.IHeadUpDisplayBlockRendererProvider;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IPowerLevelDisplay;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.guis.block.PowerProviderGui;\nimport logisticspipes.network.packets.block.PowerProviderLevel;\nimport logisticspipes.network.packets.hud.HUDStartBlockWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopBlockWatchingPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\n@CCType(name = \"LogisticsPowerProvider\")\npublic abstract class LogisticsPowerProviderTileEntity extends LogisticsSolidTileEntity\n\t\timplements IGuiTileEntity, ISubSystemPowerProvider, IPowerLevelDisplay, IGuiOpenControler, IHeadUpDisplayBlockRendererProvider, IBlockWatchingHandler {\n\n\tpublic static final int BC_COLOR = 0x00ffff;\n\tpublic static final int RF_COLOR = 0xff0000;\n\tpublic static final int IC2_COLOR = 0xffff00;\n\n\t// true if it needs more power, turns off at full, turns on at 50%.\n\tpublic boolean needMorePowerTriggerCheck = true;\n\n\tprotected Map<Integer, Double> orders = new HashMap<>();\n\tprotected BitSet reOrdered = new BitSet(ServerRouter.getBiggestSimpleID());\n\tprotected boolean pauseRequesting = false;\n\n\tprotected double internalStorage = 0;\n\tprotected int maxMode = 1;\n\tprivate double lastUpdateStorage = 0;\n\tprivate PlayerCollectionList guiListener = new PlayerCollectionList();\n\tprivate PlayerCollectionList watcherList = new PlayerCollectionList();\n\tprivate IHeadUpDisplayRenderer HUD;\n\tprivate boolean init = false;\n\n\tprotected LogisticsPowerProviderTileEntity() {\n\t\tHUD = new HUDPowerLevel(this);\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tsuper.update();\n\t\tpauseRequesting = false;\n\t\tif (!init) {\n\t\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\t\tLogisticsHUDRenderer.instance().add(this);\n\t\t\t}\n\t\t\tinit = true;\n\t\t}\n\t\tdouble globalRequest = orders.values().stream().reduce(Double::sum).orElse(0.0);\n\t\tif (globalRequest > 0) {\n\t\t\tfinal double fullfillRatio = Math.min(1, Math.min(internalStorage, getMaxProvidePerTick()) / globalRequest);\n\t\t\tif (fullfillRatio > 0) {\n\t\t\t\tfinal Function<NeighborTileEntity<LogisticsTileGenericPipe>, CoreRoutedPipe> getPipe =\n\t\t\t\t\t\t(NeighborTileEntity<LogisticsTileGenericPipe> neighbor) -> (CoreRoutedPipe) neighbor.getTileEntity().pipe;\n\t\t\t\torders.entrySet().stream()\n\t\t\t\t\t\t.map(routerIdToOrderCount -> new Pair<>(SimpleServiceLocator.routerManager.getRouter(routerIdToOrderCount.getKey()),\n\t\t\t\t\t\t\t\tMath.min(internalStorage, routerIdToOrderCount.getValue() * fullfillRatio)))\n\t\t\t\t\t\t.filter(destinationToPower -> destinationToPower.getValue1() != null && destinationToPower.getValue1().getPipe() != null)\n\t\t\t\t\t\t.forEach(destinationToPower -> new WorldCoordinatesWrapper(this)\n\t\t\t\t\t\t\t\t.allNeighborTileEntities().stream()\n\t\t\t\t\t\t\t\t.flatMap(neighbor -> LPNeighborTileEntityKt.optionalIs(neighbor, LogisticsTileGenericPipe.class).map(Stream::of).orElseGet(Stream::empty))\n\t\t\t\t\t\t\t\t.filter(neighbor -> neighbor.getTileEntity().pipe instanceof CoreRoutedPipe &&\n\t\t\t\t\t\t\t\t\t\t!getPipe.apply(neighbor).stillNeedReplace())\n\t\t\t\t\t\t\t\t.flatMap(neighbor -> getPipe.apply(neighbor).getRouter().getDistanceTo(destinationToPower.getValue1()).stream()\n\t\t\t\t\t\t\t\t\t\t.map(exitRoute -> new Pair<>(neighbor, exitRoute)))\n\t\t\t\t\t\t\t\t.filter(neighborToExit -> neighborToExit.getValue2().containsFlag(PipeRoutingConnectionType.canPowerSubSystemFrom) &&\n\t\t\t\t\t\t\t\t\t\tneighborToExit.getValue2().filters.stream().noneMatch(IFilter::blockPower))\n\t\t\t\t\t\t\t\t.findFirst()\n\t\t\t\t\t\t\t\t.ifPresent(neighborToSource -> {\n\t\t\t\t\t\t\t\t\tCoreRoutedPipe sourcePipe = getPipe.apply(neighborToSource.getValue1());\n\t\t\t\t\t\t\t\t\tif (sourcePipe.isInitialized()) {\n\t\t\t\t\t\t\t\t\t\tsourcePipe.container.addLaser(neighborToSource.getValue1().getOurDirection(), 1, getLaserColor(), true, true);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tsendPowerLaserPackets(sourcePipe.getRouter(), destinationToPower.getValue1(), neighborToSource.getValue2().exitOrientation,\n\t\t\t\t\t\t\t\t\t\t\tneighborToSource.getValue2().exitOrientation != neighborToSource.getValue1().getDirection());\n\t\t\t\t\t\t\t\t\tinternalStorage -= destinationToPower.getValue2();\n\t\t\t\t\t\t\t\t\tif (internalStorage <= 0) internalStorage = 0; // because calculations with floats\n\t\t\t\t\t\t\t\t\thandlePower(destinationToPower.getValue1().getPipe(), destinationToPower.getValue2());\n\t\t\t\t\t\t\t\t}));\n\t\t\t}\n\t\t}\n\t\torders.clear();\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tif (internalStorage != lastUpdateStorage) {\n\t\t\t\tupdateClients();\n\t\t\t\tlastUpdateStorage = internalStorage;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected abstract void handlePower(CoreRoutedPipe pipe, double toSend);\n\n\tprivate void sendPowerLaserPackets(IRouter sourceRouter, IRouter destinationRouter, EnumFacing exitOrientation, boolean addBall) {\n\t\tif (sourceRouter == destinationRouter) {\n\t\t\treturn;\n\t\t}\n\t\tLinkedList<Triplet<IRouter, EnumFacing, Boolean>> todo = new LinkedList<>();\n\t\ttodo.add(new Triplet<>(sourceRouter, exitOrientation, addBall));\n\t\twhile (!todo.isEmpty()) {\n\t\t\tTriplet<IRouter, EnumFacing, Boolean> part = todo.pollFirst();\n\t\t\tList<ExitRoute> exits = part.getValue1().getRoutersOnSide(part.getValue2());\n\t\t\tfor (ExitRoute exit : exits) {\n\t\t\t\tif (exit.containsFlag(PipeRoutingConnectionType.canPowerSubSystemFrom)) { // Find only result (caused by only straight connections)\n\t\t\t\t\tint distance = part.getValue1().getDistanceToNextPowerPipe(exit.exitOrientation);\n\t\t\t\t\tCoreRoutedPipe pipe = part.getValue1().getPipe();\n\t\t\t\t\tif (pipe != null && pipe.isInitialized()) {\n\t\t\t\t\t\tpipe.container.addLaser(exit.exitOrientation, distance, getLaserColor(), false, part.getValue3());\n\t\t\t\t\t}\n\t\t\t\t\tIRouter nextRouter = exit.destination; // Use new sourceRouter\n\t\t\t\t\tif (nextRouter == destinationRouter) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\touterRouters:\n\t\t\t\t\tfor (ExitRoute newExit : nextRouter.getDistanceTo(destinationRouter)) {\n\t\t\t\t\t\tif (newExit.containsFlag(PipeRoutingConnectionType.canPowerSubSystemFrom)) {\n\t\t\t\t\t\t\tfor (IFilter filter : newExit.filters) {\n\t\t\t\t\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\t\t\t\t\tcontinue outerRouters;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttodo.addLast(new Triplet<>(nextRouter, newExit.exitOrientation, newExit.exitOrientation != exit.exitOrientation));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected abstract double getMaxProvidePerTick();\n\n\t@CCCommand(description = \"Returns the color for the power provided by this power provider\")\n\tprotected abstract int getLaserColor();\n\n\t@Override\n\t@CCCommand(description = \"Returns the max. amount of storable power\")\n\tpublic abstract int getMaxStorage();\n\n\t@Override\n\t@CCCommand(description = \"Returns the power type stored in this power provider\")\n\tpublic abstract String getBrand();\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tLogisticsHUDRenderer.instance().remove(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tinit = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tLogisticsHUDRenderer.instance().remove(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void requestPower(int destination, double amount) {\n\t\tif (pauseRequesting) {\n\t\t\treturn;\n\t\t}\n\t\tif (getBrand().equals(\"EU\")) {\n\t\t\tSystem.out.print(\"\");\n\t\t}\n\t\tif (orders.containsKey(destination)) {\n\t\t\tif (reOrdered.get(destination)) {\n\t\t\t\tpauseRequesting = true;\n\t\t\t\treOrdered.clear();\n\t\t\t} else {\n\t\t\t\treOrdered.set(destination);\n\t\t\t}\n\t\t} else {\n\t\t\treOrdered.clear();\n\t\t}\n\t\torders.put(destination, amount);\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the current power level for this power provider\")\n\tpublic double getPowerLevel() {\n\t\treturn lastUpdateStorage;\n\t}\n\n\t@Override\n\tpublic boolean usePaused() {\n\t\treturn pauseRequesting;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tsuper.readFromNBT(nbt);\n\t\tif (nbt.getTag(\"internalStorage\") instanceof NBTTagFloat) { // support for old float\n\t\t\tinternalStorage = nbt.getFloat(\"internalStorage\");\n\t\t} else {\n\t\t\tinternalStorage = nbt.getDouble(\"internalStorage\");\n\t\t}\n\t\tmaxMode = nbt.getInteger(\"maxMode\");\n\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tnbt = super.writeToNBT(nbt);\n\t\tnbt.setDouble(\"internalStorageDouble\", internalStorage);\n\t\tnbt.setInteger(\"maxMode\", maxMode);\n\t\treturn nbt;\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn pos.getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn pos.getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn pos.getZ();\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartBlockWatchingPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopBlockWatchingPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player) {\n\t\twatcherList.add(player);\n\t\tupdateClients();\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player) {\n\t\twatcherList.remove(player);\n\t}\n\n\t@Override\n\tpublic boolean isHUDExistent() {\n\t\treturn getWorld().getTileEntity(pos) == this;\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tguiListener.add(player);\n\t\tupdateClients();\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tguiListener.remove(player);\n\t}\n\n\tpublic void updateClients() {\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(PowerProviderLevel.class).setDouble(internalStorage).setTilePos(this), guiListener);\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(PowerProviderLevel.class).setDouble(internalStorage).setTilePos(this), watcherList);\n\t}\n\n\t@Override\n\tpublic void addInfoToCrashReport(CrashReportCategory par1CrashReportCategory) {\n\t\tsuper.addInfoToCrashReport(par1CrashReportCategory);\n\t\tpar1CrashReportCategory.addCrashSection(\"LP-Version\", LogisticsPipes.getVersionString());\n\t}\n\n\tpublic void handlePowerPacket(double d) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tinternalStorage = d;\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getChargeState() {\n\t\treturn (int) Math.min(100F, internalStorage * 100 / getMaxStorage());\n\t}\n\n\t@Override\n\tpublic int getDisplayPowerLevel() {\n\t\treturn internalStorage > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) internalStorage;\n\t}\n\n\t@Override\n\tpublic boolean isHUDInvalid() {\n\t\treturn isInvalid();\n\t}\n\n\t@Override\n\tpublic CoordinatesGuiProvider getGuiProvider() {\n\t\treturn NewGuiHandler.getGui(PowerProviderGui.class);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/powertile/LogisticsRFPowerProviderTileEntity.java",
    "content": "package logisticspipes.blocks.powertile;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.energy.CapabilityEnergy;\nimport net.minecraftforge.energy.IEnergyStorage;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.cofh.subproxies.ICoFHEnergyStorage;\n\npublic class LogisticsRFPowerProviderTileEntity extends LogisticsPowerProviderTileEntity {\n\n\tpublic static final int MAX_STORAGE = 10000000;\n\tpublic static final int MAX_MAXMODE = 8;\n\tpublic static final int MAX_PROVIDE_PER_TICK = 10000; //TODO\n\n\tprivate IEnergyStorage energyInterface = new IEnergyStorage() {\n\n\t\t@Override\n\t\tpublic int receiveEnergy(int maxReceive, boolean simulate) {\n\t\t\treturn storage.receiveEnergy(maxReceive, simulate);\n\t\t}\n\n\t\t@Override\n\t\tpublic int extractEnergy(int maxExtract, boolean simulate) {\n\t\t\treturn 0;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getEnergyStored() {\n\t\t\treturn storage.getEnergyStored();\n\t\t}\n\n\t\t@Override\n\t\tpublic int getMaxEnergyStored() {\n\t\t\treturn storage.getMaxEnergyStored();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canExtract() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canReceive() {\n\t\t\treturn true;\n\t\t}\n\t};\n\n\tprivate ICoFHEnergyStorage storage;\n\n\tpublic LogisticsRFPowerProviderTileEntity() {\n\t\tstorage = SimpleServiceLocator.powerProxy.getEnergyStorage(10000);\n\t}\n\n\tpublic void addEnergy(double amount) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tinternalStorage += amount;\n\t\tif (internalStorage > LogisticsRFPowerProviderTileEntity.MAX_STORAGE) {\n\t\t\tinternalStorage = LogisticsRFPowerProviderTileEntity.MAX_STORAGE;\n\t\t}\n\t\tif (internalStorage >= getMaxStorage()) {\n\t\t\tneedMorePowerTriggerCheck = false;\n\t\t}\n\t}\n\n\tprivate void addStoredRF() {\n\t\tint space = freeSpace();\n\t\tint available = (storage.extractEnergy(space, true));\n\t\tif (available > 0) {\n\t\t\tif (storage.extractEnergy(available, false) == available) {\n\t\t\t\taddEnergy(available);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int freeSpace() {\n\t\treturn (int) (getMaxStorage() - internalStorage);\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tsuper.update();\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tif (freeSpace() > 0) {\n\t\t\t\taddStoredRF();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getMaxStorage() {\n\t\tmaxMode = Math.min(LogisticsRFPowerProviderTileEntity.MAX_MAXMODE, Math.max(1, maxMode));\n\t\treturn (LogisticsRFPowerProviderTileEntity.MAX_STORAGE / maxMode);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tsuper.readFromNBT(nbt);\n\t\tstorage.readFromNBT(nbt);\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tnbt = super.writeToNBT(nbt);\n\t\tstorage.writeToNBT(nbt);\n\t\treturn nbt;\n\t}\n\n\t@Override\n\tpublic String getBrand() {\n\t\treturn \"RF\";\n\t}\n\n\t@Override\n\tprotected double getMaxProvidePerTick() {\n\t\treturn LogisticsRFPowerProviderTileEntity.MAX_PROVIDE_PER_TICK;\n\t}\n\n\t@Override\n\tprotected void handlePower(CoreRoutedPipe pipe, double toSend) {\n\t\tpipe.handleRFPowerArival(toSend);\n\t}\n\n\t@Override\n\tprotected int getLaserColor() {\n\t\treturn LogisticsPowerProviderTileEntity.RF_COLOR;\n\t}\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == CapabilityEnergy.ENERGY) {\n\t\t\treturn true;\n\t\t}\n\t\treturn super.hasCapability(capability, facing);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == CapabilityEnergy.ENERGY) {\n\t\t\treturn (T) energyInterface;\n\t\t}\n\t\treturn super.getCapability(capability, facing);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/stats/LogisticsStatisticsTileEntity.java",
    "content": "package logisticspipes.blocks.stats;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.interfaces.IGuiTileEntity;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.guis.block.StatisticsGui;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\npublic class LogisticsStatisticsTileEntity extends LogisticsSolidTileEntity implements IGuiTileEntity {\n\n\tpublic List<TrackingTask> tasks = new ArrayList<>();\n\tprivate int tickCount;\n\tprivate CoreRoutedPipe cachedConnectedPipe;\n\n\t@Override\n\tpublic void notifyOfBlockChange() {\n\t\tsuper.notifyOfBlockChange();\n\t\tcachedConnectedPipe = null;\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\ttryUpdateBlockFormat();\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn;\n\t\t}\n\t\ttickCount++;\n\t\tif (getConnectedPipe() == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (TrackingTask task : tasks) {\n\t\t\ttask.tick(tickCount, getConnectedPipe());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tsuper.readFromNBT(nbt);\n\t\tint size = nbt.getInteger(\"taskSize\");\n\t\tfor (int i = 0; i < size; i++) {\n\t\t\tNBTTagCompound tag = (NBTTagCompound) nbt.getTag(\"Task_\" + i);\n\t\t\tTrackingTask task = new TrackingTask();\n\t\t\ttask.readFromNBT(tag);\n\t\t\ttasks.add(task);\n\t\t}\n\t}\n\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tnbt = super.writeToNBT(nbt);\n\t\tnbt.setInteger(\"taskSize\", tasks.size());\n\t\tint count = 0;\n\t\tfor (TrackingTask task : tasks) {\n\t\t\tNBTTagCompound tag = new NBTTagCompound();\n\t\t\ttask.writeToNBT(tag);\n\t\t\tnbt.setTag(\"Task_\" + count, tag);\n\t\t\tcount++;\n\t\t}\n\t\treturn nbt;\n\t}\n\n\t@Override\n\tpublic CoordinatesGuiProvider getGuiProvider() {\n\t\treturn NewGuiHandler.getGui(StatisticsGui.class).setTrackingList(tasks);\n\t}\n\n\tpublic CoreRoutedPipe getConnectedPipe() {\n\t\tif (cachedConnectedPipe == null) {\n\t\t\tnew WorldCoordinatesWrapper(this).allNeighborTileEntities().stream()\n\t\t\t\t\t.filter(NeighborTileEntity::isLogisticsPipe)\n\t\t\t\t\t.filter(adjacent -> ((LogisticsTileGenericPipe) adjacent.getTileEntity()).pipe instanceof CoreRoutedPipe)\n\t\t\t\t\t.map(adjacent -> (CoreRoutedPipe) (((LogisticsTileGenericPipe) adjacent.getTileEntity()).pipe))\n\t\t\t\t\t.findFirst()\n\t\t\t\t\t.ifPresent(coreRoutedPipe -> cachedConnectedPipe = coreRoutedPipe);\n\t\t}\n\t\treturn cachedConnectedPipe;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/blocks/stats/TrackingTask.java",
    "content": "package logisticspipes.blocks.stats;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\n\npublic class TrackingTask {\n\n\tpublic int everyNthTick = 20 * 60;\n\tpublic ItemIdentifier item;\n\tpublic int arrayPos = 0;\n\tpublic long[] amountRecorded = new long[1440]; //24h with 20ticks and 60sec\n\n\tpublic void tick(int tickCount, CoreRoutedPipe pipe) {\n\t\tif (tickCount % everyNthTick != 0) {\n\t\t\treturn;\n\t\t}\n\t\tamountRecorded[arrayPos++] = SimpleServiceLocator.logisticsManager.getAmountFor(item, pipe.getRouter().getIRoutersByCost());\n\t\tif (arrayPos >= amountRecorded.length) {\n\t\t\tarrayPos = 0;\n\t\t}\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tint[] amountRecorded_A = nbt.getIntArray(\"amountRecorded_A\");\n\t\tint[] amountRecorded_B = nbt.getIntArray(\"amountRecorded_B\");\n\t\tfor (int i = 0; i < amountRecorded.length; i++) {\n\t\t\tif (i >= amountRecorded_A.length || i >= amountRecorded_B.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tamountRecorded[i] = (((long) amountRecorded_B[i]) << 32) | amountRecorded_A[i];\n\t\t}\n\t\tarrayPos = nbt.getInteger(\"arrayPos\");\n\t\titem = ItemIdentifier.get(ItemStackLoader.loadAndFixItemStackFromNBT(nbt));\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbt) {\n\t\tint[] amountRecorded_A = new int[amountRecorded.length];\n\t\tint[] amountRecorded_B = new int[amountRecorded.length];\n\t\tfor (int i = 0; i < amountRecorded.length; i++) {\n\t\t\tamountRecorded_A[i] = (int) amountRecorded[i];\n\t\t\tamountRecorded_B[i] = (int) (amountRecorded[i] >> 32);\n\t\t}\n\t\tnbt.setIntArray(\"amountRecorded_A\", amountRecorded_A);\n\t\tnbt.setIntArray(\"amountRecorded_B\", amountRecorded_B);\n\t\tnbt.setInteger(\"arrayPos\", arrayPos);\n\t\titem.makeNormalStack(1).writeToNBT(nbt);\n\t}\n\n\tpublic void writeToLPData(LPDataOutput output) {\n\t\toutput.writeLongArray(amountRecorded);\n\t\toutput.writeInt(arrayPos);\n\t\toutput.writeItemIdentifier(item);\n\t}\n\n\tpublic void readFromLPData(LPDataInput input) {\n\t\tamountRecorded = input.readLongArray();\n\t\tarrayPos = input.readInt();\n\t\titem = input.readItemIdentifier();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/LogisticsPipesCommand.java",
    "content": "package logisticspipes.commands;\n\nimport java.util.Arrays;\nimport java.util.Locale;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.command.CommandBase;\nimport net.minecraft.command.CommandException;\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.command.WrongUsageException;\nimport net.minecraft.server.MinecraftServer;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.commands.exception.CommandNotFoundException;\nimport logisticspipes.commands.exception.LPCommandException;\nimport logisticspipes.commands.exception.PermissionDeniedException;\nimport logisticspipes.proxy.MainProxy;\n\npublic class LogisticsPipesCommand extends CommandBase {\n\n\tprivate final ICommandHandler mainCommand;\n\n\tpublic LogisticsPipesCommand() {\n\t\tmainCommand = new MainCommandHandler();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getName() {\n\t\treturn \"logisticspipes\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getUsage(@Nonnull ICommandSender var1) {\n\t\treturn \"/\" + getName() + \" help\";\n\t}\n\n\t/*\n\t\t@Override\n\t\tpublic List<String> getCommandAliases() {\n\t\t\treturn Arrays.asList(new String[] { \"lp\", \"logipipes\" });\n\t\t}\n\t*/\n\t@Override\n\tpublic void execute(@Nonnull MinecraftServer server, @Nonnull ICommandSender sender, String[] arguments) throws CommandException {\n\t\tif (arguments.length <= 0) {\n\t\t\tthrow new WrongUsageException(\"Type '/logisticspipes help' for help.\");\n\t\t}\n\t\ttry {\n\t\t\tboolean managed = false;\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t//Check for unlisted Debug commands\n\t\t\t}\n\t\t\tif (!managed) {\n\t\t\t\tmainCommand.executeCommand(sender, arguments);\n\t\t\t}\n\t\t} catch (LPCommandException e) {\n\t\t\tif (e instanceof PermissionDeniedException) {\n\t\t\t\tthrow new CommandException(\"You are not allowed to execute that command now.\");\n\t\t\t} else if (e instanceof CommandNotFoundException) {\n\t\t\t\tthrow new CommandException(\"The command was not found\");\n\t\t\t} else {\n\t\t\t\tthrow new WrongUsageException(\"/logisticspipes help\");\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static boolean isOP(ICommandSender sender) {\n\t\treturn Arrays.asList(FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getOppedPlayers().getKeys())\n\t\t\t\t.contains(sender.getName().toLowerCase(Locale.US)) || (MainProxy.proxy.checkSinglePlayerOwner(sender.getName()));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/MainCommandHandler.java",
    "content": "package logisticspipes.commands;\n\nimport net.minecraft.command.ICommandSender;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.commands.abstracts.SubCommandHandler;\nimport logisticspipes.commands.commands.BypassCommand;\nimport logisticspipes.commands.commands.ChangelogCommand;\nimport logisticspipes.commands.commands.ClearCommand;\nimport logisticspipes.commands.commands.DebugCommand;\nimport logisticspipes.commands.commands.DummyCommand;\nimport logisticspipes.commands.commands.DumpCommand;\nimport logisticspipes.commands.commands.NBTDebugCommand;\nimport logisticspipes.commands.commands.NameLookupCommand;\nimport logisticspipes.commands.commands.RoutingThreadCommand;\nimport logisticspipes.commands.commands.TestCommand;\nimport logisticspipes.commands.commands.TransferNamesCommand;\nimport logisticspipes.commands.commands.VersionCommand;\nimport logisticspipes.commands.commands.WrapperCommand;\n\npublic class MainCommandHandler extends SubCommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"logisticspipes\", \"lp\", \"logipipes\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"The main LP command\" };\n\t}\n\n\t@Override\n\tpublic void registerSubCommands() {\n\t\tregisterSubCommand(new DummyCommand());\n\t\tregisterSubCommand(new VersionCommand());\n\t\tregisterSubCommand(new ChangelogCommand());\n\t\tregisterSubCommand(new NBTDebugCommand());\n\t\tregisterSubCommand(new RoutingThreadCommand());\n\t\tregisterSubCommand(new TransferNamesCommand());\n\t\tregisterSubCommand(new NameLookupCommand());\n\t\tregisterSubCommand(new DumpCommand());\n\t\tregisterSubCommand(new BypassCommand());\n\t\tregisterSubCommand(new DebugCommand());\n\t\tregisterSubCommand(new WrapperCommand());\n\t\tif (LogisticsPipes.isTesting()) {\n\t\t\tregisterSubCommand(new TestCommand());\n\t\t}\n\t\tregisterSubCommand(new ClearCommand());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/abstracts/ICommandHandler.java",
    "content": "package logisticspipes.commands.abstracts;\n\nimport net.minecraft.command.ICommandSender;\n\npublic interface ICommandHandler {\n\n\tString[] getNames();\n\n\tboolean isCommandUsableBy(ICommandSender sender);\n\n\tString[] getDescription();\n\n\tvoid executeCommand(ICommandSender sender, String[] args);\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/abstracts/SubCommandHandler.java",
    "content": "package logisticspipes.commands.abstracts;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport net.minecraft.command.ICommandSender;\n\nimport logisticspipes.commands.chathelper.MorePageDisplay;\nimport logisticspipes.commands.exception.CommandNotFoundException;\nimport logisticspipes.commands.exception.DuplicatedCommandException;\nimport logisticspipes.commands.exception.MissingArgumentException;\nimport logisticspipes.commands.exception.PermissionDeniedException;\nimport logisticspipes.utils.string.ChatColor;\n\npublic abstract class SubCommandHandler implements ICommandHandler {\n\n\tpublic SubCommandHandler() {\n\t\tregisterSubCommands();\n\t}\n\n\tprivate final List<ICommandHandler> subCommands = new ArrayList<>();\n\n\tpublic abstract void registerSubCommands();\n\n\tprotected final void registerSubCommand(ICommandHandler newHandler) {\n\t\tList<String> newCommands = Arrays.asList(newHandler.getNames());\n\t\tfor (ICommandHandler handler : subCommands) {\n\t\t\tfor (String command : handler.getNames()) {\n\t\t\t\tif (newCommands.contains(command)) {\n\t\t\t\t\tthrow new DuplicatedCommandException();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsubCommands.add(newHandler);\n\t}\n\n\tpublic final void displayHelp(ICommandSender sender) {\n\t\tMorePageDisplay display = new MorePageDisplay(new String[] { \"|< Help - \" + getNames()[0] + \" - Page: %/$ >|\" }, sender);\n\t\tfor (ICommandHandler command : subCommands) {\n\t\t\tif (!command.getDescription()[0].startsWith(\"#\")) {\n\t\t\t\tboolean first = true;\n\t\t\t\tString prefix = (command instanceof SubCommandHandler ? ChatColor.BLUE : ChatColor.YELLOW) + command.getNames()[0] + ChatColor.RESET + \": \";\n\t\t\t\tfor (int d = 0; d < command.getDescription().length; d++) {\n\t\t\t\t\tdisplay.append(prefix + command.getDescription()[d], !first);\n\t\t\t\t\tprefix = \"    \";\n\t\t\t\t\tfirst = false;\n\t\t\t\t}\n\t\t\t\tif (command instanceof SubCommandHandler) {\n\t\t\t\t\tdisplay.append(\"      \" + ChatColor.GRAY + \"- add \" + ChatColor.YELLOW + \"help\" + ChatColor.GRAY + \" to see the subcommands\", true);\n\t\t\t\t}\n\t\t\t\tfirst = true;\n\t\t\t\tif (command.getNames().length > 1) {\n\t\t\t\t\tfor (int i = 1; i < command.getNames().length; i++) {\n\t\t\t\t\t\tdisplay.append((first ? \"  alias: - \" : \"         - \") + ChatColor.GOLD + command.getNames()[i] + \"\", true);\n\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdisplay.append(\"\", true);\n\t\t\t}\n\t\t}\n\t\tdisplay.display(sender);\n\t}\n\n\t@Override\n\tpublic final void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (args.length < 1) {\n\t\t\tthrow new MissingArgumentException();\n\t\t}\n\t\tString command = args[0];\n\t\tif (command.equalsIgnoreCase(\"help\")) {\n\t\t\tdisplayHelp(sender);\n\t\t\treturn;\n\t\t} else {\n\t\t\tfor (ICommandHandler handler : subCommands) {\n\t\t\t\tif (Arrays.asList(handler.getNames()).contains(command)) {\n\t\t\t\t\tif (!handler.isCommandUsableBy(sender)) {\n\t\t\t\t\t\tthrow new PermissionDeniedException();\n\t\t\t\t\t}\n\t\t\t\t\tString[] newArgs = Arrays.copyOfRange(args, 1, args.length);\n\t\t\t\t\thandler.executeCommand(sender, newArgs);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new CommandNotFoundException();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/chathelper/LPChatListener.java",
    "content": "package logisticspipes.commands.chathelper;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.Callable;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.util.text.ITextComponent;\nimport net.minecraft.util.text.TextComponentString;\n\nimport net.minecraftforge.client.event.ClientChatReceivedEvent;\nimport net.minecraftforge.event.ServerChatEvent;\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.OpenChatGui;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.string.ChatColor;\nimport logisticspipes.utils.string.StringUtils;\n\npublic class LPChatListener {\n\n\tprivate static final Map<String, Callable<Boolean>> tasks = new HashMap<>();\n\tprivate static final Map<String, MorePageDisplay> morePageDisplays = new HashMap<>();\n\n\tprivate List<String> sendChatMessages = null;\n\n\t@SubscribeEvent\n\tpublic void serverChat(ServerChatEvent event) {\n\t\tEntityPlayerMP player = event.getPlayer();\n\t\tif (LPChatListener.tasks.containsKey(event.getUsername())) {\n\t\t\tif (event.getMessage().startsWith(\"/\")) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"You need to answer the question, before you can use any other command\"));\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t} else {\n\t\t\t\tif (!event.getMessage().equalsIgnoreCase(\"true\") && !event.getMessage().equalsIgnoreCase(\"false\") && !event.getMessage().equalsIgnoreCase(\"on\") && !event.getMessage().equalsIgnoreCase(\"off\") && !event.getMessage().equalsIgnoreCase(\"0\") && !event.getMessage().equalsIgnoreCase(\"1\") && !event.getMessage()\n\t\t\t\t\t\t.equalsIgnoreCase(\"no\")\n\t\t\t\t\t\t&& !event.getMessage().equalsIgnoreCase(\"yes\")) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"Not a valid answer.\"));\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.AQUA + \"Please enter \" + ChatColor.RESET + \"<\" + ChatColor.GREEN + \"yes\" + ChatColor.RESET + \"/\" + ChatColor.RED + \"no \" + ChatColor.RESET + \"| \" + ChatColor.GREEN + \"true\" + ChatColor.RESET + \"/\" + ChatColor.RED + \"flase \"\n\t\t\t\t\t\t\t+ ChatColor.RESET + \"| \" + ChatColor.GREEN + \"on\" + ChatColor.RESET + \"/\" + ChatColor.RED + \"off \" + ChatColor.RESET + \"| \" + ChatColor.GREEN + \"1\" + ChatColor.RESET + \"/\" + ChatColor.RED + \"0\" + ChatColor.RESET + \">\"));\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t\t} else {\n\t\t\t\t\tboolean flag = event.getMessage().equalsIgnoreCase(\"true\") || event.getMessage().equalsIgnoreCase(\"on\") || event.getMessage().equalsIgnoreCase(\"1\") || event.getMessage().equalsIgnoreCase(\"yes\");\n\t\t\t\t\tif (!handleAnswer(flag, player)) {\n\t\t\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"Error: Could not handle answer.\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tevent.setCanceled(true);\n\t\t} else if (LPChatListener.morePageDisplays.containsKey(event.getUsername())) {\n\t\t\tif (!LPChatListener.morePageDisplays.get(event.getUsername()).isTerminated()) {\n\t\t\t\tif (event.getMessage().startsWith(\"/\")) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"Exit \" + ChatColor.AQUA + \"PageView\" + ChatColor.RED + \" first!\"));\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t} else {\n\t\t\t\t\tif (LPChatListener.morePageDisplays.get(event.getUsername()).handleChat(event.getMessage(), player)) {\n\t\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void clientChat(ClientChatReceivedEvent event) {\n\t\tITextComponent message = event.getMessage();\n\t\tif (message != null) {\n\t\t\tString realMessage = null;\n\t\t\ttry {\n\t\t\t\trealMessage = message.getFormattedText();\n\t\t\t} catch (ClassCastException e) {\n\t\t\t\t//Ignore that\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\tif (realMessage != null) {\n\t\t\t\tif (realMessage.equals(\"%LPCLEARCHAT%\")) {\n\t\t\t\t\tclearChat();\n\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t}\n\t\t\t\tif (realMessage.equals(\"%LPSTORESENDMESSAGE%\")) {\n\t\t\t\t\tstoreSendMessages();\n\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t}\n\t\t\t\tif (realMessage.equals(\"%LPRESTORESENDMESSAGE%\")) {\n\t\t\t\t\trestoreSendMessages();\n\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t}\n\t\t\t\tif (realMessage.startsWith(\"%LPADDTOSENDMESSAGE%\")) {\n\t\t\t\t\taddSendMessages(realMessage.substring(20));\n\t\t\t\t\tevent.setCanceled(true);\n\t\t\t\t}\n\t\t\t\tif (realMessage.contains(\"LPDISPLAYMISSING\") && LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tSystem.out.println(\"LIST:\");\n\t\t\t\t\tStringUtils.UNTRANSLATED_STRINGS.forEach(System.out::println);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@ClientSideOnlyMethodContent\n\tprivate void clearChat() {\n\t\tFMLClientHandler.instance().getClient().ingameGUI.getChatGUI().clearChatMessages(true);\n\t}\n\n\t@ClientSideOnlyMethodContent\n\tprivate void storeSendMessages() {\n\t\tsendChatMessages = new ArrayList<>();\n\t\tsendChatMessages.addAll(FMLClientHandler.instance().getClient().ingameGUI.getChatGUI().getSentMessages());\n\t}\n\n\t@ClientSideOnlyMethodContent\n\tprivate void restoreSendMessages() {\n\t\tif (sendChatMessages != null) {\n\t\t\tfor (String o : sendChatMessages) {\n\t\t\t\tFMLClientHandler.instance().getClient().ingameGUI.getChatGUI().addToSentMessages(o);\n\t\t\t}\n\t\t\tsendChatMessages = null;\n\t\t}\n\t}\n\n\t@ClientSideOnlyMethodContent\n\tprivate void addSendMessages(String substring) {\n\t\tif (sendChatMessages != null) {\n\t\t\tsendChatMessages.add(substring);\n\t\t} else {\n\t\t\tFMLClientHandler.instance().getClient().ingameGUI.getChatGUI().addToSentMessages(substring);\n\t\t}\n\t}\n\n\tpublic static void register(MorePageDisplay displayInput, String name) {\n\t\tif (LPChatListener.morePageDisplays.containsKey(name) && !LPChatListener.morePageDisplays.get(name).isTerminated()) {\n\t\t\treturn;\n\t\t}\n\t\tLPChatListener.morePageDisplays.put(name, displayInput);\n\t}\n\n\tpublic static void remove(String name) {\n\t\tLPChatListener.morePageDisplays.remove(name);\n\t}\n\n\tpublic boolean handleAnswer(boolean flag, ICommandSender sender) {\n\t\tif (!LPChatListener.tasks.containsKey(sender.getName())) {\n\t\t\treturn false;\n\t\t}\n\t\tif (flag) {\n\t\t\ttry {\n\t\t\t\tBoolean result;\n\t\t\t\tif ((result = LPChatListener.tasks.get(sender.getName()).call()) != null) {\n\t\t\t\t\tif (result != null && !result) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\tsender.sendMessage(new TextComponentString(ChatColor.GREEN + \"Answer handled.\"));\n\t\t}\n\t\tLPChatListener.tasks.remove(sender.getName());\n\t\treturn true;\n\t}\n\n\tpublic static boolean existTaskFor(String name) {\n\t\treturn LPChatListener.tasks.containsKey(name);\n\t}\n\n\tpublic static void removeTask(String name) {\n\t\tLPChatListener.tasks.remove(name);\n\t}\n\n\tpublic static boolean addTask(Callable<Boolean> input, ICommandSender sender) {\n\t\tif (LPChatListener.tasks.containsKey(sender.getName())) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tLPChatListener.tasks.put(sender.getName(), input);\n\t\t\treturn true;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/chathelper/MorePageDisplay.java",
    "content": "package logisticspipes.commands.chathelper;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.OpenChatGui;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.string.ChatColor;\n\npublic class MorePageDisplay {\n\n\tprivate ArrayList<String> header = new ArrayList<>();\n\tprivate ArrayList<StringConnected> content = new ArrayList<>();\n\n\tprivate final int row = 20;\n\tprivate final int colum = 55;\n\n\tprivate int currentpage = 0;\n\tprivate int currentpagecount = 0;\n\tprivate boolean terminated = false;\n\n\tpublic MorePageDisplay(ArrayList<String> header, ICommandSender name) {\n\t\tif (header.size() <= (row - 2)) {\n\t\t\tthis.header = header;\n\t\t}\n\t\tLPChatListener.register(this, name.getName());\n\t\tname.sendMessage(new TextComponentString(\"%LPSTORESENDMESSAGE%\"));\n\t}\n\n\tpublic MorePageDisplay(String[] header, ICommandSender name) {\n\t\tif (header.length <= (row - 2)) {\n\t\t\tthis.header = new ArrayList<>();\n\t\t\tthis.header.addAll(Arrays.asList(header));\n\t\t}\n\t\tLPChatListener.register(this, name.getName());\n\t\tname.sendMessage(new TextComponentString(\"%LPSTORESENDMESSAGE%\"));\n\t}\n\n\tpublic int getRow() {\n\t\treturn row;\n\t}\n\n\tpublic int getColum() {\n\t\treturn colum;\n\t}\n\n\tpublic void append(String input) {\n\t\tappend(input, false);\n\t}\n\n\tpublic void append(String input, boolean flag) {\n\t\tcontent.add(new StringConnected(input, flag));\n\t}\n\n\tpublic boolean isTerminated() {\n\t\treturn terminated;\n\t}\n\n\tpublic void display(ICommandSender sender) {\n\t\tdisplay(sender, 1);\n\t}\n\n\tpublic void display(ICommandSender player, int page) {\n\t\tdisplay(player, page, false);\n\t}\n\n\tprivate String replaceMeta(String input, int page, int count) {\n\t\tStringBuilder output = new StringBuilder();\n\t\tint pagecount = getPageCount(count);\n\t\tif (count == -1) {\n\t\t\tpagecount = 0;\n\t\t}\n\t\tif (count == -2) {\n\t\t\tpagecount = 1;\n\t\t}\n\t\tfor (int i = 0; i < input.length(); i++) {\n\t\t\tchar c = input.charAt(i);\n\t\t\tswitch (c) {\n\t\t\t\tcase '%':\n\t\t\t\t\toutput.append(page);\n\t\t\t\t\tbreak;\n\t\t\t\tcase '$':\n\t\t\t\t\toutput.append(pagecount);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\toutput.append(c);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tboolean LeftDone = false;\n\t\tboolean RightDone = false;\n\t\tStringBuilder output2 = new StringBuilder();\n\t\t// Add = for <>\n\t\tfor (int i = 0; i < output.length(); i++) {\n\t\t\tchar c = output.charAt(i);\n\t\t\tswitch (c) {\n\t\t\t\tcase '<':\n\t\t\t\t\tif (LeftDone) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tLeftDone = true;\n\t\t\t\t\toutput2.append(ChatColor.AQUA);\n\t\t\t\t\tfor (int j = 0; j < ((colum - output.length()) / 2); j++) {\n\t\t\t\t\t\toutput2.append(\"=\");\n\t\t\t\t\t}\n\t\t\t\t\toutput2.append(ChatColor.WHITE);\n\t\t\t\t\tbreak;\n\t\t\t\tcase '>':\n\t\t\t\t\tif (RightDone) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tRightDone = true;\n\t\t\t\t\toutput2.append(ChatColor.AQUA);\n\t\t\t\t\tfor (int j = 0; j < ((colum - output.length()) / 2); j++) {\n\t\t\t\t\t\toutput2.append(\"=\");\n\t\t\t\t\t}\n\t\t\t\t\toutput2.append(ChatColor.WHITE);\n\t\t\t\t\tbreak;\n\t\t\t\tcase '(':\n\t\t\t\t\tif (LeftDone) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tLeftDone = true;\n\t\t\t\t\tfor (int j = 0; j < ((colum - output.length()) / 2); j++) {\n\t\t\t\t\t\toutput2.append(\" \");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase ')':\n\t\t\t\t\tif (RightDone) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tRightDone = true;\n\t\t\t\t\tfor (int j = 0; j < ((colum - output.length()) / 2); j++) {\n\t\t\t\t\t\toutput2.append(\" \");\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\toutput2.append(c);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn output2.toString();\n\t}\n\n\tpublic boolean handleChat(String input, ICommandSender sender) {\n\t\tif (terminated) {\n\t\t\treturn false;\n\t\t}\n\t\tif (input.equalsIgnoreCase(\"exit\") || input.equalsIgnoreCase(\"quit\") || input.equalsIgnoreCase(\"q\") || input.equalsIgnoreCase(\"e\")) {\n\t\t\tterminated = true;\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPCLEARCHAT%\"));\n\t\t\tfor (Object zeilenobject : header.toArray()) {\n\t\t\t\tif (!(zeilenobject instanceof String)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tsender.sendMessage(new TextComponentString(replaceMeta((String) zeilenobject, 0, -1)));\n\t\t\t}\n\t\t\tclearscreen(sender, 19 - header.size());\n\t\t\tsender.sendMessage(new TextComponentString(ChatColor.AQUA + \"Pageview: \" + ChatColor.RED + \"Exit.\"));\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPRESTORESENDMESSAGE%\"));\n\t\t} else if (input.equalsIgnoreCase(\"next\") || input.equalsIgnoreCase(\"nex\") || input.equalsIgnoreCase(\"n\")) {\n\t\t\tif (currentpage > (currentpagecount - 1)) {\n\t\t\t\tdisplay(sender, 0);\n\t\t\t} else {\n\t\t\t\tcurrentpage++;\n\t\t\t\tdisplay(sender, currentpage);\n\t\t\t}\n\t\t\tif (sender instanceof EntityPlayer) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t\t}\n\t\t} else if (input.equalsIgnoreCase(\"previous\") || input.equalsIgnoreCase(\"prev\") || input.equalsIgnoreCase(\"pre\") || input.equalsIgnoreCase(\"p\")) {\n\t\t\tif (currentpage < 2) {\n\t\t\t\tdisplay(sender, currentpagecount);\n\t\t\t} else {\n\t\t\t\tcurrentpage--;\n\t\t\t\tdisplay(sender, currentpage);\n\t\t\t}\n\t\t} else if (MorePageDisplay.isNumber(input)) {\n\t\t\tif (MorePageDisplay.toNumber(input) <= currentpagecount && MorePageDisplay.toNumber(input) > 0) {\n\t\t\t\tdisplay(sender, MorePageDisplay.toNumber(input));\n\t\t\t} else {\n\t\t\t\tdisplay(sender, currentpage, true);\n\t\t\t\tsender.sendMessage(new TextComponentString(ChatColor.AQUA + \"Pageview:\" + ChatColor.RED + \" Not a valid number.\"));\n\t\t\t}\n\t\t} else if (input.equalsIgnoreCase(\"reprint\")) {\n\t\t\tdisplay(sender, currentpage);\n\t\t} else if (input.equalsIgnoreCase(\"all\")) {\n\t\t\tdisplay(sender, currentpage, false, true, 0);\n\t\t} else if (input.startsWith(\"save \")) {\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPADDTOSENDMESSAGE%\" + input.substring(5)));\n\t\t\tdisplay(sender, currentpage, true, false, 1);\n\t\t\tsender.sendMessage(new TextComponentString(ChatColor.AQUA + \"Added '\" + ChatColor.YELLOW + input.substring(5) + ChatColor.AQUA + \"' to your chat history.\"));\n\t\t\tprintLastLine(sender, false);\n\t\t\tif (sender instanceof EntityPlayer) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t\t}\n\t\t} else if (input.equals(\"save\")) {\n\t\t\tdisplay(sender, currentpage, true, false, 2);\n\t\t\tsender.sendMessage(new TextComponentString(ChatColor.AQUA + \"Add an command after the '\" + ChatColor.YELLOW + \"save \" + ChatColor.AQUA + \"' and it will be added to your chat history.\"));\n\t\t\tprintLastLine(sender, false);\n\t\t\tif (sender instanceof EntityPlayer) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t\t}\n\t\t} else {\n\t\t\t//display(sender,currentpage,true);\n\t\t\tprintLastLine(sender, true);\n\t\t\tif (sender instanceof EntityPlayer) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic static boolean isNumber(String input) {\n\t\ttry {\n\t\t\tint number = Integer.parseInt(input);\n\t\t\tString numstring = String.valueOf(number);\n\t\t\tif (numstring.equalsIgnoreCase(input)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (Exception ignored) {}\n\t\treturn false;\n\t}\n\n\tpublic static int toNumber(String input) {\n\t\ttry {\n\t\t\treturn Integer.parseInt(input);\n\t\t} catch (Exception ignored) {}\n\t\treturn -1;\n\t}\n\n\tprivate void clearscreen(ICommandSender sender, int count) {\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tsender.sendMessage(new TextComponentString(\"\"));\n\t\t}\n\t}\n\n\tpublic void display(ICommandSender sender, int page, boolean flag) {\n\t\tdisplay(sender, page, flag, false, 0);\n\t}\n\n\tpublic void printLastLine(ICommandSender sender) {\n\t\tprintLastLine(sender, false);\n\t}\n\n\tpublic void printLastLine(ICommandSender sender, boolean flag) {\n\t\tsender.sendMessage(new TextComponentString((flag ? \"! \" : \"\") + ChatColor.AQUA + \"Pageview:\" + ChatColor.WHITE + \" Enter \" + ChatColor.RED + \"Pre\" + ChatColor.WHITE + \"/\" + ChatColor.GREEN + \"Next\" + ChatColor.WHITE + \", a \" + ChatColor.AQUA + \"number\" + ChatColor.WHITE + \", \" + ChatColor.AQUA + \"all\"\n\t\t\t\t+ ChatColor.WHITE + \", \" + ChatColor.AQUA + \"reprint\" + ChatColor.WHITE + \", \" + ChatColor.AQUA + \"save\" + ChatColor.WHITE + \" or \" + ChatColor.RED + \"exit\" + ChatColor.WHITE + (flag ? \" !\" : \".\")));\n\t}\n\n\tpublic int getPageCount(int count) {\n\t\tint currentPage = 0;\n\t\tint lineOnCurentPage = 0;\n\t\tfor (int i = 0; i < content.size(); i++, lineOnCurentPage++) {\n\t\t\tint I;\n\t\t\tfor (I = i; I < (content.size() - 1) && content.get(I + 1).connected; I++) {\n\t\t\t}\n\t\t\tint needed = I - i;\n\t\t\tif (lineOnCurentPage + needed > count - 1) {\n\t\t\t\tcurrentPage++;\n\t\t\t\tlineOnCurentPage = 0;\n\t\t\t}\n\t\t}\n\t\treturn currentPage + 1;\n\t}\n\n\tpublic void display(ICommandSender sender, int page, boolean flag, boolean all, int linesub) {\n\t\tif (terminated) {\n\t\t\treturn;\n\t\t}\n\t\tsender.sendMessage(new TextComponentString(\"%LPCLEARCHAT%\"));\n\t\tint count = row - header.size() - 1 - linesub;\n\t\tpage = (page > 0 && !all ? page : 1);\n\t\tcurrentpage = page;\n\t\tcurrentpagecount = getPageCount(count);\n\t\tif (all) {\n\t\t\tcount = -2;\n\t\t}\n\t\tfor (Object zeilenobject : header.toArray()) {\n\t\t\tif (!(zeilenobject instanceof String)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tsender.sendMessage(new TextComponentString(replaceMeta((String) zeilenobject, page, count)));\n\t\t}\n\t\tint currentPage = 0;\n\t\tint lineOnCurentPage = 0;\n\t\tint doneLines = 0;\n\t\tfor (int i = 0; i < content.size(); i++, lineOnCurentPage++) {\n\t\t\tif (all) {\n\t\t\t\tsender.sendMessage(new TextComponentString(content.get(i).content));\n\t\t\t} else {\n\t\t\t\tint I;\n\t\t\t\tfor (I = i; I < (content.size() - 1) && content.get(I + 1).connected; I++) {\n\t\t\t\t}\n\t\t\t\tint needed = I - i;\n\t\t\t\tif (lineOnCurentPage + needed > count - 1) {\n\t\t\t\t\tcurrentPage++;\n\t\t\t\t\tlineOnCurentPage = 0;\n\t\t\t\t}\n\t\t\t\tif (page == currentPage + 1) {\n\t\t\t\t\tsender.sendMessage(new TextComponentString(content.get(i).content));\n\t\t\t\t\tdoneLines = lineOnCurentPage;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!all) {\n\t\t\tclearscreen(sender, row - 2 - header.size() - doneLines - linesub);\n\t\t}\n\t\tif (all && count > content.size()) {\n\t\t\tclearscreen(sender, count - content.size());\n\t\t}\n\t\tif (!flag) {\n\t\t\tprintLastLine(sender);\n\t\t}\n\t\tif (sender instanceof EntityPlayer) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t}\n\t}\n\n\tprivate static class StringConnected {\n\n\t\tStringConnected(String s, boolean b) {\n\t\t\tcontent = s;\n\t\t\tconnected = b;\n\t\t}\n\n\t\tpublic String content;\n\t\tpublic boolean connected;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/BypassCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class BypassCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"bypass\", \"bp\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer && LogisticsPipesCommand.isOP(sender);\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Allows to enable/disable the\", \"security station bypass token\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (!LogisticsSecurityTileEntity.byPassed.contains((EntityPlayer) sender)) {\n\t\t\tLogisticsSecurityTileEntity.byPassed.add((EntityPlayer) sender);\n\t\t\tsender.sendMessage(new TextComponentString(\"Enabled\"));\n\t\t} else {\n\t\t\tLogisticsSecurityTileEntity.byPassed.remove((EntityPlayer) sender);\n\t\t\tsender.sendMessage(new TextComponentString(\"Disabled\"));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/ChangelogCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.commands.chathelper.MorePageDisplay;\nimport logisticspipes.ticks.VersionChecker;\n\npublic class ChangelogCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"changelog\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Display the changelog between this version\", \"and the newest one\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tVersionChecker versionChecker = LogisticsPipes.versionChecker;\n\t\tString statusMessage = versionChecker.getVersionCheckerStatus();\n\n\t\tif (versionChecker.isVersionCheckDone() && versionChecker.getVersionInfo().isNewVersionAvailable()) {\n\t\t\tVersionChecker.VersionInfo versionInfo = versionChecker.getVersionInfo();\n\n\t\t\tMorePageDisplay display = new MorePageDisplay(new String[] { \"(The newest version is #\" + versionInfo.getNewestBuild() + \")\", \"< Changelog Page %/$ >\" }, sender);\n\t\t\tif (versionInfo.getChangelog().isEmpty()) {\n\t\t\t\tdisplay.append(\"No commits since your version.\");\n\t\t\t} else {\n\t\t\t\tversionInfo.getChangelog().forEach(display::append);\n\t\t\t}\n\t\t\tdisplay.display(sender);\n\t\t} else {\n\t\t\tsender.sendMessage(new TextComponentString(statusMessage));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/ClearCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.utils.string.ChatColor;\n\npublic class ClearCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"clear\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Clears the chat window from every content\", ChatColor.GRAY + \"add '\" + ChatColor.YELLOW + \"all\" + ChatColor.GRAY + \"' to also clear the send messages\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (args.length <= 0 || !args[0].equalsIgnoreCase(\"all\")) {\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPSTORESENDMESSAGE%\"));\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPCLEARCHAT%\"));\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPRESTORESENDMESSAGE%\"));\n\t\t} else {\n\t\t\tsender.sendMessage(new TextComponentString(\"%LPCLEARCHAT%\"));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/DebugCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport java.util.Arrays;\n\nimport net.minecraft.command.ICommandSender;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.commands.abstracts.SubCommandHandler;\nimport logisticspipes.commands.commands.debug.HandCommand;\nimport logisticspipes.commands.commands.debug.MeCommand;\nimport logisticspipes.commands.commands.debug.PipeCommand;\nimport logisticspipes.commands.commands.debug.RoutingTableCommand;\nimport logisticspipes.commands.commands.debug.TargetCommand;\n\npublic class DebugCommand extends SubCommandHandler {\n\n\tprivate static final String[] allowedPlayers = new String[] { \"davboecki\", \"theZorro266\" };\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"debug\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn LogisticsPipes.isDEBUG() || Arrays.asList(DebugCommand.allowedPlayers).contains(sender.getName());\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Debug helper commands\" };\n\t}\n\n\t@Override\n\tpublic void registerSubCommands() {\n\t\tregisterSubCommand(new MeCommand());\n\t\tregisterSubCommand(new TargetCommand());\n\t\tregisterSubCommand(new RoutingTableCommand());\n\t\tregisterSubCommand(new PipeCommand());\n\t\tregisterSubCommand(new HandCommand());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/DummyCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class DummyCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"dummy\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"#This Command doesn't do anything\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/DumpCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class DumpCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"dump\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn LogisticsPipesCommand.isOP(sender);\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Dumps the current Tread states\", \"into the server log\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tsender.sendMessage(new TextComponentString(\"Dump Created\"));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/NBTDebugCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.ActivateNBTDebug;\nimport logisticspipes.proxy.MainProxy;\n\npublic class NBTDebugCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"nbtdebug\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer && LogisticsPipesCommand.isOP(sender);\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Enables the Hotkey to show an debug gui\", \"for the howered item. (Only if NEI is installed)\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tsender.sendMessage(new TextComponentString(\"Trying to Enable NBTDebug\"));\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ActivateNBTDebug.class), (EntityPlayer) sender);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/NameLookupCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.item.Item;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.commands.exception.MissingArgumentException;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class NameLookupCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"name\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Displays the serverside stored name for\", \"the <item id> and <meta data>\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (args.length < 2) {\n\t\t\tthrow new MissingArgumentException();\n\t\t}\n\t\tString idString = args[0];\n\t\tString metaString = args[1];\n\t\tint id = Integer.valueOf(idString);\n\t\tint meta = Integer.valueOf(metaString);\n\t\tItemIdentifier item = ItemIdentifier.get(Item.getItemById(id), meta, null);\n\t\tsender.sendMessage(new TextComponentString(\"Name: \" + item.getFriendlyNameCC()));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/RoutingThreadCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.ticks.RoutingTableUpdateThread;\n\npublic class RoutingThreadCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"routingthread\", \"rt\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Display Routing thread status information\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tsender.sendMessage(new TextComponentString(\"RoutingTableUpdateThread: Queued: \" + RoutingTableUpdateThread.size()));\n\t\tsender.sendMessage(new TextComponentString(\"RoutingTableUpdateThread: Average: \" + RoutingTableUpdateThread.getAverage() + \"ns\"));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/TestCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport java.lang.reflect.Method;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport kotlin.Unit;\nimport kotlin.jvm.functions.Function1;\nimport kotlinx.coroutines.Job;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.utils.string.ChatColor;\n\npublic class TestCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"retest\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Reruns all tests\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tfinal Class<?> testClass;\n\t\ttry {\n\t\t\ttestClass = Class.forName(\"network.rs485.logisticspipes.integration.MinecraftTest\");\n\t\t} catch (ReflectiveOperationException e) {\n\t\t\tsender.sendMessage(new TextComponentString(ChatColor.RED + \"Error loading minecraft test class \" + e));\n\t\t\treturn;\n\t\t}\n\t\tfinal Object minecraftTestInstance;\n\t\ttry {\n\t\t\tminecraftTestInstance = testClass.getDeclaredField(\"INSTANCE\").get(null);\n\t\t\tfinal Method startTestsMethod = testClass.getDeclaredMethod(\"startTests\", Function1.class);\n\t\t\tfinal Job job = (Job) startTestsMethod.invoke(minecraftTestInstance, (Function1<Object, Unit>) msg -> {\n\t\t\t\tsender.sendMessage(new TextComponentString(String.valueOf(msg)));\n\t\t\t\treturn Unit.INSTANCE;\n\t\t\t});\n\t\t\tjob.invokeOnCompletion(throwable -> {\n\t\t\t\tif (throwable == null) {\n\t\t\t\t\tsender.sendMessage(new TextComponentString(ChatColor.GREEN + \"SUCCESS\"));\n\t\t\t\t} else {\n\t\t\t\t\tsender.sendMessage(new TextComponentString(ChatColor.RED + \"Tests failed with: \" + throwable));\n\t\t\t\t}\n\t\t\t\treturn Unit.INSTANCE;\n\t\t\t});\n\t\t} catch (ReflectiveOperationException | ClassCastException e) {\n\t\t\tsender.sendMessage(new TextComponentString(ChatColor.RED + \"Error accessing minecraft test instance \" + e));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/TransferNamesCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.RequestUpdateNamesPacket;\nimport logisticspipes.proxy.MainProxy;\n\npublic class TransferNamesCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"transfernames\", \"tn\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer && LogisticsPipesCommand.isOP(sender);\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Sends all item names form the client\", \"to the server to update the Language Database\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tsender.sendMessage(new TextComponentString(\"Requesting Transfer\"));\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RequestUpdateNamesPacket.class), (EntityPlayer) sender);\n\t\tMainProxy.proxy.sendNameUpdateRequest((EntityPlayer) sender);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/VersionCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.ticks.VersionChecker;\n\npublic class VersionCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"version\", \"v\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Display the used LP version\", \"and shows, if an update is available\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tsender.sendMessage(new TextComponentString(LogisticsPipes.getVersionString()));\n\n\t\tVersionChecker versionChecker = LogisticsPipes.versionChecker;\n\t\tsender.sendMessage(new TextComponentString(versionChecker.getVersionCheckerStatus()));\n\n\t\tif (versionChecker.isVersionCheckDone() && versionChecker.getVersionInfo().isNewVersionAvailable()) {\n\t\t\tsender.sendMessage(new TextComponentString(\"Use \\\"/logisticspipes changelog\\\" to see a changelog.\"));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/WrapperCommand.java",
    "content": "package logisticspipes.commands.commands;\n\nimport net.minecraft.command.ICommandSender;\n\nimport logisticspipes.commands.abstracts.SubCommandHandler;\nimport logisticspipes.commands.commands.wrapper.EnableCommand;\nimport logisticspipes.commands.commands.wrapper.ListCommand;\nimport logisticspipes.commands.commands.wrapper.ShowCommand;\n\npublic class WrapperCommand extends SubCommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"wrapper\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"wrapper control commands\" };\n\t}\n\n\t@Override\n\tpublic void registerSubCommands() {\n\t\tregisterSubCommand(new ListCommand());\n\t\tregisterSubCommand(new EnableCommand());\n\t\tregisterSubCommand(new ShowCommand());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/debug/DebugGuiController.java",
    "content": "package logisticspipes.commands.commands.debug;\n\nimport java.lang.reflect.Array;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.launchwrapper.Launch;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport lombok.AllArgsConstructor;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.exception.DelayPacketException;\nimport logisticspipes.network.packets.debuggui.DebugDataPacket;\nimport logisticspipes.network.packets.debuggui.DebugPanelOpen;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.debug.api.IDataConnection;\nimport network.rs485.debug.api.IDebugGuiEntry;\nimport network.rs485.debug.api.IObjectIdentification;\n\npublic class DebugGuiController {\n\n\tstatic {\n\t\tLaunch.classLoader.addTransformerExclusion(\"com.trolltech.qt.\");\n\t\tLaunch.classLoader.addTransformerExclusion(\"network.rs485.debuggui.\");\n\t\tLaunch.classLoader.addTransformerExclusion(\"network.rs485.debug.\");\n\t}\n\n\ttransient private static DebugGuiController instance;\n\n\tprivate DebugGuiController() {}\n\n\tpublic static DebugGuiController instance() {\n\t\tif (DebugGuiController.instance == null) {\n\t\t\tDebugGuiController.instance = new DebugGuiController();\n\t\t}\n\t\treturn DebugGuiController.instance;\n\t}\n\n\tpublic void execClient() {\n\t\tif (clientController != null) {\n\t\t\tclientController.exec();\n\t\t}\n\t}\n\n\tpublic void execServer() {\n\t\tserverDebugger.values().forEach(IDebugGuiEntry::exec);\n\t}\n\n\tprivate final HashMap<EntityPlayer, IDebugGuiEntry> serverDebugger = new HashMap<>();\n\tprivate final List<IDataConnection> serverList = new LinkedList<>();\n\n\tprivate IDebugGuiEntry clientController = null;\n\tprivate final List<Future<IDataConnection>> clientList = new LinkedList<>();\n\n\tpublic void startWatchingOf(Object object, EntityPlayer player) {\n\t\tif (object == null) {\n\t\t\treturn;\n\t\t}\n\t\tIDebugGuiEntry entry = serverDebugger.get(player);\n\t\tif (entry == null) {\n\t\t\ttry {\n\t\t\t\tentry = IDebugGuiEntry.create();\n\t\t\t\tserverDebugger.put(player, entry);\n\t\t\t} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t\tif (entry == null) {\n\t\t\tSystem.out.println(\"DebugGui could not be loaded\");\n\t\t\treturn;\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(DebugPanelOpen.class).setName(object.getClass().getSimpleName()), player);\n\t\tsynchronized (serverList) {\n\t\t\tint identification = serverList.size();\n\t\t\tIDataConnection conIn = new DataConnectionServer(identification, player);\n\t\t\twhile (serverList.size() <= identification) serverList.add(null);\n\t\t\tserverList.set(identification, entry.startServerDebugging(object, conIn, new ObjectIdentification()));\n\t\t}\n\t}\n\n\tpublic void createNewDebugGui(String name, int identification) {\n\t\tif (clientController == null) {\n\t\t\ttry {\n\t\t\t\tclientController = IDebugGuiEntry.create();\n\t\t\t} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tsynchronized (clientList) {\n\t\t\twhile (clientList.size() <= identification) clientList.add(null);\n\t\t\tclientList.set(identification, clientController.startClientDebugging(name, new DataConnectionClient(identification)));\n\t\t}\n\t}\n\n\tpublic void handleDataPacket(byte[] payload, int identifier, EntityPlayer player) {\n\t\tif (MainProxy.isServer(player.getEntityWorld())) {\n\t\t\tsynchronized (serverList) {\n\t\t\t\tIDataConnection connection = serverList.get(identifier);\n\t\t\t\tif (connection != null) {\n\t\t\t\t\tconnection.passData(payload);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tsynchronized (clientList) {\n\t\t\t\tFuture<IDataConnection> connectionFuture;\n\t\t\t\ttry {\n\t\t\t\t\tconnectionFuture = clientList.get(identifier);\n\t\t\t\t} catch (IndexOutOfBoundsException e) {\n\t\t\t\t\tSystem.out.println(clientList);\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t\tif (connectionFuture == null || !connectionFuture.isDone()) {\n\t\t\t\t\tthrow new DelayPacketException();\n\t\t\t\t}\n\t\t\t\tIDataConnection connection = null;\n\t\t\t\ttry {\n\t\t\t\t\tconnection = connectionFuture.get();\n\t\t\t\t} catch (InterruptedException | ExecutionException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t\tif (connection != null) {\n\t\t\t\t\tconnection.passData(payload);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new DelayPacketException();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@AllArgsConstructor\n\tprivate class DataConnectionServer implements IDataConnection {\n\n\t\tprivate int identification;\n\t\tprivate EntityPlayer player;\n\n\t\t@Override\n\t\tpublic void passData(byte[] packet) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(DebugDataPacket.class).setPayload(packet).setIdentifier(identification), player);\n\t\t}\n\n\t\t@Override\n\t\tpublic void closeCon() {\n\t\t\tserverList.set(identification, null);\n\t\t}\n\t}\n\n\t@AllArgsConstructor\n\tprivate class DataConnectionClient implements IDataConnection {\n\n\t\tprivate int identification;\n\n\t\t@Override\n\t\tpublic void passData(byte[] packet) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DebugDataPacket.class).setPayload(packet).setIdentifier(identification));\n\t\t}\n\n\t\t@Override\n\t\tpublic void closeCon() {\n\t\t\tclientList.set(identification, null);\n\t\t}\n\t}\n\n\tprivate static class ObjectIdentification implements IObjectIdentification {\n\n\t\t@Override\n\t\tpublic boolean toStringObject(Object o) {\n\t\t\treturn o.getClass() == EnumFacing.class || o.getClass() == ItemIdentifier.class || o.getClass() == ItemIdentifierStack.class;\n\t\t}\n\n\t\t@Override\n\t\tpublic String handleObject(Object o) {\n\t\t\tif (o instanceof World) {\n\t\t\t\treturn ((World) o).getWorldInfo().getWorldName();\n\t\t\t}\n\t\t\tif (o != null && o.getClass().isArray() && Array.getLength(o) > 100) {\n\t\t\t\treturn \"(Too big)\";\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/debug/HandCommand.java",
    "content": "package logisticspipes.commands.commands.debug;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class HandCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"hand\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Start debugging the selected ItemStack\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tEntityPlayer player = (EntityPlayer) sender;\n\t\tItemStack item = player.inventory.mainInventory.get(player.inventory.currentItem);\n\t\tif (!item.isEmpty()) {\n\t\t\tDebugGuiController.instance().startWatchingOf(item, player);\n\t\t\tsender.sendMessage(new TextComponentString(\"Starting HandDebuging\"));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/debug/MeCommand.java",
    "content": "package logisticspipes.commands.commands.debug;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class MeCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"me\", \"self\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Start debugging the CommandSender\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tDebugGuiController.instance().startWatchingOf(sender, (EntityPlayer) sender);\n\t\tsender.sendMessage(new TextComponentString(\"Starting SelfDebugging\"));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/debug/PipeCommand.java",
    "content": "package logisticspipes.commands.commands.debug;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.debug.PipeDebugLogAskForTarget;\nimport logisticspipes.network.packets.pipe.PipeDebugAskForTarget;\nimport logisticspipes.proxy.MainProxy;\n\npublic class PipeCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"pipe\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Set the pipe into debug mode\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (args.length != 1) {\n\t\t\tsender.sendMessage(new TextComponentString(\"Wrong amount of arguments\"));\n\t\t\treturn;\n\t\t}\n\t\tif (args[0].equalsIgnoreCase(\"help\")) {\n\t\t\tsender.sendMessage(new TextComponentString(\"client, server, both or console\"));\n\t\t} else if (args[0].equalsIgnoreCase(\"both\")) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PipeDebugAskForTarget.class).setServer(true), (EntityPlayer) sender);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PipeDebugAskForTarget.class).setServer(false), (EntityPlayer) sender);\n\t\t\tsender.sendMessage(new TextComponentString(\"Asking for Target.\"));\n\t\t} else if (args[0].equalsIgnoreCase(\"console\") || args[0].equalsIgnoreCase(\"c\")) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PipeDebugLogAskForTarget.class), (EntityPlayer) sender);\n\t\t\tsender.sendMessage(new TextComponentString(\"Asking for Target.\"));\n\t\t} else {\n\t\t\tboolean isClient = args[0].equalsIgnoreCase(\"client\");\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PipeDebugAskForTarget.class).setServer(!isClient), (EntityPlayer) sender);\n\t\t\tsender.sendMessage(new TextComponentString(\"Asking for Target.\"));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/debug/RoutingTableCommand.java",
    "content": "package logisticspipes.commands.commands.debug;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateAskForTarget;\nimport logisticspipes.proxy.MainProxy;\n\npublic class RoutingTableCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"rt\", \"routing\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Starts debugging the Routing Table\", \"update of the pipe you are currently looking at.\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateAskForTarget.class), (EntityPlayer) sender);\n\t\tsender.sendMessage(new TextComponentString(\"Asking for Target.\"));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/debug/TargetCommand.java",
    "content": "package logisticspipes.commands.commands.debug;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.debuggui.DebugAskForTarget;\nimport logisticspipes.proxy.MainProxy;\n\npublic class TargetCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"target\", \"look\", \"watch\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn sender instanceof EntityPlayer;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Starts debugging the TileEntity\", \"or Entity you are currently looking at.\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(DebugAskForTarget.class), (EntityPlayer) sender);\n\t\tsender.sendMessage(new TextComponentString(\"Asking for Target.\"));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/wrapper/EnableCommand.java",
    "content": "package logisticspipes.commands.commands.wrapper;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.asm.wrapper.AbstractWrapper;\nimport logisticspipes.asm.wrapper.LogisticsWrapperHandler;\nimport logisticspipes.asm.wrapper.WrapperState;\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class EnableCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"enable\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn LogisticsPipesCommand.isOP(sender);\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Re-enables the given proxy\", \"if it was disabled by an exception.\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (args.length != 1) {\n\t\t\tsender.sendMessage(new TextComponentString(\"Wrong amount of arguments\"));\n\t\t\treturn;\n\t\t}\n\t\tString name = args[0];\n\t\tList<AbstractWrapper> list = new ArrayList<>(LogisticsWrapperHandler.wrapperController);\n\t\tIterator<AbstractWrapper> iter = list.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tAbstractWrapper item = iter.next();\n\t\t\tif (item.getState() != WrapperState.Exception) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t\titer = list.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tAbstractWrapper item = iter.next();\n\t\t\tif (!(item.getName() + item.getTypeName()).startsWith(name)) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t\tif (list.size() > 1) {\n\t\t\tsender.sendMessage(new TextComponentString(\"Possible: \"));\n\t\t\tfor (AbstractWrapper can : list) {\n\t\t\t\tsender.sendMessage(new TextComponentString(can.getName() + can.getTypeName()));\n\t\t\t}\n\t\t} else if (list.isEmpty()) {\n\t\t\tsender.sendMessage(new TextComponentString(\"No match found\"));\n\t\t} else {\n\t\t\tAbstractWrapper wrapper = list.get(0);\n\t\t\twrapper.reEnable();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/wrapper/ListCommand.java",
    "content": "package logisticspipes.commands.commands.wrapper;\n\nimport net.minecraft.command.ICommandSender;\n\nimport logisticspipes.asm.wrapper.AbstractWrapper;\nimport logisticspipes.asm.wrapper.LogisticsWrapperHandler;\nimport logisticspipes.asm.wrapper.WrapperState;\nimport logisticspipes.commands.abstracts.ICommandHandler;\nimport logisticspipes.commands.chathelper.MorePageDisplay;\nimport logisticspipes.utils.string.ChatColor;\n\npublic class ListCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"list\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Lists all wrapper and their status.\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tMorePageDisplay display = new MorePageDisplay(new String[] { \"|< Wrapper status - Page: %/$ >|\" }, sender);\n\t\tfor (AbstractWrapper controller : LogisticsWrapperHandler.wrapperController) {\n\t\t\tStringBuilder builder = new StringBuilder();\n\t\t\tbuilder.append(ChatColor.AQUA);\n\t\t\tbuilder.append(controller.getName());\n\t\t\tbuilder.append(controller.getTypeName());\n\t\t\tbuilder.append(\": \");\n\t\t\tif (controller.getState() == WrapperState.Enabled) {\n\t\t\t\tbuilder.append(ChatColor.GREEN);\n\t\t\t\tbuilder.append(\"enabled\");\n\t\t\t} else if (controller.getState() == WrapperState.ModMissing) {\n\t\t\t\tbuilder.append(ChatColor.GRAY);\n\t\t\t\tbuilder.append(\"disabled (mod not found)\");\n\t\t\t} else if (controller.getState() == WrapperState.Exception) {\n\t\t\t\tbuilder.append(ChatColor.RED);\n\t\t\t\tbuilder.append(\"disabled (exception)\");\n\t\t\t} else {\n\t\t\t\tbuilder.append(ChatColor.BLUE);\n\t\t\t\tbuilder.append(\"disabled (\").append(controller.getReason()).append(\")\");\n\t\t\t}\n\t\t\tdisplay.append(builder.toString());\n\t\t}\n\t\tdisplay.display(sender);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/commands/wrapper/ShowCommand.java",
    "content": "package logisticspipes.commands.commands.wrapper;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.asm.wrapper.AbstractWrapper;\nimport logisticspipes.asm.wrapper.LogisticsWrapperHandler;\nimport logisticspipes.asm.wrapper.WrapperState;\nimport logisticspipes.commands.LogisticsPipesCommand;\nimport logisticspipes.commands.abstracts.ICommandHandler;\n\npublic class ShowCommand implements ICommandHandler {\n\n\t@Override\n\tpublic String[] getNames() {\n\t\treturn new String[] { \"show\" };\n\t}\n\n\t@Override\n\tpublic boolean isCommandUsableBy(ICommandSender sender) {\n\t\treturn LogisticsPipesCommand.isOP(sender);\n\t}\n\n\t@Override\n\tpublic String[] getDescription() {\n\t\treturn new String[] { \"Re-enables the given proxy\", \"if it was disabled by an exception.\" };\n\t}\n\n\t@Override\n\tpublic void executeCommand(ICommandSender sender, String[] args) {\n\t\tif (args.length != 1) {\n\t\t\tsender.sendMessage(new TextComponentString(\"Wrong amount of arguments\"));\n\t\t\treturn;\n\t\t}\n\t\tString name = args[0];\n\t\tList<AbstractWrapper> list = new ArrayList<>(LogisticsWrapperHandler.wrapperController);\n\t\tIterator<AbstractWrapper> iter = list.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tAbstractWrapper item = iter.next();\n\t\t\tif (item.getState() != WrapperState.Exception) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t\titer = list.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tAbstractWrapper item = iter.next();\n\t\t\tif (!(item.getName() + item.getTypeName()).startsWith(name)) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t\tif (list.size() > 1) {\n\t\t\tsender.sendMessage(new TextComponentString(\"Possible: \"));\n\t\t\tfor (AbstractWrapper can : list) {\n\t\t\t\tsender.sendMessage(new TextComponentString(can.getName() + can.getTypeName()));\n\t\t\t}\n\t\t} else if (list.isEmpty()) {\n\t\t\tsender.sendMessage(new TextComponentString(\"No match found\"));\n\t\t} else {\n\t\t\tAbstractWrapper wrapper = list.get(0);\n\t\t\tThrowable t = wrapper.getReason();\n\t\t\tif (t == null) {\n\t\t\t\tsender.sendMessage(new TextComponentString(\"null\"));\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tsender.sendMessage(new TextComponentString(\"-----------------------------------------------------\"));\n\t\t\t\tsender.sendMessage(new TextComponentString(t.toString()));\n\t\t\t\tfor (StackTraceElement s : t.getStackTrace()) {\n\t\t\t\t\tsender.sendMessage(new TextComponentString(\" \" + s.toString()));\n\t\t\t\t}\n\t\t\t\tt.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/exception/CommandNotFoundException.java",
    "content": "package logisticspipes.commands.exception;\n\npublic class CommandNotFoundException extends LPCommandException {\n\n\tprivate static final long serialVersionUID = 1989131037198520984L;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/exception/DuplicatedCommandException.java",
    "content": "package logisticspipes.commands.exception;\n\npublic class DuplicatedCommandException extends LPCommandException {\n\n\tprivate static final long serialVersionUID = 8207355333881350761L;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/exception/LPCommandException.java",
    "content": "package logisticspipes.commands.exception;\n\npublic class LPCommandException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 1013470631863858420L;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/exception/MissingArgumentException.java",
    "content": "package logisticspipes.commands.exception;\n\npublic class MissingArgumentException extends LPCommandException {\n\n\tprivate static final long serialVersionUID = -5221600615641546721L;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/commands/exception/PermissionDeniedException.java",
    "content": "package logisticspipes.commands.exception;\n\npublic class PermissionDeniedException extends LPCommandException {\n\n\tprivate static final long serialVersionUID = 1L;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/config/Configs.java",
    "content": "package logisticspipes.config;\n\nimport java.io.File;\nimport java.util.Arrays;\n\nimport net.minecraftforge.common.config.Configuration;\nimport net.minecraftforge.common.config.Property;\nimport net.minecraftforge.fml.common.Loader;\n\nimport logisticspipes.LogisticsPipes;\n\n//@formatter:off\n//CHECKSTYLE:OFF\n\npublic class Configs {\n\n\tpublic static final String CATEGORY_MULTITHREAD = \"multithread\";\n\tpublic static final String CATEGORY_PERFORMANCE = \"performance\";\n\n\tprivate static Configuration CONFIGURATION;\n\n\t// Configurable\n\tpublic static int LOGISTICS_DETECTION_LENGTH = 50;\n\tpublic static int LOGISTICS_DETECTION_COUNT = 100;\n\tpublic static int LOGISTICS_DETECTION_FREQUENCY = 20 * 30;\n\tpublic static boolean LOGISTICS_ORDERER_COUNT_INVERTWHEEL = false;\n\tpublic static boolean LOGISTICS_ORDERER_PAGE_INVERTWHEEL = false;\n\tpublic static final float LOGISTICS_ROUTED_SPEED_MULTIPLIER = 20F;\n\tpublic static final float LOGISTICS_DEFAULTROUTED_SPEED_MULTIPLIER = 10F;\n\tpublic static int MAX_UNROUTED_CONNECTIONS = 32;\n\n\tpublic static int LOGISTICS_HUD_RENDER_DISTANCE = 15;\n\n\tpublic static float\tpipeDurability = 0.25F; //TODO\n\n\tpublic static boolean LOGISTICS_POWER_USAGE_DISABLED = false;\n\tpublic static double POWER_USAGE_MULTIPLIER = 1;\n\tpublic static double COMPILER_SPEED = 1.0;\n\tpublic static boolean ENABLE_RESEARCH_SYSTEM = false;\n\n\tpublic static int LOGISTICS_CRAFTING_TABLE_POWER_USAGE = 250;\n\n\tpublic static boolean TOOLTIP_INFO = LogisticsPipes.isDEBUG();\n\tpublic static boolean ENABLE_PARTICLE_FX = true;\n\n\tpublic static int[] CHASSIS_SLOTS_ARRAY = {1,2,3,4,8};\n\n\t// GuiOrderer Popup setting\n\tpublic static boolean DISPLAY_POPUP = true;\n\n\t// MultiThread\n\tpublic static int MULTI_THREAD_NUMBER = 4;\n\tpublic static int MULTI_THREAD_PRIORITY = Thread.NORM_PRIORITY;\n\n\t// Performance\n\tpublic static boolean DISABLE_ASYNC_WORK = false;\n\tpublic static int MINIMUM_INVENTORY_SLOT_ACCESS_PER_TICK = 10;\n\tpublic static int MAXIMUM_INVENTORY_SLOT_ACCESS_PER_TICK = 0;\n\tpublic static int MINIMUM_JOB_TICK_LENGTH = 1;\n\n\tpublic static boolean CHECK_FOR_UPDATES = true;\n\n\tpublic static boolean EASTER_EGGS = true;\n\n\tpublic static boolean OPAQUE = false;\n\n\tpublic static int MAX_ROBOT_DISTANCE = 64;\n\n\tprivate static boolean loaded = false;\n\tpublic static void load() {\n\t\tif(Configs.loaded) {\n\t\t\treturn;\n\t\t}\n\t\tif(Loader.instance().getConfigDir() == null) {\n\t\t\treturn;\n\t\t}\n\t\tConfigs.CONFIGURATION = new Configuration(new File(Loader.instance().getConfigDir(), \"LogisticsPipes.cfg\"));\n\t\tConfigs.CONFIGURATION.load();\n\t\tConfigs.loaded = true;\n\n\t\tif (Configs.CONFIGURATION.hasCategory(\"logisticspipe.id\")\n\t\t\t\t|| Configs.CONFIGURATION.hasCategory(\"logisticsPipe.id\")) {\n\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\"Old config, please remove it and manually reconfigure LogisticPipes\");\n\t\t}\n\n\t\tConfigs.LOGISTICS_DETECTION_LENGTH = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"detectionLength\",\n\t\t\t\t\t\tConfigs.LOGISTICS_DETECTION_LENGTH,\n\t\t\t\t\t\t\"The maximum shortest length between logistics pipes. This is an indicator on the maxim depth of the recursion algorithm to discover logistics neighbours. A low value might use less CPU, a high value will allow longer pipe sections\")\n\t\t\t\t\t\t.getInt();\n\t\tConfigs.LOGISTICS_DETECTION_COUNT = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"detectionCount\",\n\t\t\t\t\t\tConfigs.LOGISTICS_DETECTION_COUNT,\n\t\t\t\t\t\t\"The maximum number of BuildCraft pipes (including forks) between logistics pipes. This is an indicator of the maximum amount of nodes the recursion algorithm will visit before giving up. As it is possible to fork a pipe connection using standard BC pipes the algorithm will attempt to discover all available destinations through that pipe. Do note that the logistics system will not interfere with the operation of non-logistics pipes. So a forked pipe will usually be sup-optimal, but it is possible. A low value might reduce CPU usage, a high value will be able to handle more complex pipe setups. If you never fork your connection between the logistics pipes this has the same meaning as detectionLength and the lower of the two will be used\")\n\t\t\t\t\t\t.getInt();\n\t\tConfigs.LOGISTICS_DETECTION_FREQUENCY = Math\n\t\t\t\t.max(Configs.CONFIGURATION\n\t\t\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\t\t\"reDetectionFrequency\",\n\t\t\t\t\t\t\t\tConfigs.LOGISTICS_DETECTION_FREQUENCY,\n\t\t\t\t\t\t\t\t\"The amount of time that passes between checks to see if it is still connected to its neighbours (Independently from block place detection). A low value will mean that it will correct wrong values faster but use more CPU. A high value means error correction takes longer, but CPU consumption is reduced. A value of 20 will check about every second (default 600 [30 seconds])\")\n\t\t\t\t\t\t\t\t.getInt(), 1);\n\n\t\tConfigs.MAX_ROBOT_DISTANCE = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL, \"maxRobotDistance\",\n\t\t\t\t\t\tConfigs.MAX_ROBOT_DISTANCE,\n\t\t\t\t\t\t\"The max. distance between two robots when there is no zone defined.\")\n\t\t\t\t\t\t.getInt();\n\t\tConfigs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL, \"ordererCountInvertWheel\",\n\t\t\t\t\t\tConfigs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL,\n\t\t\t\t\t\t\"Inverts the the mouse wheel scrolling for remote order number of items\")\n\t\t\t\t\t\t.getBoolean(false);\n\t\tConfigs.LOGISTICS_ORDERER_PAGE_INVERTWHEEL = Configs.CONFIGURATION.get(\n\t\t\t\tConfiguration.CATEGORY_GENERAL, \"ordererPageInvertWheel\",\n\t\t\t\tConfigs.LOGISTICS_ORDERER_PAGE_INVERTWHEEL,\n\t\t\t\t\"Inverts the the mouse wheel scrolling for remote order pages\")\n\t\t\t\t.getBoolean(false);\n\n\t\tConfigs.LOGISTICS_POWER_USAGE_DISABLED = Configs.CONFIGURATION.get(\n\t\t\t\tConfiguration.CATEGORY_GENERAL, \"powerUsageDisabled\",\n\t\t\t\tConfigs.LOGISTICS_POWER_USAGE_DISABLED,\n\t\t\t\t\"Disable the power usage trough LogisticsPipes\").getBoolean(\n\t\t\t\t\t\tfalse);\n\n\t\tConfigs.COMPILER_SPEED = Configs.CONFIGURATION.get(\n\t\t\t\tConfiguration.CATEGORY_GENERAL, \"compilerSpeed\",\n\t\t\t\tConfigs.COMPILER_SPEED,\n\t\t\t\t\"Multiplier for the work speed of the compiler\").getDouble(\n\t\t\t\t\t\t1.0);\n\n\t\tConfigs.LOGISTICS_HUD_RENDER_DISTANCE = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL, \"HUDRenderDistance\",\n\t\t\t\t\t\tConfigs.LOGISTICS_HUD_RENDER_DISTANCE,\n\t\t\t\t\t\t\"The max. distance between a player and the HUD that get's shown in blocks.\")\n\t\t\t\t\t\t.getInt();\n\n\t\tConfigs.DISPLAY_POPUP = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"displayPopup\",\n\t\t\t\t\t\tConfigs.DISPLAY_POPUP,\n\t\t\t\t\t\t\"Set the default configuration for the popup of the Orderer Gui. Should it be used?\")\n\t\t\t\t\t\t.getBoolean(false);\n\n\t\tConfigs.ENABLE_PARTICLE_FX = Configs.CONFIGURATION.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\"enableParticleFX\", Configs.ENABLE_PARTICLE_FX,\n\t\t\t\t\"Whether or not special particles will spawn.\")\n\t\t\t\t.getBoolean(false);\n\n\t\tif(Configs.CONFIGURATION.hasKey(Configs.CATEGORY_MULTITHREAD, \"enabled\")) {\n\t\t\t//ConfigCategory.remove is deprecated, but there's no other way to remove a key-value pair without completely recreating the config...\n\t\t\tConfigs.CONFIGURATION.getCategory(Configs.CATEGORY_MULTITHREAD).remove(\"enabled\");\n\t\t}\n\t\tConfigs.MULTI_THREAD_NUMBER = Configs.CONFIGURATION.get(Configs.CATEGORY_MULTITHREAD, \"count\",\n\t\t\t\tConfigs.MULTI_THREAD_NUMBER, \"Number of routing table update Threads, 0 to disable.\").getInt();\n\t\tif (Configs.MULTI_THREAD_NUMBER < 0) {\n\t\t\tConfigs.MULTI_THREAD_NUMBER = 0;\n\t\t\tConfigs.CONFIGURATION.get(Configs.CATEGORY_MULTITHREAD, \"count\",\n\t\t\t\t\tConfigs.MULTI_THREAD_NUMBER, \"Number of routing table update Threads, 0 to disable.\").set(Integer\n\t\t\t\t\t\t\t.toString(Configs.MULTI_THREAD_NUMBER));\n\t\t}\n\t\tConfigs.MULTI_THREAD_PRIORITY = Configs.CONFIGURATION\n\t\t\t\t.get(Configs.CATEGORY_MULTITHREAD, \"priority\", Configs.MULTI_THREAD_PRIORITY,\n\t\t\t\t\t\t\"Priority of the multiThread Threads. 10 is highest, 5 normal, 1 lowest\")\n\t\t\t\t\t\t.getInt();\n\t\tif (Configs.MULTI_THREAD_PRIORITY < 1 || Configs.MULTI_THREAD_PRIORITY > 10) {\n\t\t\tConfigs.MULTI_THREAD_PRIORITY = Thread.NORM_PRIORITY;\n\t\t\tConfigs.CONFIGURATION\n\t\t\t.get(Configs.CATEGORY_MULTITHREAD, \"priority\",\n\t\t\t\t\tConfigs.MULTI_THREAD_PRIORITY,\n\t\t\t\t\t\"Priority of the multiThread Threads. 10 is highest, 5 normal, 1 lowest\").set(Integer\n\t\t\t\t\t\t\t.toString(Thread.NORM_PRIORITY));\n\t\t}\n\n\t\tConfigs.DISABLE_ASYNC_WORK = Configs.CONFIGURATION.get(CATEGORY_PERFORMANCE, \"disableAsyncWork\",\n\t\t\tConfigs.DISABLE_ASYNC_WORK,\n\t\t\t\"Disables asynchronous work (currently Extractor and QuickSort modules)\").getBoolean();\n\t\tConfigs.MINIMUM_INVENTORY_SLOT_ACCESS_PER_TICK = Configs.CONFIGURATION.get(CATEGORY_PERFORMANCE, \"minSlotsPerTick\",\n\t\t\tConfigs.MINIMUM_INVENTORY_SLOT_ACCESS_PER_TICK,\n\t\t\t\"Minimum slots to access per tick for asynchronous modules (currently Extractor and QuickSort modules)\",\n\t\t\t1, 1024).getInt();\n\t\tConfigs.MAXIMUM_INVENTORY_SLOT_ACCESS_PER_TICK = Configs.CONFIGURATION.get(CATEGORY_PERFORMANCE, \"maxSlotsPerTick\",\n\t\t\tConfigs.MAXIMUM_INVENTORY_SLOT_ACCESS_PER_TICK,\n\t\t\t\"Maximum slots to access per tick (0 means infinite) for asynchronous modules (currently Extractor and QuickSort modules)\",\n\t\t\t0, 1024).getInt();\n\t\tConfigs.MINIMUM_JOB_TICK_LENGTH = Configs.CONFIGURATION.get(CATEGORY_PERFORMANCE, \"minJobTicks\",\n\t\t\tConfigs.MINIMUM_JOB_TICK_LENGTH,\n\t\t\t\"Minimum ticks to split work on within a job of asynchronous modules (currently Extractor and QuickSort modules)\",\n\t\t\t1, 1200).getInt();\n\n\t\tConfigs.POWER_USAGE_MULTIPLIER = Configs.CONFIGURATION.get(\n\t\t\t\tConfiguration.CATEGORY_GENERAL, \"powerUsageMultiplyer\",\n\t\t\t\tConfigs.POWER_USAGE_MULTIPLIER, \"A multiplier for the power usage.\")\n\t\t\t\t.getDouble(Configs.POWER_USAGE_MULTIPLIER);\n\n\t\tif (Configs.POWER_USAGE_MULTIPLIER <= 0) {\n\t\t\tConfigs.POWER_USAGE_MULTIPLIER = 1;\n\t\t\tConfigs.CONFIGURATION.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\"powerUsageMultiplyer\", Configs.POWER_USAGE_MULTIPLIER,\n\t\t\t\t\t\"A multiplier for the power usage.\").set(1);\n\t\t}\n\n\t\tConfigs.LOGISTICS_CRAFTING_TABLE_POWER_USAGE = Math\n\t\t\t\t.max(Configs.CONFIGURATION\n\t\t\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\t\t\"logisticsCraftingTablePowerUsage\",\n\t\t\t\t\t\t\t\tConfigs.LOGISTICS_CRAFTING_TABLE_POWER_USAGE,\n\t\t\t\t\t\t\t\t\"Number of LPower units the Logistics Crafting Table uses per craft.\")\n\t\t\t\t\t\t\t\t.getInt(), 0);\n\n\t\tConfigs.CHECK_FOR_UPDATES = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"checkForUpdates\",\n\t\t\t\t\t\tConfigs.CHECK_FOR_UPDATES,\n\t\t\t\t\t\t\"Should LogisticsPipes check for updates?\")\n\t\t\t\t\t\t.getBoolean(false);\n\n\t\tConfigs.OPAQUE = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"OpaquePipes\",\n\t\t\t\t\t\tConfigs.OPAQUE,\n\t\t\t\t\t\t\"Render every LP pipe opaque.\")\n\t\t\t\t\t\t.getBoolean(false);\n\n\t\tConfigs.EASTER_EGGS = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"easterEggs\",\n\t\t\t\t\t\tConfigs.EASTER_EGGS,\n\t\t\t\t\t\t\"Do you fancy easter eggs?\")\n\t\t\t\t\t\t.getBoolean(false);\n\n\t\tConfigs.CHASSIS_SLOTS_ARRAY = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL, \"chassisSlots\",\n\t\t\t\t\t\tConfigs.CHASSIS_SLOTS_ARRAY,\n\t\t\t\t\t\t\"The number of slots in a chassis pipe starting from MK1 to MK5. Because there are 5 tiers, there need to be 5 values (positive integers, zero is allowed).\")\n\t\t\t\t\t\t.getIntList();\n\n\t\tif (Configs.CHASSIS_SLOTS_ARRAY.length != 5) {\n\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\"The config file of Logistics Pipes needs to have 5 values (positive integers, zero is allowed) in ascending order in chassisSlots. \\nThe configuration contains \"\n\t\t\t\t\t\t\t+ Configs.CHASSIS_SLOTS_ARRAY.length + \" values.\");\n\t\t}\n\n\t\tfor (int i = 0; i < Configs.CHASSIS_SLOTS_ARRAY.length; i++) {\n\t\t\tif (Configs.CHASSIS_SLOTS_ARRAY[i] < 0)\n\t\t\t\tthrow new RuntimeException(\n\t\t\t\t\t\t\"The config file of Logistics Pipes needs to have 5 values (positive integers, zero is allowed) in ascending order in chassisSlots. \\nThe configuration contains \"\n\t\t\t\t\t\t\t\t+ Configs.CHASSIS_SLOTS_ARRAY[i] + \" as one of the values.\");\n\t\t}\n\t\tArrays.sort(Configs.CHASSIS_SLOTS_ARRAY);\n\n\t\tConfigs.CONFIGURATION.save();\n\t}\n\n\tpublic static void savePopupState() {\n\t\tProperty pageDisplayPopupProperty = Configs.CONFIGURATION\n\t\t\t\t.get(Configuration.CATEGORY_GENERAL,\n\t\t\t\t\t\t\"displayPopup\",\n\t\t\t\t\t\tConfigs.DISPLAY_POPUP,\n\t\t\t\t\t\t\"Set the default configuration for the popup of the Orderer Gui. Should it be used?\");\n\t\tpageDisplayPopupProperty.set(Boolean.toString(Configs.DISPLAY_POPUP));\n\t\tConfigs.CONFIGURATION.save();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/datafixer/DataFixerSolidBlockItems.java",
    "content": "package logisticspipes.datafixer;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.datafix.FixTypes;\nimport net.minecraft.util.datafix.IFixableData;\n\nimport logisticspipes.blocks.BlockDummy;\n\npublic class DataFixerSolidBlockItems implements IFixableData {\n\n\tpublic static final FixTypes TYPE = FixTypes.ITEM_INSTANCE;\n\tpublic static final int VERSION = 1;\n\n\t@Override\n\tpublic int getFixVersion() {\n\t\treturn VERSION;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound fixTagCompound(NBTTagCompound compound) {\n\t\tif (\n\t\t\t\t!compound.getString(\"id\").equals(\"logisticspipes:solid_block\") &&\n\t\t\t\t\t\t!compound.getString(\"id\").equals(\"logisticspipes:tile.logisticssolidblock\")\n\t\t) return compound;\n\n\t\tint meta = compound.getShort(\"Damage\");\n\t\tcompound.removeTag(\"Damage\");\n\t\tcompound.setString(\"id\", BlockDummy.updateItemMap.get(meta).getRegistryName().toString());\n\n\t\treturn compound;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/datafixer/DataFixerTE.java",
    "content": "package logisticspipes.datafixer;\n\nimport java.util.Map;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.datafix.FixTypes;\nimport net.minecraft.util.datafix.IFixableData;\n\nimport com.google.common.collect.ImmutableMap;\n\npublic class DataFixerTE implements IFixableData {\n\n\tpublic static final FixTypes TYPE = FixTypes.BLOCK_ENTITY;\n\tpublic static final int VERSION = 0;\n\n\tprivate Map<String, String> tileIDMap = ImmutableMap.<String, String>builder()\n\t\t\t.put(\"minecraft:logisticspipes.blocks.logisticssolderingtileentity\", \"logisticspipes:soldering_station\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.powertile.logisticspowerjuntiontileentity\", \"logisticspipes:power_junction\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.powertile.logisticsrfpowerprovidertileentity\", \"logisticspipes:power_provider_rf\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.powertile.logisticsic2powerprovidertileentity\", \"logisticspipes:power_provider_ic2\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.logisticssecuritytileentity\", \"logisticspipes:security_station\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.crafting.logisticscraftingtabletileentity\", \"logisticspipes:logistics_crafting_table\")\n\t\t\t.put(\"minecraft:logisticspipes.pipes.basic.logisticstilegenericpipe\", \"logisticspipes:pipe\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.stats.logisticsstatisticstileentity\", \"logisticspipes:statistics_table\")\n\t\t\t.put(\"minecraft:logisticspipes.blocks.logisticsprogramcompilertileentity\", \"logisticspipes:program_compiler\")\n\t\t\t.put(\"minecraft:logisticspipes.pipes.basic.logisticstilegenericsubmultiblock\", \"logisticspipes:submultiblock\")\n\t\t\t.build();\n\n\t@Override\n\tpublic int getFixVersion() {\n\t\treturn VERSION;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound fixTagCompound(NBTTagCompound compound) {\n\t\tString teName = compound.getString(\"id\");\n\n\t\tcompound.setString(\"id\", tileIDMap.getOrDefault(teName, teName));\n\n\t\treturn compound;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/datafixer/LPDataFixer.java",
    "content": "package logisticspipes.datafixer;\n\nimport net.minecraftforge.common.MinecraftForge;\nimport net.minecraftforge.common.util.ModFixs;\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport logisticspipes.LPConstants;\n\npublic class LPDataFixer {\n\n\tpublic static final LPDataFixer INSTANCE = new LPDataFixer();\n\n\tpublic static final int VERSION = 1;\n\n\tprivate LPDataFixer() {}\n\n\tpublic void init() {\n\t\tModFixs mf = FMLCommonHandler.instance().getDataFixer().init(LPConstants.LP_MOD_ID, VERSION);\n\t\tmf.registerFix(DataFixerTE.TYPE, new DataFixerTE());\n\t\tmf.registerFix(DataFixerSolidBlockItems.TYPE, new DataFixerSolidBlockItems());\n\t\tMinecraftForge.EVENT_BUS.register(new MissingMappingHandler());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/datafixer/MissingMappingHandler.java",
    "content": "package logisticspipes.datafixer;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.item.Item;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.event.RegistryEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.registry.ForgeRegistries;\n\nimport com.google.common.collect.ImmutableMap;\n\nimport logisticspipes.LPConstants;\n\npublic class MissingMappingHandler {\n\n\tprivate Map<String, String> itemIDMap = ImmutableMap.<String, String>builder()\n\t\t\t// pipes\n\t\t\t.put(\"item.pipeitemsbasiclogistics\", \"pipe_basic\")\n\t\t\t.put(\"item.pipeitemsbasictransport\", \"pipe_transport_basic\")\n\t\t\t.put(\"item.pipelogisticschassimk1\", \"pipe_chassis_mk1\")\n\t\t\t.put(\"item.pipelogisticschassimk2\", \"pipe_chassis_mk2\")\n\t\t\t.put(\"item.pipelogisticschassimk3\", \"pipe_chassis_mk3\")\n\t\t\t.put(\"item.pipelogisticschassimk4\", \"pipe_chassis_mk4\")\n\t\t\t.put(\"item.pipelogisticschassimk5\", \"pipe_chassis_mk5\")\n\t\t\t.put(\"item.pipeitemssupplierlogistics\", \"pipe_supplier\")\n\t\t\t.put(\"item.pipeitemscraftinglogistics\", \"pipe_crafting\")\n\t\t\t.put(\"item.pipeitemscraftinglogisticsmk2\", \"pipe_crafting_mk2\")\n\t\t\t.put(\"item.pipeitemscraftinglogisticsmk3\", \"pipe_crafting_mk3\")\n\t\t\t.put(\"item.pipeitemsfirewall\", \"pipe_firewall\")\n\t\t\t.put(\"item.pipeitemsproviderlogisticsmk2\", \"pipe_provider_mk2\")\n\t\t\t.put(\"item.pipeitemsrequestlogistics\", \"pipe_request\")\n\t\t\t.put(\"item.pipeitemsremoteordererlogistics\", \"pipe_remote_orderer\")\n\t\t\t.put(\"item.pipeitemssatellitelogistics\", \"pipe_satellite\")\n\t\t\t.put(\"item.pipeblockrequesttable\", \"pipe_request_table\")\n\t\t\t.put(\"item.pipeitemsproviderlogistics\", \"pipe_provider\")\n\t\t\t.put(\"item.pipeitemsinvsysconnector\", \"pipe_inventory_system_connector\")\n\t\t\t.put(\"item.pipeitemsrequestlogisticsmk2\", \"pipe_request_mk2\")\n\t\t\t.put(\"item.pipeitemssystemdestinationlogistics\", \"pipe_system_destination\")\n\t\t\t.put(\"item.pipeitemssystementrancelogistics\", \"pipe_system_entrance\")\n\t\t\t.put(\"item.pipefluidbasic\", \"pipe_fluid_basic\")\n\t\t\t.put(\"item.pipefluidprovider\", \"pipe_fluid_provider\")\n\t\t\t.put(\"item.pipefluidinsertion\", \"pipe_fluid_insertion\")\n\t\t\t.put(\"item.pipeitemsfluidsupplier\", \"pipe_fluid_supplier\")\n\t\t\t.put(\"item.pipefluidsuppliermk2\", \"pipe_fluid_supplier_mk2\")\n\t\t\t.put(\"item.pipefluidrequestlogistics\", \"pipe_fluid_request\")\n\t\t\t.put(\"item.pipefluidextractor\", \"pipe_fluid_extractor\")\n\t\t\t.put(\"item.pipefluidsatellite\", \"pipe_fluid_satellite\")\n\t\t\t.put(\"item.hstubeline\", \"pipe_hs_line\")\n\t\t\t.put(\"item.hstubegain\", \"pipe_hs_gain\")\n\t\t\t.put(\"item.hstubescurve\", \"pipe_hs_s_curve\")\n\t\t\t.put(\"item.hstubespeedup\", \"pipe_hs_speedup\")\n\t\t\t.put(\"item.hstubecurve\", \"pipe_hs_curve\")\n\n\t\t\t// modules\n\t\t\t.put(\"moduleblank\", \"module_blank\")\n\t\t\t.put(\"itemmodule.moduleitemsink\", \"module_item_sink\")\n\t\t\t.put(\"itemmodule.modulemodbaseditemsink\", \"module_item_sink_mod\")\n\t\t\t.put(\"itemmodule.moduleextractor\", \"module_extractor\")\n\t\t\t.put(\"itemmodule.moduleextractormk2\", \"module_extractor_mk2\")\n\t\t\t.put(\"itemmodule.moduleextractormk3\", \"module_extractor_mk3\")\n\t\t\t.put(\"itemmodule.modulecrafter\", \"module_crafter\")\n\t\t\t.put(\"itemmodule.modulecraftermk2\", \"module_crafter_mk2\")\n\t\t\t.put(\"itemmodule.modulecraftermk3\", \"module_crafter_mk3\")\n\t\t\t.put(\"itemmodule.modulepassivesupplier\", \"module_passive_supplier\")\n\t\t\t.put(\"itemmodule.modulepolymorphicitemsink\", \"module_item_sink_polymorphic\")\n\t\t\t.put(\"itemmodule.moduleadvancedextractor\", \"module_extractor_advanced\")\n\t\t\t.put(\"itemmodule.moduleadvancedextractormk2\", \"module_extractor_advanced_mk2\")\n\t\t\t.put(\"itemmodule.moduleadvancedextractormk3\", \"module_extractor_advanced_mk3\")\n\t\t\t.put(\"itemmodule.moduleccbasedquicksort\", \"module_quick_sort_cc\")\n\t\t\t.put(\"itemmodule.moduleenchantmentsink\", \"module_enchantment_sink\")\n\t\t\t.put(\"itemmodule.moduleenchantmentsinkmk2\", \"module_enchantment_sink_mk2\")\n\t\t\t.put(\"itemmodule.modulequicksort\", \"module_quick_sort\")\n\t\t\t.put(\"itemmodule.moduleprovider\", \"module_provider\")\n\t\t\t.put(\"itemmodule.moduleprovidermk2\", \"module_provider_mk2\")\n\t\t\t.put(\"itemmodule.moduleoredictitemsink\", \"module_item_sink_oredict\")\n\t\t\t.put(\"itemmodule.modulecreativetabbaseditemsink\", \"module_item_sink_creativetab\")\n\t\t\t.put(\"itemmodule.moduleterminus\", \"module_terminus\")\n\t\t\t.put(\"itemmodule.moduleactivesupplier\", \"module_active_supplier\")\n\t\t\t.put(\"itemmodule.moduleccbaseditemsink\", \"module_item_sink_cc\")\n\n\t\t\t// upgrades\n\t\t\t.put(\"itemmodule.rfpowersupplierupgrade\", \"upgrade_power_supplier_rf\")\n\t\t\t.put(\"itemmodule.bcpowersupplierupgrade\", \"upgrade_power_supplier_mj\")\n\t\t\t.put(\"itemmodule.ic2lvpowersupplierupgrade\", \"upgrade_power_supplier_eu_lv\")\n\t\t\t.put(\"itemmodule.ic2mvpowersupplierupgrade\", \"upgrade_power_supplier_eu_mv\")\n\t\t\t.put(\"itemmodule.ic2hvpowersupplierupgrade\", \"upgrade_power_supplier_eu_hv\")\n\t\t\t.put(\"itemmodule.ic2evpowersupplierupgrade\", \"upgrade_power_supplier_eu_ev\")\n\t\t\t.put(\"itemmodule.fluidcraftingupgrade\", \"upgrade_fluid_crafting\")\n\t\t\t.put(\"itemmodule.logiccontrollerupgrade\", \"upgrade_logic_controller\")\n\t\t\t.put(\"itemmodule.connectionupgradeconfig\", \"upgrade_disconnection\")\n\t\t\t.put(\"itemmodule.sneakyupgradeconfig\", \"upgrade_sneaky\")\n\t\t\t.put(\"itemmodule.ccremotecontrolupgrade\", \"upgrade_cc_remote_control\")\n\t\t\t.put(\"itemmodule.opaqueupgrade\", \"upgrade_opaque\")\n\t\t\t.put(\"itemmodule.powertransportationupgrade\", \"upgrade_power_transportation\")\n\t\t\t.put(\"itemmodule.combinedsneakyupgrade\", \"upgrade_sneaky_combination\")\n\t\t\t.put(\"itemmodule.fuzzyupgrade\", \"upgrade_fuzzy\")\n\t\t\t.put(\"itemmodule.advancedsatelliteupgrade\", \"upgrade_satellite_advanced\")\n\t\t\t.put(\"itemmodule.craftingcleanupupgrade\", \"upgrade_crafting_cleanup\")\n\t\t\t.put(\"itemmodule.craftingmonitoringupgrade\", \"upgrade_crafting_monitoring\")\n\t\t\t.put(\"itemmodule.upgrademoduleupgrade\", \"upgrade_module_upgrade\")\n\t\t\t.put(\"itemmodule.speedupgrade\", \"upgrade_speed\")\n\t\t\t.put(\"itemmodule.patternupgrade\", \"upgrade_pattern\")\n\t\t\t.put(\"itemmodule.craftingbyproductupgrade\", \"upgrade_crafting_byproduct\")\n\n\t\t\t// misc\n\t\t\t.put(\"logisticsfluidcontainer\", \"fluid_container\")\n\t\t\t.put(\"logisticsprogrammer\", \"logistics_programmer\")\n\t\t\t.put(\"remoteordereritem\", \"remote_orderer\")\n\t\t\t.put(\"logisticschips.0\", \"chip_basic\")\n\t\t\t.put(\"logisticschips.1\", \"chip_basic_raw\")\n\t\t\t.put(\"logisticschips.2\", \"chip_advanced\")\n\t\t\t.put(\"logisticschips.3\", \"chip_advanced_raw\")\n\t\t\t.put(\"logisticschips.4\", \"chip_fpga\")\n\t\t\t.put(\"logisticschips.5\", \"chip_fpga_raw\")\n\t\t\t.put(\"brokenitem\", \"broken_item\")\n\t\t\t.put(\"logisticsparts\", \"parts\")\n\t\t\t.put(\"pipecontroller\", \"pipe_controller\")\n\t\t\t.put(\"pipemanager\", \"pipe_manager\")\n\t\t\t.put(\"logisticshudglasses\", \"hud_glasses\")\n\t\t\t.put(\"logisticsitemcard\", \"item_card\")\n\t\t\t.put(\"itempipesigncreator\", \"sign_creator\")\n\t\t\t.put(\"itemdisk\", \"disk\")\n\t\t\t.build();\n\n\tprivate Map<String, String> blockIDMap = ImmutableMap.<String, String>builder()\n\t\t\t.put(\"tile.logisticssolidblock\", \"solid_block\")\n\t\t\t.put(\"tile.logisticsblockgenericsubmultiblock\", \"sub_multiblock\")\n\t\t\t.put(\"tile.logisticsblockgenericpipe\", \"pipe\")\n\t\t\t.build();\n\n\t// handled by data fixer\n\tprivate List<String> ignoreItems = Arrays.asList(\n\t\t\t\"solid_block\", \"tile.logisticssolidblock\"\n\t);\n\n\t@SubscribeEvent\n\tpublic void onMissingBlocks(RegistryEvent.MissingMappings<Block> e) {\n\t\tfor (RegistryEvent.MissingMappings.Mapping<Block> m : e.getMappings()) {\n\t\t\tString entry = blockIDMap.get(m.key.getPath());\n\t\t\tif (entry == null) continue;\n\t\t\tBlock value = ForgeRegistries.BLOCKS.getValue(new ResourceLocation(LPConstants.LP_MOD_ID, entry));\n\t\t\tif (value == null) continue;\n\t\t\tm.remap(value);\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void onMissingItems(RegistryEvent.MissingMappings<Item> e) {\n\t\tfor (RegistryEvent.MissingMappings.Mapping<Item> m : e.getMappings()) {\n\t\t\tString old = m.key.getPath();\n\t\t\tif (ignoreItems.contains(old)) {\n\t\t\t\tm.ignore();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tString entry = itemIDMap.get(old);\n\t\t\tif (entry == null) continue;\n\t\t\tItem value = ForgeRegistries.ITEMS.getValue(new ResourceLocation(LPConstants.LP_MOD_ID, entry));\n\t\t\tif (value == null) continue;\n\t\t\tm.remap(value);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/entity/FakeNetServerHandler.java",
    "content": "package logisticspipes.entity;\n\nimport java.net.SocketAddress;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\nimport javax.crypto.SecretKey;\n\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.network.EnumConnectionState;\nimport net.minecraft.network.EnumPacketDirection;\nimport net.minecraft.network.INetHandler;\nimport net.minecraft.network.NetHandlerPlayServer;\nimport net.minecraft.network.NetworkManager;\nimport net.minecraft.network.Packet;\nimport net.minecraft.network.play.client.CPacketAnimation;\nimport net.minecraft.network.play.client.CPacketChatMessage;\nimport net.minecraft.network.play.client.CPacketClickWindow;\nimport net.minecraft.network.play.client.CPacketClientSettings;\nimport net.minecraft.network.play.client.CPacketClientStatus;\nimport net.minecraft.network.play.client.CPacketCloseWindow;\nimport net.minecraft.network.play.client.CPacketConfirmTeleport;\nimport net.minecraft.network.play.client.CPacketConfirmTransaction;\nimport net.minecraft.network.play.client.CPacketCreativeInventoryAction;\nimport net.minecraft.network.play.client.CPacketCustomPayload;\nimport net.minecraft.network.play.client.CPacketEnchantItem;\nimport net.minecraft.network.play.client.CPacketEntityAction;\nimport net.minecraft.network.play.client.CPacketHeldItemChange;\nimport net.minecraft.network.play.client.CPacketInput;\nimport net.minecraft.network.play.client.CPacketKeepAlive;\nimport net.minecraft.network.play.client.CPacketPlayer;\nimport net.minecraft.network.play.client.CPacketPlayerAbilities;\nimport net.minecraft.network.play.client.CPacketPlayerDigging;\nimport net.minecraft.network.play.client.CPacketPlayerTryUseItem;\nimport net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock;\nimport net.minecraft.network.play.client.CPacketResourcePackStatus;\nimport net.minecraft.network.play.client.CPacketSpectate;\nimport net.minecraft.network.play.client.CPacketSteerBoat;\nimport net.minecraft.network.play.client.CPacketTabComplete;\nimport net.minecraft.network.play.client.CPacketUpdateSign;\nimport net.minecraft.network.play.client.CPacketUseEntity;\nimport net.minecraft.network.play.client.CPacketVehicleMove;\nimport net.minecraft.network.play.server.SPacketPlayerPosLook;\nimport net.minecraft.server.MinecraftServer;\nimport net.minecraft.util.text.ITextComponent;\n\nimport io.netty.channel.Channel;\nimport io.netty.channel.ChannelHandlerContext;\nimport io.netty.util.concurrent.Future;\nimport io.netty.util.concurrent.GenericFutureListener;\n\npublic class FakeNetServerHandler extends NetHandlerPlayServer {\n\n\tpublic static class NetworkManagerFake extends NetworkManager {\n\n\t\tpublic NetworkManagerFake() {\n\t\t\tsuper(EnumPacketDirection.CLIENTBOUND);\n\t\t}\n\n\t\t@Override\n\t\tpublic void channelActive(ChannelHandlerContext p_channelActive_1_) { }\n\n\t\t@Override\n\t\tpublic void setConnectionState(@Nonnull EnumConnectionState newState) { }\n\n\t\t@Override\n\t\tpublic void channelInactive(ChannelHandlerContext p_channelInactive_1_) { }\n\n\t\t@Override\n\t\tpublic void exceptionCaught(ChannelHandlerContext p_exceptionCaught_1_, @Nonnull Throwable p_exceptionCaught_2_) { }\n\n\t\t@Override\n\t\tpublic void setNetHandler(INetHandler handler) { }\n\n\t\t@Override\n\t\tpublic void sendPacket(@Nonnull Packet<?> packetIn) { }\n\n\t\t@Override\n\t\tpublic void sendPacket(@Nonnull Packet<?> packetIn, @Nonnull GenericFutureListener<? extends Future<? super Void>> listener, @Nonnull GenericFutureListener<? extends Future<? super Void>>... listeners) { }\n\n\t\t@Override\n\t\tpublic void processReceivedPackets() { }\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic SocketAddress getRemoteAddress() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isLocalChannel() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tpublic void enableEncryption(SecretKey key) { }\n\n\t\t@Override\n\t\tpublic boolean isChannelOpen() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic INetHandler getNetHandler() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic ITextComponent getExitMessage() {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic void setCompressionThreshold(int threshold) { }\n\n\t\t@Override\n\t\tpublic void disableAutoRead() { }\n\n\t\t@Override\n\t\tpublic void handleDisconnection() { }\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic Channel channel() {\n\t\t\treturn null;\n\t\t}\n\n\t}\n\n\tpublic FakeNetServerHandler(MinecraftServer server, EntityPlayerMP playerIn) {\n\t\tsuper(server, new NetworkManagerFake(), playerIn);\n\t}\n\n\t@Override\n\tpublic void update() { }\n\n\t@Override\n\tpublic void disconnect(@Nonnull final ITextComponent textComponent) { }\n\n\t@Override\n\tpublic void processInput(CPacketInput packetIn) { }\n\n\t@Override\n\tpublic void processVehicleMove(CPacketVehicleMove packetIn) { }\n\n\t@Override\n\tpublic void processConfirmTeleport(CPacketConfirmTeleport packetIn) { }\n\n\t@Override\n\tpublic void processPlayer(CPacketPlayer packetIn) { }\n\n\t@Override\n\tpublic void setPlayerLocation(double x, double y, double z, float yaw, float pitch) { }\n\n\t@Override\n\tpublic void setPlayerLocation(double x, double y, double z, float yaw, float pitch, Set<SPacketPlayerPosLook.EnumFlags> relativeSet) { }\n\n\t@Override\n\tpublic void processPlayerDigging(CPacketPlayerDigging packetIn) { }\n\n\t@Override\n\tpublic void processTryUseItemOnBlock(CPacketPlayerTryUseItemOnBlock packetIn) { }\n\n\t@Override\n\tpublic void processTryUseItem(CPacketPlayerTryUseItem packetIn) { }\n\n\t@Override\n\tpublic void handleSpectate(@Nonnull CPacketSpectate packetIn) { }\n\n\t@Override\n\tpublic void handleResourcePackStatus(CPacketResourcePackStatus packetIn) { }\n\n\t@Override\n\tpublic void processSteerBoat(@Nonnull CPacketSteerBoat packetIn) { }\n\n\t@Override\n\tpublic void onDisconnect(ITextComponent reason) { }\n\n\t@Override\n\tpublic void sendPacket(@Nonnull final Packet<?> packetIn) { }\n\n\t@Override\n\tpublic void processHeldItemChange(CPacketHeldItemChange packetIn) { }\n\n\t@Override\n\tpublic void processChatMessage(@Nonnull CPacketChatMessage packetIn) { }\n\n\t@Override\n\tpublic void handleAnimation(CPacketAnimation packetIn) { }\n\n\t@Override\n\tpublic void processEntityAction(CPacketEntityAction packetIn) { }\n\n\t@Override\n\tpublic void processUseEntity(CPacketUseEntity packetIn) { }\n\n\t@Override\n\tpublic void processClientStatus(CPacketClientStatus packetIn) { }\n\n\t@Override\n\tpublic void processCloseWindow(@Nonnull CPacketCloseWindow packetIn) { }\n\n\t@Override\n\tpublic void processClickWindow(CPacketClickWindow packetIn) { }\n\n\t@Override\n\tpublic void processEnchantItem(CPacketEnchantItem packetIn) { }\n\n\t@Override\n\tpublic void processCreativeInventoryAction(@Nonnull CPacketCreativeInventoryAction packetIn) { }\n\n\t@Override\n\tpublic void processConfirmTransaction(@Nonnull CPacketConfirmTransaction packetIn) { }\n\n\t@Override\n\tpublic void processUpdateSign(CPacketUpdateSign packetIn) { }\n\n\t@Override\n\tpublic void processKeepAlive(@Nonnull CPacketKeepAlive packetIn) { }\n\n\t@Override\n\tpublic void processPlayerAbilities(CPacketPlayerAbilities packetIn) { }\n\n\t@Override\n\tpublic void processTabComplete(CPacketTabComplete packetIn) { }\n\n\t@Override\n\tpublic void processClientSettings(@Nonnull CPacketClientSettings packetIn) { }\n\n\t@Override\n\tpublic void processCustomPayload(CPacketCustomPayload packetIn) { }\n}\n"
  },
  {
    "path": "common/logisticspipes/entity/FakePlayerLP.java",
    "content": "package logisticspipes.entity;\n\nimport java.util.List;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.crafting.IRecipe;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.text.ITextComponent;\nimport net.minecraft.util.text.TextComponentString;\nimport net.minecraft.world.WorldServer;\n\nimport net.minecraftforge.common.util.FakePlayer;\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport com.mojang.authlib.GameProfile;\n\n@SuppressWarnings(\"EntityConstructor\")\npublic class FakePlayerLP extends FakePlayer {\n\n\tpublic static GameProfile LPPLAYER = new GameProfile(UUID.fromString(\"e7d8e347-3828-4f39-b76f-ea519857c004\"), \"[LogisticsPipes]\");\n\n\tpublic String myName = \"[LogisticsPipes]\";\n\n\tpublic FakePlayerLP(WorldServer world) {\n\t\tsuper(world, LPPLAYER);\n\t\tconnection = new FakeNetServerHandler(FMLCommonHandler.instance().getMinecraftServerInstance(), this);\n\t\tthis.addedToChunk = false;\n\t\tthis.posX = 0;\n\t\tthis.posY = 0;\n\t\tthis.posZ = 0;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ITextComponent getDisplayName() {\n\t\treturn new TextComponentString(getName());\n\t}\n\n\t@Override\n\tpublic void onUpdate() { }\n\n\t@Override\n\tpublic void unlockRecipes(@Nonnull List<IRecipe> p_192021_1_) { }\n\n\t@Override\n\tpublic void unlockRecipes(ResourceLocation[] p_193102_1_) { }\n\n\t@Override\n\tpublic void resetRecipes(@Nonnull List<IRecipe> p_192022_1_) { }\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiCardManager.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.utils.CardManagementInventory;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class GuiCardManager extends LogisticsBaseGuiScreen {\n\n\tpublic GuiCardManager(EntityPlayer player) {\n\t\tsuper(180, 180, 0, 0);\n\t\tfinal CardManagementInventory Cinv = new CardManagementInventory();\n\t\tDummyContainer dummy = new DummyContainer(player, Cinv, new IGuiOpenControler() {\n\n\t\t\t@Override\n\t\t\tpublic void guiOpenedByPlayer(EntityPlayer player) {}\n\n\t\t\t@Override\n\t\t\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\t\t\tCinv.close(player, (int) player.posX, (int) player.posY, (int) player.posZ);\n\t\t\t}\n\t\t});\n\t\tdummy.addRestrictedSlot(0, Cinv, 21, 21, ItemModule.class);\n\t\tdummy.addRestrictedSlot(1, Cinv, 61, 21, ItemModule.class);\n\t\tdummy.addRestrictedSlot(2, Cinv, 41, 58, itemStack -> false);\n\t\tdummy.addRestrictedSlot(3, Cinv, 121, 39, LPItems.itemCard);\n\t\tfor (int i = 4; i < 7; i++) {\n\t\t\tdummy.addColorSlot(i, Cinv, 101, 21 + (i - 4) * 18);\n\t\t}\n\t\tfor (int i = 7; i < 10; i++) {\n\t\t\tdummy.addColorSlot(i, Cinv, 141, 21 + (i - 7) * 18);\n\t\t}\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 95);\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int j, int k) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, bottom - 85);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 20, guiTop + 20);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 60, guiTop + 20);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 40, guiTop + 57);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 120, guiTop + 38);\n\t\tdrawRect(guiLeft + 38, guiTop + 27, guiLeft + 60, guiTop + 31, Color.DARKER_GREY);\n\t\tdrawRect(guiLeft + 47, guiTop + 31, guiLeft + 51, guiTop + 57, Color.DARKER_GREY);\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 100, guiTop + 20 + i * 18);\n\t\t}\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 140, guiTop + 20 + i * 18);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiChassisPipe.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.pipe.ChassisGuiProvider;\nimport logisticspipes.network.packets.chassis.ChassisGUI;\nimport logisticspipes.network.packets.gui.GuiClosePacket;\nimport logisticspipes.network.packets.gui.OpenUpgradePacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.upgrades.ModuleUpgradeManager;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.string.StringUtils;\nimport network.rs485.logisticspipes.module.Gui;\n\npublic class GuiChassisPipe extends LogisticsBaseGuiScreen {\n\n\tprivate final PipeLogisticsChassis chassisPipe;\n\tprivate final IInventory _moduleInventory;\n\t//private final GuiScreen _previousGui;\n\tprivate final List<SmallGuiButton> moduleConfigButtons = new LinkedList<>();\n\n\tprivate final Slot[] upgradeSlots = new Slot[2 * Configs.CHASSIS_SLOTS_ARRAY[4]];\n\tprivate GuiButton[] upgradeConfig;\n\n\tprivate final boolean hasUpgradeModuleUpgrade;\n\n\tpublic GuiChassisPipe(EntityPlayer player, PipeLogisticsChassis chassis, boolean hasUpgradeModuleUpgrade) { //, GuiScreen previousGui) {\n\t\tsuper(null);\n\t\tchassisPipe = chassis;\n\t\t_moduleInventory = chassis.getModuleInventory();\n\t\t//_previousGui = previousGui;\n\t\tthis.hasUpgradeModuleUpgrade = hasUpgradeModuleUpgrade;\n\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, _moduleInventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 9 + 20* chassisPipe.getChassisSize());\n\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++)\n\t\t\tdummy.addModuleSlot(i, _moduleInventory, 18, 9 + 20 * i, chassisPipe);\n\n\t\tif (hasUpgradeModuleUpgrade) {\n\t\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++) {\n\t\t\t\tfinal int fI = i;\n\t\t\t\tModuleUpgradeManager upgradeManager = chassisPipe.getModuleUpgradeManager(i);\n\t\t\t\tupgradeSlots[i * 2] = dummy.addUpgradeSlot(0, upgradeManager, 0, 145, 9 + i * 20, itemStack -> ChassisGuiProvider.checkStack(itemStack,\n\t\t\t\t\tchassisPipe, fI));\n\t\t\t\tupgradeSlots[i * 2 + 1] = dummy.addUpgradeSlot(1, upgradeManager, 1, 165, 9 + i * 20, itemStack -> ChassisGuiProvider.checkStack(itemStack,\n\t\t\t\t\tchassisPipe, fI));\n\t\t\t}\n\t\t}\n\n\t\tinventorySlots = dummy;\n\n\t\tint playerInventoryWidth = 162;\n\t\tint playerInventoryHeight = 76;\n\n\t\txSize = playerInventoryWidth + 26;\n\t\tySize = playerInventoryHeight + 14 + (20 * chassisPipe.getChassisSize());\n\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\n\t\tint left = width / 2 - xSize / 2;\n\t\tint top = height / 2 - ySize / 2;\n\n\t\tbuttonList.clear();\n\t\tmoduleConfigButtons.clear();\n\t\tupgradeConfig = new GuiButton[chassisPipe.getChassisSize() * 2];\n\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++) {\n\t\t\tmoduleConfigButtons.add(addButton(new SmallGuiButton(i, left + 5, top + 12 + 20 * i, 10, 10, \"!\")));\n\t\t\tif (_moduleInventory == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tupdateModuleConfigButtonVisibility(i);\n\n\t\t\tif (hasUpgradeModuleUpgrade) {\n\t\t\t\tupgradeConfig[i * 2] = addButton(new SmallGuiButton(100 + i, guiLeft + 134, guiTop + 12 + i * 20, 10, 10, \"!\"));\n\t\t\t\tupgradeConfig[i * 2].visible = chassisPipe.getModuleUpgradeManager(i).hasGuiUpgrade(0);\n\t\t\t\tupgradeConfig[i * 2 + 1] = addButton(new SmallGuiButton(120 + i, guiLeft + 182, guiTop + 12 + i * 20, 10, 10, \"!\"));\n\t\t\t\tupgradeConfig[i * 2 + 1].visible = chassisPipe.getModuleUpgradeManager(i).hasGuiUpgrade(1);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void updateModuleConfigButtonVisibility(int slot) {\n\t\tItemStack module = _moduleInventory.getStackInSlot(slot);\n\t\tLogisticsModule subModule = chassisPipe.getSubModule(slot);\n\t\tif (module.isEmpty() || subModule == null) {\n\t\t\tmoduleConfigButtons.get(slot).visible = false;\n\t\t} else {\n\t\t\tmoduleConfigButtons.get(slot).visible = subModule instanceof Gui;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(GuiClosePacket.class).setTilePos(chassisPipe.container));\n\t\tsuper.onGuiClosed();\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) {\n\t\tif (guibutton.id >= 0 && guibutton.id <= chassisPipe.getChassisSize()) {\n\t\t\tLogisticsModule module = chassisPipe.getSubModule(guibutton.id);\n\t\t\tif (module != null) {\n\t\t\t\tfinal ModernPacket packet = PacketHandler.getPacket(ChassisGUI.class).setButtonID(guibutton.id).setPosX(\n\t\t\t\t\tchassisPipe.getX()).setPosY(chassisPipe.getY()).setPosZ(chassisPipe.getZ());\n\t\t\t\tMainProxy.sendPacketToServer(packet);\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < upgradeConfig.length; i++) {\n\t\t\tif (upgradeConfig[i] == guibutton) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OpenUpgradePacket.class).setSlot(upgradeSlots[i]));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++) {\n\t\t\tupdateModuleConfigButtonVisibility(i);\n\t\t}\n\t\tif (hasUpgradeModuleUpgrade) {\n\t\t\tfor (int i = 0; i < upgradeConfig.length; i++) {\n\t\t\t\tupgradeConfig[i].visible = chassisPipe.getModuleUpgradeManager(i / 2).hasGuiUpgrade(i % 2);\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++)\n\t\t\tmc.fontRenderer.drawString(getModuleName(i), 40, 14 + 20 * i, 0x404040);\n\t}\n\n\tprivate String getModuleName(int slot) {\n\t\tif (_moduleInventory == null) {\n\t\t\treturn \"\";\n\t\t}\n\t\tif (_moduleInventory.getStackInSlot(slot).isEmpty()) {\n\t\t\treturn \"\";\n\t\t}\n\t\tif (!(_moduleInventory.getStackInSlot(slot).getItem() instanceof ItemModule)) {\n\t\t\treturn \"\";\n\t\t}\n\t\tString name = _moduleInventory.getStackInSlot(slot).getItem().getItemStackDisplayName(_moduleInventory.getStackInSlot(slot));\n\t\tif (!hasUpgradeModuleUpgrade) {\n\t\t\treturn name;\n\t\t}\n\t\treturn StringUtils.getWithMaxWidth(name, 100, fontRenderer);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++)\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 17, guiTop + 8 + 20 * i);\n\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 18, guiTop + 9 + 20 * chassisPipe.getChassisSize());\n\n\t\tif (hasUpgradeModuleUpgrade) {\n\t\t\tfor (int i = 0; i < chassisPipe.getChassisSize(); i++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 144, guiTop + 8 + i * 20);\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 164, guiTop + 8 + i * 20);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiCraftingPipe.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport kotlin.Unit;\nimport lombok.Getter;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.gui.modules.ModuleBaseGui;\nimport logisticspipes.gui.popup.GuiSelectSatellitePopup;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.cpipe.CPipeCleanupImport;\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate;\nimport logisticspipes.network.packets.pipe.CraftingPipeSetSatellitePacket;\nimport logisticspipes.pipes.upgrades.CraftingByproductUpgrade;\nimport logisticspipes.pipes.upgrades.CraftingCleanupUpgrade;\nimport logisticspipes.pipes.upgrades.FluidCraftingUpgrade;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.extension.GuiExtension;\nimport network.rs485.logisticspipes.gui.widget.Label;\nimport network.rs485.logisticspipes.gui.widget.VerticalLabel;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.IntListProperty;\nimport network.rs485.logisticspipes.property.IntegerProperty;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay;\nimport network.rs485.logisticspipes.property.layer.ValuePropertyOverlay;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiCraftingPipe extends ModuleBaseGui {\n\n\tprivate static final String PREFIX = \"gui.crafting.\";\n\n\t@Getter\n\tprivate final ModuleCrafter craftingModule;\n\tprivate final EntityPlayer _player;\n\tprivate final GuiButton[] normalButtonArray;\n\tprivate final GuiButton[][] advancedSatButtonArray;\n\tprivate final GuiButton[][] liquidGuiParts;\n\tprivate final boolean isAdvancedSat;\n\tprivate final int liquidCrafter;\n\tprivate final boolean hasByproductExtractor;\n\tprivate final int cleanupSize;\n\tprivate final int[] fluidSlotIDs;\n\tprivate final int byproductSlotID;\n\tprivate final int[] cleanupSlotIDs;\n\tprivate final PropertyLayer propertyLayer;\n\tprivate final ValuePropertyOverlay<Boolean, BooleanProperty> cleanupModeIsExcludeOverlay;\n\tprivate final ValuePropertyOverlay<Integer, IntegerProperty> craftingPriorityOverlay;\n\tprivate final PropertyOverlay<List<Integer>, IntListProperty> liquidAmountsOverlay;\n\n\tprivate GuiButton cleanupModeButton;\n\tprivate final Label[] satellitePipeLabels;\n\tprivate Label satellitePipeLabel;\n\n\tpublic GuiCraftingPipe(EntityPlayer player, ModuleCrafter module, boolean isAdvancedSat,\n\t\t\tint liquidCrafter, int[] amount, boolean hasByproductExtractor, boolean isFuzzy, int cleanupSize,\n\t\t\tboolean cleanupExclude) {\n\t\tsuper(null, module);\n\t\tcraftingModule = module;\n\t\t_player = player;\n\t\tthis.isAdvancedSat = isAdvancedSat;\n\t\tthis.liquidCrafter = liquidCrafter;\n\t\tthis.hasByproductExtractor = hasByproductExtractor;\n\t\tthis.cleanupSize = cleanupSize;\n\t\tcraftingModule.cleanupModeIsExclude.setValue(cleanupExclude);\n\n\t\tpropertyLayer = new PropertyLayer(craftingModule.getProperties());\n\t\tcleanupModeIsExcludeOverlay = propertyLayer.overlay(craftingModule.cleanupModeIsExclude);\n\t\tpropertyLayer.addObserver(craftingModule.cleanupModeIsExclude, this::updateCleanupModeButton);\n\t\tcraftingPriorityOverlay = propertyLayer.overlay(craftingModule.priority);\n\t\tliquidAmountsOverlay = propertyLayer.overlay(craftingModule.liquidAmounts);\n\n\t\tif (!hasByproductExtractor) {\n\t\t\txSize = 177;\n\t\t} else {\n\t\t\txSize = 217;\n\t\t}\n\n\t\tif (!isAdvancedSat) {\n\t\t\tySize = 187;\n\t\t} else {\n\t\t\tySize = 187 + 30;\n\t\t}\n\n\t\tDummyContainer dummy = new DummyContainer(player.inventory,\n\t\t\t\tpropertyLayer.writeProp(craftingModule.dummyInventory));\n\t\tdummy.addNormalSlotsForPlayerInventory(8, ySize - 82);\n\n\t\t// Input slots\n\t\tfor (int l = 0; l < 9; l++) {\n\t\t\tif (isFuzzy) {\n\t\t\t\tdummy.addFuzzyDummySlot(l, 8 + l * 18, 18, craftingModule.inputFuzzy(l));\n\t\t\t} else {\n\t\t\t\tdummy.addDummySlot(l, 8 + l * 18, 18);\n\t\t\t}\n\t\t}\n\n\t\t// Output slot\n\t\tint yPosOutput = 55;\n\t\tif (isAdvancedSat) yPosOutput = 105;\n\t\tif (isFuzzy) {\n\t\t\tdummy.addFuzzyDummySlot(9, 85, yPosOutput, craftingModule.outputFuzzy());\n\t\t} else {\n\t\t\tdummy.addDummySlot(9, 85, yPosOutput);\n\t\t}\n\n\t\tliquidGuiParts = new GuiButton[liquidCrafter][];\n\t\tfluidSlotIDs = new int[liquidCrafter];\n\n\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\tint liquidLeft;\n\t\t\tif (isAdvancedSat) {\n\t\t\t\tliquidLeft = -40;\n\t\t\t} else {\n\t\t\t\tliquidLeft = -(liquidCrafter * 40) + (i * 40);\n\t\t\t}\n\t\t\tfluidSlotIDs[i] = extensionControllerLeft.registerControlledSlot(dummy.addFluidSlot(i,\n\t\t\t\t\tcraftingModule.liquidInventory, liquidLeft + 11, 24));\n\t\t}\n\n\t\tif (hasByproductExtractor) {\n\t\t\tbyproductSlotID = extensionControllerLeft.registerControlledSlot(dummy.addDummySlot(10, -26, 29));\n\t\t} else {\n\t\t\tbyproductSlotID = -1;\n\t\t}\n\n\t\tcleanupSlotIDs = new int[cleanupSize * 3];\n\t\tfor (int y = 0; y < cleanupSize; y++) {\n\t\t\tfor (int x = 0; x < 3; x++) {\n\t\t\t\tcleanupSlotIDs[y * 3 + x] = extensionControllerLeft.registerControlledSlot(dummy.addDummySlot(y * 3 + x,\n\t\t\t\t\t\tcraftingModule.cleanupInventory, x * 18 - 57, y * 18 + 13));\n\t\t\t}\n\t\t}\n\n\t\tinventorySlots = dummy;\n\t\tcraftingModule.liquidAmounts.replaceContent(amount);\n\t\tnormalButtonArray = new GuiButton[7];\n\t\tadvancedSatButtonArray = new GuiButton[9][2];\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tadvancedSatButtonArray[i] = new GuiButton[2];\n\t\t}\n\t\tsatellitePipeLabels = new Label[9];\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\textensionControllerLeft.clear();\n\t\tbuttonList.clear();\n\t\tFluidCraftingExtension extension = null;\n\t\tif (!isAdvancedSat) {\n\t\t\tif (liquidCrafter != 0) {\n\t\t\t\textension = new FluidCraftingExtension(0);\n\t\t\t}\n\t\t\taddButton(normalButtonArray[0] = new SmallGuiButton(0, (width - xSize) / 2 + 125, (height - ySize) / 2 + 57, 37, 10, TextUtil.translate(PREFIX + \"Select\")));\n\t\t\tnormalButtonArray[0].enabled = craftingModule.getSlot().isInWorld();\n\t\t\taddButton(normalButtonArray[1] = new SmallGuiButton(3, (width - xSize) / 2 + 39, (height - ySize) / 2 + 50, 37, 10, TextUtil.translate(GuiCraftingPipe.PREFIX + \"Import\")));\n\t\t\taddButton(normalButtonArray[2] = new SmallGuiButton(4, (width - xSize) / 2 + 6, (height - ySize) / 2 + 50, 28, 10, TextUtil.translate(GuiCraftingPipe.PREFIX + \"Open\")));\n\t\t\taddButton(normalButtonArray[3] = new SmallGuiButton(20, (width - xSize) / 2 + 155, (height - ySize) / 2 + 85, 10, 10, \">\"));\n\t\t\taddButton(normalButtonArray[4] = new SmallGuiButton(21, (width - xSize) / 2 + 120, (height - ySize) / 2 + 85, 10, 10, \"<\"));\n\t\t\tif (liquidCrafter != 0) {\n\t\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(normalButtonArray[5] = new SmallGuiButton(22, guiLeft - (liquidCrafter * 40) / 2 - 18, guiTop + 158, 37, 10, TextUtil.translate(PREFIX + \"Select\")))));\n\t\t\t}\n\t\t\tsatellitePipeLabel = new Label(craftingModule.clientSideSatelliteNames.satelliteName, 115, 43, 55, 0x404040, 0xff8b8b8b);\n\t\t} else {\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\taddButton(advancedSatButtonArray[i][0] = new SmallGuiButton(30 + i, (width - xSize) / 2 + 9 + 18 * i, (height - ySize) / 2 + 75, 17, 10, TextUtil.translate(PREFIX + \"Sel\")));\n\t\t\t\tsatellitePipeLabels[i] = new VerticalLabel(craftingModule.clientSideSatelliteNames.advancedSatelliteNameArray[i], 11 + (i * 18), 37, 36, 0x404040, 0xffc6c6c6);\n\t\t\t}\n\t\t\taddButton(normalButtonArray[1] = new SmallGuiButton(3, (width - xSize) / 2 + 39, (height - ySize) / 2 + 100, 37, 10, TextUtil.translate(GuiCraftingPipe.PREFIX + \"Import\")));\n\t\t\taddButton(normalButtonArray[2] = new SmallGuiButton(4, (width - xSize) / 2 + 6, (height - ySize) / 2 + 100, 28, 10, TextUtil\n\t\t\t\t\t.translate(GuiCraftingPipe.PREFIX + \"Open\")));\n\t\t\taddButton(normalButtonArray[3] = new SmallGuiButton(20, (width - xSize) / 2 + 155, (height - ySize) / 2 + 105, 10, 10, \">\"));\n\t\t\taddButton(normalButtonArray[4] = new SmallGuiButton(21, (width - xSize) / 2 + 120, (height - ySize) / 2 + 105, 10, 10, \"<\"));\n\t\t}\n\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\tif (isAdvancedSat) {\n\t\t\t\textension = new FluidCraftingExtension(i);\n\t\t\t}\n\t\t\tint liquidLeft;\n\t\t\tif (isAdvancedSat) {\n\t\t\t\tliquidLeft = guiLeft - 40;\n\t\t\t} else {\n\t\t\t\tliquidLeft = guiLeft - (liquidCrafter * 40) + (i * 40);\n\t\t\t}\n\t\t\tliquidGuiParts[i] = new GuiButton[10];\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][0] = new SmallGuiButton(100 + 10 * i + 0, liquidLeft + 22, guiTop + 65, 10, 10, \"+\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][1] = new SmallGuiButton(100 + 10 * i + 1, liquidLeft + 22, guiTop + 85, 10, 10, \"+\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][2] = new SmallGuiButton(100 + 10 * i + 2, liquidLeft + 22, guiTop + 105, 10, 10, \"+\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][3] = new SmallGuiButton(100 + 10 * i + 3, liquidLeft + 22, guiTop + 125, 10, 10, \"+\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][4] = new SmallGuiButton(100 + 10 * i + 4, liquidLeft + 8, guiTop + 65, 10, 10, \"-\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][5] = new SmallGuiButton(100 + 10 * i + 5, liquidLeft + 8, guiTop + 85, 10, 10, \"-\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][6] = new SmallGuiButton(100 + 10 * i + 6, liquidLeft + 8, guiTop + 105, 10, 10, \"-\"))));\n\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][7] = new SmallGuiButton(100 + 10 * i + 7, liquidLeft + 8, guiTop + 125, 10, 10, \"-\"))));\n\t\t\tif (isAdvancedSat) {\n\t\t\t\tfinal SmallGuiButton advancedSatelliteSelector = new SmallGuiButton(100 + 10 * i + 8, liquidLeft + 2, guiTop + 160, 37, 10, TextUtil.translate(PREFIX + \"Select\"));\n\t\t\t\tadvancedSatelliteSelector.enabled = craftingModule.getSlot().isInWorld();\n\t\t\t\textension.registerButton(extensionControllerLeft.registerControlledButton(addButton(liquidGuiParts[i][8] = advancedSatelliteSelector)));\n\t\t\t\textensionControllerLeft.addExtension(extension);\n\t\t\t}\n\t\t\textension.registerSlot(fluidSlotIDs[i]);\n\t\t}\n\t\tif (!isAdvancedSat && liquidCrafter != 0) {\n\t\t\textensionControllerLeft.addExtension(extension);\n\t\t}\n\t\tif (hasByproductExtractor) {\n\t\t\tByproductExtension byproductExtension = new ByproductExtension();\n\t\t\tbyproductExtension.registerSlot(byproductSlotID);\n\t\t\textensionControllerLeft.addExtension(byproductExtension);\n\t\t}\n\t\tif (cleanupSize > 0) {\n\t\t\tCleanupExtension cleanupExtension = new CleanupExtension();\n\t\t\tcleanupExtension.registerButton(extensionControllerLeft.registerControlledButton(addButton(cleanupModeButton = new SmallGuiButton(24, guiLeft - 56, guiTop + 18 + (18 * cleanupSize), 50, 10, TextUtil.translate(GuiCraftingPipe.PREFIX + (\n\t\t\t\t\tcleanupModeIsExcludeOverlay.get() ? \"Exclude\" : \"Include\"))))));\n\t\t\tcleanupExtension.registerButton(\n\t\t\t\textensionControllerLeft.registerControlledButton(addButton(new SmallGuiButton(25, guiLeft - 56, guiTop + 32 + (18 * cleanupSize), 50, 10, TextUtil.translate(GuiCraftingPipe.PREFIX + \"Import\")))));\n\t\t\tfor (int i = 0; i < cleanupSize * 3; i++) {\n\t\t\t\tcleanupExtension.registerSlot(cleanupSlotIDs[i]);\n\t\t\t}\n\t\t\textensionControllerLeft.addExtension(cleanupExtension);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\t/*\n\t\tif(5 <= guibutton.id && guibutton.id < 11) {\n\t\t\t_pipe.handleStackMove(guibutton.id - 5);\n\t\t}\n\t\t */\n\t\tif (30 <= guibutton.id && guibutton.id < 40) {\n\t\t\topenSubGuiForSatelliteSelection(10 + (guibutton.id - 30), false);\n\t\t}\n\t\tif (100 <= guibutton.id && guibutton.id < 200) {\n\t\t\tint i = guibutton.id - 100;\n\t\t\tint action = i % 10;\n\t\t\ti -= action;\n\t\t\ti /= 10;\n\t\t\tif (action < 8) {\n\t\t\t\tint amount = 0;\n\t\t\t\tswitch (action) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tamount = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tamount = 10;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tamount = 100;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tamount = 1000;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 4:\n\t\t\t\t\t\tamount = -1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 5:\n\t\t\t\t\t\tamount = -10;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 6:\n\t\t\t\t\t\tamount = -100;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 7:\n\t\t\t\t\t\tamount = -1000;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcraftingModule.changeFluidAmount(amount, i, _player);\n\t\t\t} else if (action == 8) {\n\t\t\t\topenSubGuiForSatelliteSelection(110 + i, true);\n\t\t\t}\n\t\t}\n\t\tswitch (guibutton.id) {\n\t\t\tcase 0:\n\t\t\t\topenSubGuiForSatelliteSelection(0, false);\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tcraftingModule.importFromCraftingTable(_player);\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tcraftingModule.openAttachedGui(_player);\n\t\t\t\t//LogisticsEventListener.addGuiToReopen(_pipe.getX(), _pipe.getY(), _pipe.getZ(), 0); //TODO reactivate this\n\t\t\t\tbreak;\n\t\t\tcase 20:\n\t\t\t\tcraftingPriorityOverlay.write(prop -> prop.increase(1));\n\t\t\t\tbreak;\n\t\t\tcase 21:\n\t\t\t\tcraftingPriorityOverlay.write(prop -> prop.increase(-1));\n\t\t\t\tbreak;\n\t\t\tcase 22:\n\t\t\t\topenSubGuiForSatelliteSelection(100, true);\n\t\t\t\tbreak;\n\t\t\tcase 24:\n\t\t\t\tcleanupModeIsExcludeOverlay.write(BooleanProperty::toggle);\n\t\t\t\tbreak;\n\t\t\tcase 25:\n\t\t\t\tcleanupModeIsExcludeOverlay.set(false);\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(CPipeCleanupImport.class).setModulePos(craftingModule));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\tprivate void openSubGuiForSatelliteSelection(int id, boolean fluidSatellite) {\n\t\tif (module.getSlot().isInWorld()) {\n\t\t\tthis.setSubGui(new GuiSelectSatellitePopup(module.getBlockPos(), fluidSatellite, uuid ->\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(CraftingPipeSetSatellitePacket.class).setPipeID(uuid).setInteger(id).setModulePos(module))));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t\tpropertyLayer.unregister();\n\t\tif (this.mc.player != null && !propertyLayer.getProperties().isEmpty()) {\n\t\t\t// send update to server, when there are changed properties\n\t\t\tMainProxy.sendPacketToServer(ModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(module));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {\n\t\tsuper.drawGuiContainerForegroundLayer(mouseX, mouseY);\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Inputs\"), 18, 7, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Inventory\"), 10, ySize - 93, 0x404040);\n\n\t\tif (!isAdvancedSat) {\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Output\"), 77, 40, 0x404040);\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Satellite\"), 123, 7, 0x404040);\n\t\t\tif (craftingModule.clientSideSatelliteNames.satelliteName.isEmpty()) {\n\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Off\"), 135, 43, 0x404040);\n\t\t\t} else {\n\t\t\t\tif (!satellitePipeLabel.isTextEqual(craftingModule.clientSideSatelliteNames.satelliteName)) {\n\t\t\t\t\tsatellitePipeLabel.setText(craftingModule.clientSideSatelliteNames.satelliteName);\n\t\t\t\t}\n\t\t\t\tsatellitePipeLabel.draw(mouseX - guiLeft, mouseY - guiTop);\n\t\t\t}\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Priority\") + \":\", 123, 75, 0x404040);\n\t\t\tmc.fontRenderer.drawString(String.valueOf(craftingPriorityOverlay.get()), 143 - (mc.fontRenderer.getStringWidth(String.valueOf(craftingPriorityOverlay.get())) / 2), 87, 0x404040);\n\t\t} else {\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tif (craftingModule.clientSideSatelliteNames.advancedSatelliteNameArray[i].isEmpty()) {\n\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Off\"), 9 + (i * 18), 57, 0x404040);\n\t\t\t\t} else {\n\t\t\t\t\tif (!satellitePipeLabels[i].isTextEqual(craftingModule.clientSideSatelliteNames.advancedSatelliteNameArray[i])) {\n\t\t\t\t\t\tsatellitePipeLabels[i].setText(craftingModule.clientSideSatelliteNames.advancedSatelliteNameArray[i]);\n\t\t\t\t\t}\n\t\t\t\t\tsatellitePipeLabels[i].draw(mouseX - guiLeft, mouseY - guiTop);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Output\"), 77, 90, 0x404040);\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Priority\") + \":\", 123, 95, 0x404040);\n\t\t\tmc.fontRenderer.drawString(String.valueOf(craftingPriorityOverlay.get()), 143 - (mc.fontRenderer.getStringWidth(String.valueOf(craftingPriorityOverlay.get())) / 2), 107, 0x404040);\n\t\t}\n\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, guiLeft + xSize - (hasByproductExtractor ? 40 : 0), guiTop + ySize, zLevel, true, true, true, true, true);\n\n\t\tif (!isAdvancedSat) {\n\t\t\tGui.drawRect(guiLeft + 115, guiTop + 4, guiLeft + 170, guiTop + 70, 0xff8B8B8B);\n\t\t}\n\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 7 + (18 * i), guiTop + 17);\n\t\t}\n\t\tif (!isAdvancedSat) {\n\t\t\tGuiGraphics.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 50);\n\t\t} else {\n\t\t\tGuiGraphics.drawBigSlotBackground(mc, guiLeft + 80, guiTop + 100);\n\t\t}\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 8, guiTop + ySize - 82);\n\n\t\tsuper.renderExtensions();\n\t}\n\n\tprivate Unit updateCleanupModeButton(Property<Boolean> prop) {\n\t\tcleanupModeButton.displayString = TextUtil.translate(\n\t\t\t\tGuiCraftingPipe.PREFIX + (prop.copyValue() ? \"Exclude\" : \"Include\"));\n\t\treturn Unit.INSTANCE;\n\t}\n\n\tprivate final class FluidCraftingExtension extends GuiExtension {\n\n\t\tprivate final int id;\n\n\t\tpublic FluidCraftingExtension(int id) {\n\t\t\tthis.id = id;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getFinalWidth() {\n\t\t\tif (isAdvancedSat) {\n\t\t\t\treturn 42;\n\t\t\t} else {\n\t\t\t\treturn 2 + liquidCrafter * 40;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic int getFinalHeight() {\n\t\t\treturn 175;\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForeground(int left, int top) {\n\t\t\tif (!isFullyExtended()) {\n\t\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\t\tItemStack stack = new ItemStack(ItemUpgrade.getAndCheckUpgrade(LPItems.upgrades.get(FluidCraftingUpgrade.getName())));\n\t\t\t\titemRender.renderItemAndEffectIntoGUI(stack, left + 5, top + 5);\n\t\t\t\titemRender.renderItemOverlayIntoGUI(fontRenderer, stack, left + 5, top + 5, \"\");\n\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t}\n\t\t\titemRender.zLevel = 0.0F;\n\n\t\t\tif (!isAdvancedSat && liquidCrafter > 1 && !isFullyExtended()) {\n\t\t\t\tString s = Integer.toString(liquidCrafter);\n\t\t\t\tmc.fontRenderer.drawStringWithShadow(s, left + 22 - fontRenderer.getStringWidth(s), top + 14, 16777215);\n\t\t\t}\n\t\t\tif (isFullyExtended()) {\n\t\t\t\tif (liquidCrafter > 1 && !isAdvancedSat) {\n\t\t\t\t\tfor (int i = 1; i < liquidCrafter; i++) {\n\t\t\t\t\t\tint xLine = left + 2 + (i * 40);\n\t\t\t\t\t\tGui.drawRect(xLine, top + 3, xLine + 1, top + 138, 0xff8B8B8B);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!isAdvancedSat) {\n\t\t\t\t\tGui.drawRect(left + 3, top + 138, left + 2 + (liquidCrafter * 40), top + 139, 0xff8B8B8B);\n\t\t\t\t}\n\t\t\t\tif (!isAdvancedSat) {\n\t\t\t\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\t\t\t\tint liquidLeft = left + i * 40;\n\t\t\t\t\t\trenderFluidText(liquidLeft, top, i);\n\t\t\t\t\t}\n\t\t\t\t\tif (craftingModule.clientSideSatelliteNames.liquidSatelliteName.isEmpty()) {\n\t\t\t\t\t\tGui.drawRect(left + 3, top + 3, left + 3 + (liquidCrafter * 40), top + 138, 0xAA8B8B8B);\n\t\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Off\"), left + (liquidCrafter * 40) / 2 - 5, top + 145, 0x404040);\n\t\t\t\t\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\t\t\t\t\tfor (int j = 0; j < 8; j++) {\n\t\t\t\t\t\t\t\tliquidGuiParts[i][j].enabled = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmc.fontRenderer.drawString(craftingModule.clientSideSatelliteNames.liquidSatelliteName, left + (liquidCrafter * 40) / 2 + 3 - (fontRenderer.getStringWidth(craftingModule.clientSideSatelliteNames.liquidSatelliteName) / 2), top + 145, 0x404040);\n\t\t\t\t\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\t\t\t\t\tfor (int j = 0; j < 8; j++) {\n\t\t\t\t\t\t\t\tliquidGuiParts[i][j].enabled = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\trenderFluidText(left, top, id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate void renderFluidText(int left, int top, int i) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, left + 12, top + 19);\n\t\t\tfinal String liquidAmount = liquidAmountsOverlay.read(intList -> intList.get(i).toString());\n\t\t\tmc.fontRenderer.drawString(liquidAmount, left + 22 - (fontRenderer.getStringWidth(liquidAmount) / 2), top + 40, 0x404040);\n\t\t\tmc.fontRenderer.drawString(\"1\", left + 19, top + 53, 0x404040);\n\t\t\tmc.fontRenderer.drawString(\"10\", left + 16, top + 73, 0x404040);\n\t\t\tmc.fontRenderer.drawString(\"100\", left + 13, top + 93, 0x404040);\n\t\t\tmc.fontRenderer.drawString(\"1000\", left + 10, top + 113, 0x404040);\n\t\t\tif (isAdvancedSat) {\n\t\t\t\tif (craftingModule.clientSideSatelliteNames.liquidSatelliteNameArray[i].isEmpty()) {\n\t\t\t\t\tGui.drawRect(left + 3, top + 3, left + 42, top + 138, 0xAA8B8B8B);\n\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Off\"), left + 15, top + 146, 0x404040);\n\t\t\t\t\tfor (int j = 0; j < 8; j++) {\n\t\t\t\t\t\tliquidGuiParts[i][j].enabled = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tString name = craftingModule.clientSideSatelliteNames.liquidSatelliteNameArray[i];\n\t\t\t\t\tname = TextUtil.getTrimmedString(name, 40, mc.fontRenderer, \"...\");\n\t\t\t\t\tmc.fontRenderer.drawString(name, left + 22 - (fontRenderer.getStringWidth(name) / 2), top + 146, 0x404040);\n\t\t\t\t\tfor (int j = 0; j < 8; j++) {\n\t\t\t\t\t\tliquidGuiParts[i][j].enabled = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tGui.drawRect(left + 3, top + 138, left + 42, top + 139, 0xff8B8B8B);\n\t\t\t}\n\t\t\tif (((IItemIdentifierInventory) craftingModule.liquidInventory).getStackInSlot(i).isEmpty() && !((!isAdvancedSat && craftingModule.clientSideSatelliteNames.liquidSatelliteName.isEmpty()) || (isAdvancedSat && craftingModule.clientSideSatelliteNames.liquidSatelliteNameArray[i].isEmpty()))) {\n\t\t\t\tGui.drawRect(left + 3, top + 50, left + 42, top + 138, 0xAA8B8B8B);\n\t\t\t\tfor (int j = 0; j < 8; j++) {\n\t\t\t\t\tliquidGuiParts[i][j].enabled = false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean renderSelectSlot(int slotId) {\n\t\t\tif ((isAdvancedSat && craftingModule.clientSideSatelliteNames.liquidSatelliteNameArray[id].isEmpty()) || (!isAdvancedSat && craftingModule.clientSideSatelliteNames.liquidSatelliteName.isEmpty())) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn super.renderSelectSlot(slotId);\n\t\t}\n\t}\n\n\tprivate final class ByproductExtension extends GuiExtension {\n\n\t\t@Override\n\t\tpublic int getFinalWidth() {\n\t\t\treturn 40;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getFinalHeight() {\n\t\t\treturn 55;\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForeground(int left, int top) {\n\t\t\tif (!isFullyExtended()) {\n\t\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\t\tItemStack stack = new ItemStack(ItemUpgrade.getAndCheckUpgrade(LPItems.upgrades.get(CraftingByproductUpgrade.getName())));\n\t\t\t\titemRender.renderItemAndEffectIntoGUI(stack, left + 5, top + 5);\n\t\t\t\titemRender.renderItemOverlayIntoGUI(fontRenderer, stack, left + 5, top + 5, \"\");\n\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t\titemRender.zLevel = 0.0F;\n\t\t\t} else {\n\t\t\t\tGuiGraphics.drawBigSlotBackground(mc, left + 9, top + 20);\n\t\t\t\tfontRenderer.drawString(TextUtil.translate(GuiCraftingPipe.PREFIX + \"Extra\"), left + 9, top + 8, 0x404040);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate final class CleanupExtension extends GuiExtension {\n\n\t\t@Override\n\t\tpublic int getFinalWidth() {\n\t\t\treturn 66;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getFinalHeight() {\n\t\t\treturn cleanupSize * 18 + 16 + 30;\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForeground(int left, int top) {\n\t\t\tif (!isFullyExtended()) {\n\t\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\t\tItemStack stack = new ItemStack(ItemUpgrade.getAndCheckUpgrade(LPItems.upgrades.get(CraftingCleanupUpgrade.getName())));\n\t\t\t\titemRender.renderItemAndEffectIntoGUI(stack, left + 5, top + 5);\n\t\t\t\titemRender.renderItemOverlayIntoGUI(fontRenderer, stack, left + 5, top + 5, \"\");\n\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t\titemRender.zLevel = 0.0F;\n\t\t\t} else {\n\t\t\t\tfor (int y = 0; y < cleanupSize; y++) {\n\t\t\t\t\tfor (int x = 0; x < 3; x++) {\n\t\t\t\t\t\tGuiGraphics.drawSlotBackground(mc, left + 8 + x * 18, top + 8 + y * 18);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiFirewall.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.pipes.PipeItemsFirewall;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.GuiStringHandlerButton;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiFirewall extends LogisticsBaseGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.firewall.\";\n\n\tprivate PipeItemsFirewall pipe;\n\n\tpublic GuiFirewall(PipeItemsFirewall pipe, EntityPlayer player) {\n\t\tsuper(230, 260, 0, 0);\n\t\tthis.pipe = pipe;\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, pipe.inv);\n\t\tdummy.addNormalSlotsForPlayerInventory(33, 175);\n\t\tfor (int x = 0; x < 6; x++) {\n\t\t\tfor (int y = 0; y < 6; y++) {\n\t\t\t\tdummy.addDummySlot(x * 6 + y, x * 18 + 17, y * 18 + 41);\n\t\t\t}\n\t\t}\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tfinal String blocked = TextUtil.translate(GuiFirewall.PREFIX + \"Blocked\");\n\t\tfinal String allowed = TextUtil.translate(GuiFirewall.PREFIX + \"Allowed\");\n\t\tbuttonList.add(new GuiStringHandlerButton(0, width / 2 + 23, height / 2 + 27 - 139, 60, 20, () -> pipe.isBlocking() ? blocked : allowed));\n\t\tbuttonList.add(new GuiStringHandlerButton(1, width / 2 + 23, height / 2 + 60 - 139, 60, 20, () -> pipe.isBlockProvider() ? blocked : allowed));\n\t\tbuttonList.add(new GuiStringHandlerButton(2, width / 2 + 23, height / 2 + 93 - 139, 60, 20, () -> pipe.isBlockCrafter() ? blocked : allowed));\n\t\tbuttonList.add(new GuiStringHandlerButton(3, width / 2 + 23, height / 2 + 126 - 139, 60, 20, () -> pipe.isBlockSorting() ? blocked : allowed));\n\t\tbuttonList.add(new GuiStringHandlerButton(4, width / 2 + 23, height / 2 + 160 - 139, 60, 20, () -> pipe.isBlockPower() ? blocked : allowed));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tswitch (button.id) {\n\t\t\tcase 0:\n\t\t\t\tpipe.setBlocking(!pipe.isBlocking());\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tpipe.setBlockProvider(!pipe.isBlockProvider());\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tpipe.setBlockCrafter(!pipe.isBlockCrafter());\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tpipe.setBlockSorting(!pipe.isBlockSorting());\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tpipe.setBlockPower(!pipe.isBlockPower());\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 33, guiTop + 175);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Firewall\"), guiLeft + 45, guiTop + 8, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Filter\") + \":\", guiLeft + 14, guiTop + 28, 0x404040);\n\t\tfor (int x = 0; x < 6; x++) {\n\t\t\tfor (int y = 0; y < 6; y++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + x * 18 + 16, guiTop + y * 18 + 40);\n\t\t\t}\n\t\t}\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Filtereditemsare\") + \":\", guiLeft + 125, guiTop + 8, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Providing\") + \":\", guiLeft + 144, guiTop + 41, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Crafting\") + \":\", guiLeft + 146, guiTop + 74, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Sorting\") + \":\", guiLeft + 150, guiTop + 107, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFirewall.PREFIX + \"Powerflow\") + \":\", guiLeft + 142, guiTop + 141, 0x404040);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiFluidBasic.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\n\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiFluidBasic extends LogisticsBaseGuiScreen {\n\n\tpublic GuiFluidBasic(EntityPlayer player, IInventory inventory) {\n\t\tsuper(180, 130, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, inventory);\n\t\tdummy.addFluidSlot(0, inventory, 28, 13);\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 45);\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 45);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 27, guiTop + 12);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tif (inventorySlots.getSlot(0).getStack() == null) {\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(\"gui.fluidbasic.Empty\"), 50, 18, 0x404040);\n\t\t} else {\n\t\t\tmc.fontRenderer.drawString(ItemIdentifier.get(inventorySlots.getSlot(0).getStack()).getFriendlyName(), 50, 18, 0x404040);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiFluidSupplierMk2Pipe.java",
    "content": "/**\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.FluidSupplierAmount;\nimport logisticspipes.network.packets.pipe.FluidSupplierMinMode;\nimport logisticspipes.network.packets.pipe.FluidSupplierMode;\nimport logisticspipes.pipes.PipeFluidSupplierMk2;\nimport logisticspipes.pipes.PipeFluidSupplierMk2.MinMode;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiFluidSupplierMk2Pipe extends LogisticsBaseGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.fluidsuppliermk2.\";\n\n\tprivate PipeFluidSupplierMk2 logic;\n\n\tpublic GuiFluidSupplierMk2Pipe(IInventory playerInventory, IInventory dummyInventory, PipeFluidSupplierMk2 logic) {\n\t\tsuper(null);\n\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, dummyInventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(13, 92);\n\n\t\tdummy.addFluidSlot(0, dummyInventory, 60, 18);\n\n\t\tinventorySlots = dummy;\n\n\t\tthis.logic = logic;\n\t\txSize = 184;\n\t\tySize = 176;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FluidSupplierAmount.class).setInteger(0).setPosX(this.logic.getX()).setPosY(this.logic.getY()).setPosZ(this.logic.getZ()));\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"TargetInv\"), xSize / 2 - mc.fontRenderer.getStringWidth(TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"TargetInv\")) / 2, 6, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"Inventory\"), 15, ySize - 95, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"Fluid\") + \":\", 25, 22, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"Partial\") + \":\", xSize - 176, ySize - 109, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"minMode\") + \":\", xSize - 108, ySize - 109, 0x404040);\n\t\tmc.fontRenderer.drawString(Integer.toString(logic.getAmount()), xSize / 2, 22, 0x404040);\n\t\tmc.fontRenderer.drawString(\"+\", 32, 39, 0x404040);\n\t\tmc.fontRenderer.drawString(\"-\", 32, 50, 0x404040);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, guiLeft + xSize, guiTop + ySize, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 13, guiTop + 92);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 59, guiTop + 17);\n\t\t//GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t//mc.renderEngine.func_110577_a(\"/logisticspipes/gui/supplier.png\");\n\t\t//int j = guiLeft;\n\t\t//int k = guiTop;\n\t\t//drawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, width / 2 - 48, guiTop + ySize - 115, 30, 20, logic.isRequestingPartials() ? TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"Yes\") : TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"No\")));\n\t\tbuttonList.add(new GuiButton(1, width / 2 + 30, guiTop + ySize - 115, 55, 20, TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + logic.getMinMode().name())));\n\t\tbuttonList.add(new SmallGuiButton(10, guiLeft + 40, guiTop + 37, 10, 10, \"1\"));\n\t\tbuttonList.add(new SmallGuiButton(11, guiLeft + 40, guiTop + 48, 10, 10, \"1\"));\n\t\tbuttonList.add(new SmallGuiButton(20, guiLeft + 51, guiTop + 37, 20, 10, \"10\"));\n\t\tbuttonList.add(new SmallGuiButton(21, guiLeft + 51, guiTop + 48, 20, 10, \"10\"));\n\t\tbuttonList.add(new SmallGuiButton(30, guiLeft + 72, guiTop + 37, 30, 10, \"100\"));\n\t\tbuttonList.add(new SmallGuiButton(31, guiLeft + 72, guiTop + 48, 30, 10, \"100\"));\n\t\tbuttonList.add(new SmallGuiButton(40, guiLeft + 103, guiTop + 37, 40, 10, \"1000\"));\n\t\tbuttonList.add(new SmallGuiButton(41, guiLeft + 103, guiTop + 48, 40, 10, \"1000\"));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) {\n\t\t\tlogic.setRequestingPartials(!logic.isRequestingPartials());\n\t\t\tbuttonList.get(0).displayString = logic.isRequestingPartials() ? TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"Yes\") : TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + \"No\");\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FluidSupplierMode.class).setInteger((logic.isRequestingPartials() ? 1 : 0)).setPosX(logic.getX()).setPosY(logic.getY()).setPosZ(logic.getZ()));\n\t\t} else if (guibutton.id == 1) {\n\t\t\tint index = logic.getMinMode().ordinal() + 1;\n\t\t\tif (index >= MinMode.values().length) {\n\t\t\t\tindex = 0;\n\t\t\t}\n\t\t\tlogic.setMinMode(MinMode.values()[index]);\n\t\t\tbuttonList.get(1).displayString = TextUtil.translate(GuiFluidSupplierMk2Pipe.PREFIX + logic.getMinMode().name());\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FluidSupplierMinMode.class).setInteger(logic.getMinMode().ordinal()).setPosX(logic.getX()).setPosY(logic.getY()).setPosZ(logic.getZ()));\n\t\t} else if ((guibutton.id % 10 == 0 || guibutton.id % 10 == 1) && guibutton.id / 10 < 5 && guibutton.id / 10 > 0) {\n\t\t\tint change = 1;\n\t\t\tif (guibutton.id % 10 == 1) {\n\t\t\t\tchange = -1;\n\t\t\t}\n\t\t\tchange *= Math.pow(10, guibutton.id / 10 - 1);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FluidSupplierAmount.class).setInteger(change).setPosX(logic.getX()).setPosY(logic.getY()).setPosZ(logic.getZ()));\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiFluidSupplierPipe.java",
    "content": "/**\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.FluidSupplierMode;\nimport logisticspipes.pipes.PipeItemsFluidSupplier;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiFluidSupplierPipe extends LogisticsBaseGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.fluidsupplier.\";\n\n\tprivate PipeItemsFluidSupplier logic;\n\n\tpublic GuiFluidSupplierPipe(IInventory playerInventory, IInventory dummyInventory, PipeItemsFluidSupplier logic) {\n\t\tsuper(null);\n\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, dummyInventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\n\t\tint xOffset = 72;\n\t\tint yOffset = 18;\n\n\t\tfor (int row = 0; row < 3; row++) {\n\t\t\tfor (int column = 0; column < 3; column++) {\n\t\t\t\tdummy.addDummySlot(column + row * 3, xOffset + column * 18, yOffset + row * 18);\n\t\t\t}\n\t\t}\n\t\tinventorySlots = dummy;\n\n\t\tthis.logic = logic;\n\t\txSize = 194;\n\t\tySize = 186;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"TargetInv\"), xSize / 2 - mc.fontRenderer.getStringWidth(TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"TargetInv\")) / 2, 6, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"Inventory\"), 18, ySize - 102, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"Partialrequests\") + \":\", xSize - 140, ySize - 112, 0x404040);\n\t}\n\n\tprotected static final ResourceLocation SUPPLIER = new ResourceLocation(\"logisticspipes\", \"textures/gui/supplier.png\");\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiFluidSupplierPipe.SUPPLIER);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, width / 2 + 45, height / 2 - 25, 30, 20, logic.isRequestingPartials() ? TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"Yes\") : TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"No\")));\n\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) {\n\t\t\tlogic.setRequestingPartials(!logic.isRequestingPartials());\n\t\t\tbuttonList.get(0).displayString = logic.isRequestingPartials() ? TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"Yes\") : TextUtil.translate(GuiFluidSupplierPipe.PREFIX + \"No\");\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FluidSupplierMode.class).setInteger((logic.isRequestingPartials() ? 1 : 0)).setPosX(logic.getX()).setPosY(logic.getY()).setPosZ(logic.getZ()));\n\t\t}\n\t\tsuper.actionPerformed(guibutton);\n\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiFluidTerminus.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.network.packets.pipe.PipePropertiesUpdate;\nimport logisticspipes.pipes.PipeFluidTerminus;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay;\n\npublic class GuiFluidTerminus extends LogisticsBaseGuiScreen {\n\n\tprivate final PropertyLayer propertyLayer;\n\tprivate final BlockPos pipePosition;\n\tprivate final PropertyOverlay<ItemIdentifierInventory, ItemIdentifierInventoryProperty> sinkInventoryOverlay;\n\n\tpublic GuiFluidTerminus(EntityPlayer player, PipeFluidTerminus pipe) {\n\t\tsuper(null);\n\n\t\tpipePosition = pipe.getPos();\n\t\tpropertyLayer = new PropertyLayer(pipe.getProperties());\n\t\tsinkInventoryOverlay = propertyLayer.overlay(pipe.getSinkInv());\n\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, propertyLayer.writeProp(pipe.getSinkInv()));\n\t\t// Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < pipe.getSinkInv().getSizeInventory(); ++pipeSlot) {\n\t\t\tdummy.addFluidSlot(pipeSlot, 10 + pipeSlot * 18, 19);\n\t\t}\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 45);\n\n\t\tinventorySlots = dummy;\n\t\txSize = 180;\n\t\tySize = 130;\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t\tpropertyLayer.unregister();\n\t\tif (this.mc.player != null && !propertyLayer.getProperties().isEmpty()) {\n\t\t\t// send update to server, when there are changed properties\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPipePropertiesUpdate.fromPropertyHolder(propertyLayer).setBlockPos(pipePosition));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 45);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 9 + i * 18, guiTop + 18);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tmc.fontRenderer.drawString(sinkInventoryOverlay.read(IItemIdentifierInventory::getName), 10, 8, 0x404040);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiFreqCardContent.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class GuiFreqCardContent extends LogisticsBaseGuiScreen {\n\n\tpublic GuiFreqCardContent(EntityPlayer player, IInventory card) {\n\t\tsuper(180, 130, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, card);\n\t\tdummy.addRestrictedSlot(0, card, 82, 15, itemStack ->\n\t\t\t\t!itemStack.isEmpty() && itemStack.getItem() == LPItems.itemCard && itemStack.getItemDamage() == LogisticsItemCard.FREQ_CARD);\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 45);\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 45);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 81, guiTop + 14);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiInvSysConnector.java",
    "content": "package logisticspipes.gui;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IGUIChannelInformationReceiver;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.InvSysConContentRequest;\nimport logisticspipes.network.packets.pipe.InvSysConOpenSelectChannelPopupPacket;\nimport logisticspipes.network.packets.pipe.InvSysConResistance;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiInvSysConnector extends LogisticsBaseGuiScreen implements IGUIChannelInformationReceiver {\n\n\tprivate static final String PREFIX = \"gui.invsyscon.\";\n\n\tprivate int page = 0;\n\tprivate final List<ItemIdentifierStack> _allItems = new ArrayList<>();\n\tprivate final PipeItemsInvSysConnector pipe;\n\tprivate InputBar resistanceCountBar;\n\n\tprivate ChannelInformation connectedChannel = null;\n\n\tpublic GuiInvSysConnector(EntityPlayer player, PipeItemsInvSysConnector pipe) {\n\t\tsuper(180, 220, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, null);\n\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 135);\n\n\t\tinventorySlots = dummy;\n\t\tthis.pipe = pipe;\n\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, guiLeft + 120, guiTop + 67, 10, 10, \"<\"));\n\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 160, guiTop + 67, 10, 10, \">\"));\n\t\tbuttonList.add(new SmallGuiButton(2, guiLeft + 68, guiTop + 67, 46, 10, TextUtil.translate(GuiInvSysConnector.PREFIX + \"Refresh\")));\n\t\tbuttonList.add(new SmallGuiButton(3, guiLeft + 80, guiTop + 55, 10, 10, \"<\"));\n\t\tbuttonList.add(new SmallGuiButton(4, guiLeft + 120, guiTop + 55, 10, 10, \">\"));\n\t\tbuttonList.add(new SmallGuiButton(5, guiLeft + 140, guiTop + 55, 30, 10, TextUtil.translate(GuiInvSysConnector.PREFIX + \"Save\")));\n\t\tbuttonList.add(new SmallGuiButton(6, guiLeft + 130, guiTop + 20, 40, 10, TextUtil.translate(GuiInvSysConnector.PREFIX + \"Change\")));\n\n\t\tif (this.resistanceCountBar == null) {\n\t\t\tthis.resistanceCountBar = new InputBar(this.fontRenderer, this, guiLeft + 90, guiTop + 55, 30, 12, false, true, InputBar.Align.CENTER);\n\t\t\tthis.resistanceCountBar.minNumber = 0;\n\t\t\tthis.resistanceCountBar.setInteger(pipe.resistance);\n\t\t}\n\t\tthis.resistanceCountBar.reposition(guiLeft + 90, guiTop + 55, 30, 12);\n\n\t\trefreshPacket();\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 135);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiInvSysConnector.PREFIX + \"InventorySystemConnector\"), guiLeft + 5, guiTop + 6, 0x404040);\n\t\tdrawRect(guiLeft + 9, guiTop + 78, guiLeft + 170, guiTop + 132, Color.GREY);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiInvSysConnector.PREFIX + \"ConnectionInformation\") + \":\", guiLeft + 10, guiTop + 21, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.getTrimmedString(TextUtil.translate(GuiInvSysConnector.PREFIX + \"Channel\") + \": \" + (connectedChannel != null ? connectedChannel.getName() : \"UNDEFINED\"), 150, this.fontRenderer, \"...\"), guiLeft + 15, guiTop + 38, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiInvSysConnector.PREFIX + \"Waitingfor\") + \":\", guiLeft + 10, guiTop + 68, 0x404040);\n\t\tmc.fontRenderer.drawString((page + 1) + \"/\" + maxPage(), guiLeft + 136, guiTop + 69, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiInvSysConnector.PREFIX + \"Resistance\") + \":\", guiLeft + 10, guiTop + 55, 0x404040);\n\t\tresistanceCountBar.drawTextBox();\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(_allItems, null, page, 9, 79, 9, 27, 18, 18, 100.0F, DisplayAmount.ALWAYS);\n\n\t\tint ppi = 0;\n\t\tint column = 0;\n\t\tint row = 0;\n\t\tfor (ItemIdentifierStack itemStack : _allItems) {\n\t\t\tppi++;\n\n\t\t\tif (ppi <= 27 * page) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ppi > 27 * (page + 1)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack st = itemStack.unsafeMakeNormalStack();\n\t\t\tint x = 9 + 18 * column + guiLeft;\n\t\t\tint y = 79 + 18 * row + guiTop;\n\n\t\t\tGL11.glDisable(2896 /*GL_LIGHTING*/);\n\n\t\t\tint mouseX = Mouse.getX() * width / mc.displayWidth;\n\t\t\tint mouseY = height - Mouse.getY() * height / mc.displayHeight - 1;\n\n\t\t\tif (x < mouseX && mouseX < x + 18 && y < mouseY && mouseY < y + 18) {\n\t\t\t\tGuiGraphics.displayItemToolTip(new Object[] { mouseX, mouseY, st, true }, zLevel, guiLeft, guiTop, false);\n\t\t\t}\n\n\t\t\tcolumn++;\n\t\t\tif (column >= 9) {\n\t\t\t\trow++;\n\t\t\t\tcolumn = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void refreshPacket() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(InvSysConContentRequest.class).setPosX(pipe.getX()).setPosY(pipe.getY()).setPosZ(pipe.getZ()));\n\t}\n\n\tprivate void pageDown() {\n\t\tif (page <= 0) {\n\t\t\tpage = maxPage() - 1;\n\t\t} else {\n\t\t\tpage--;\n\t\t}\n\t}\n\n\tprivate void pageUp() {\n\t\tif (page >= maxPage() - 1) {\n\t\t\tpage = 0;\n\t\t} else {\n\t\t\tpage++;\n\t\t}\n\t}\n\n\tprivate int maxPage() {\n\t\tint i = (int) (Math.floor(((float) _allItems.size()) / 27) + (((float) _allItems.size()) % 27 == 0 ? 0 : 1));\n\t\tif (i <= 0) {\n\t\t\ti = 1;\n\t\t}\n\t\treturn i;\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) throws IOException {\n\t\tsuper.actionPerformed(button);\n\t\tif (button.id == 0) {\n\t\t\tpageDown();\n\t\t} else if (button.id == 1) {\n\t\t\tpageUp();\n\t\t} else if (button.id == 2) {\n\t\t\trefreshPacket();\n\t\t} else if (button.id == 3) {\n\t\t\tresistanceCountBar.setInteger(resistanceCountBar.getInteger() - (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 10 : 1));\n\t\t} else if (button.id == 4) {\n\t\t\tresistanceCountBar.setInteger(resistanceCountBar.getInteger() + 1);\n\t\t} else if (button.id == 5) {\n\t\t\tpipe.resistance = resistanceCountBar.getInteger();\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(InvSysConResistance.class).setInteger(pipe.resistance).setPosX(pipe.getX()).setPosY(pipe.getY()).setPosZ(pipe.getZ()));\n\t\t} else if (button.id == 6) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(InvSysConOpenSelectChannelPopupPacket.class).setTilePos(pipe.container));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int x, int y, int k) throws IOException {\n\t\tif (!resistanceCountBar.handleClick(x, y, k)) {\n\t\t\tsuper.mouseClicked(x, y, k);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void keyTyped(char c, int i) throws IOException {\n\t\tif (!resistanceCountBar.handleKey(c, i)) {\n\t\t\tsuper.keyTyped(c, i);\n\t\t}\n\t}\n\n\tpublic void handleContentAnswer(Collection<ItemIdentifierStack> allItems) {\n\t\t_allItems.clear();\n\t\t_allItems.addAll(allItems);\n\t}\n\n\tpublic void handleResistanceAnswer(int resistance) {\n\t\tresistanceCountBar.setInteger(resistance);\n\t}\n\n\t@Override\n\tpublic void handleChannelInformation(ChannelInformation channel, boolean flag) {\n\t\tif (this.getSubGui() instanceof IGUIChannelInformationReceiver) {\n\t\t\t((IGUIChannelInformationReceiver) this.getSubGui()).handleChannelInformation(channel, flag);\n\t\t}\n\t\tif (flag) {\n\t\t\tthis.connectedChannel = channel;\n\t\t} else if (this.connectedChannel != null && this.connectedChannel.getChannelIdentifier().equals(channel.getChannelIdentifier())) {\n\t\t\tthis.connectedChannel = channel;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiLogisticsCraftingTable.java",
    "content": "package logisticspipes.gui;\n\nimport java.util.Arrays;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.CraftingCycleRecipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class GuiLogisticsCraftingTable extends LogisticsBaseGuiScreen {\n\n\tpublic LogisticsCraftingTableTileEntity _crafter;\n\n\tprivate int fuzzyPanelSelection = -1;\n\tprivate int fuzzyPanelHover = -1;\n\tprivate int fuzzyPanelHoverTime = 0;\n\n\tprivate GuiButton[] cycleButtons = new GuiButton[2];\n\n\tpublic GuiLogisticsCraftingTable(EntityPlayer player, LogisticsCraftingTableTileEntity crafter) {\n\t\tsuper(176, 218, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, crafter.matrix);\n\t\tdummy.guiHolderForJEI = this;\n\n\t\tfor (int x = 0; x < 3; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tif (crafter.isFuzzy()) {\n\t\t\t\t\tdummy.addFuzzyDummySlot(y * 3 + x, 35 + x * 18, 10 + y * 18, crafter.inputFuzzy(y * 3 + x));\n\t\t\t\t} else {\n\t\t\t\t\tdummy.addDummySlot(y * 3 + x, 35 + x * 18, 10 + y * 18);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (crafter.isFuzzy()) {\n\t\t\tdummy.addFuzzyUnmodifiableSlot(0, crafter.resultInv, 125, 28, crafter.outputFuzzy());\n\t\t} else {\n\t\t\tdummy.addUnmodifiableSlot(0, crafter.resultInv, 125, 28);\n\t\t}\n\t\tfor (int y = 0; y < 2; y++) {\n\t\t\tfor (int x = 0; x < 9; x++) {\n\t\t\t\tdummy.addNormalSlot(y * 9 + x, crafter.inv, 8 + x * 18, 80 + y * 18);\n\t\t\t}\n\t\t}\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 135);\n\t\tinventorySlots = dummy;\n\t\t_crafter = crafter;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\t(cycleButtons[0] = addButton(new SmallGuiButton(0, guiLeft + 144, guiTop + 25, 15, 10, \"/\\\\\"))).visible = false;\n\t\t(cycleButtons[1] = addButton(new SmallGuiButton(1, guiLeft + 144, guiTop + 37, 15, 10, \"\\\\/\"))).visible = false;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float fA, int iA, int jA) {\n\t\tfor (GuiButton cycleButton : cycleButtons) {\n\t\t\tcycleButton.visible = _crafter.targetType != null;\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tfor (int x = 0; x < 3; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 34 + x * 18, guiTop + 9 + y * 18);\n\t\t\t}\n\t\t}\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 124, guiTop + 27);\n\t\tfor (int x = 0; x < 9; x++) {\n\t\t\tfor (int y = 0; y < 2; y++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 7 + x * 18, guiTop + 79 + y * 18);\n\t\t\t}\n\t\t}\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 8, guiTop + 135);\n\n\t\tItemIdentifierStack[] items = new ItemIdentifierStack[9];\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tif (_crafter.matrix.getIDStackInSlot(i) != null) {\n\t\t\t\titems[i] = _crafter.matrix.getIDStackInSlot(i);\n\t\t\t}\n\t\t}\n\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(Arrays.asList(items), null, 0, guiLeft + 8, guiTop + 79, 9, 9, 18, 18, 0.0F, DisplayAmount.NEVER);\n\n\t\tGlStateManager.translate(0, 0, 200F);\n\t\tfor (int a = 0; a < 9; a++) {\n\t\t\tGui.drawRect(guiLeft + 8 + (a * 18), guiTop + 80, guiLeft + 24 + (a * 18), guiTop + 96, 0xc08b8b8b);\n\t\t}\n\t\tGlStateManager.translate(0, 0, -200F);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tif (button.id == 0 || button.id == 1) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(CraftingCycleRecipe.class).setDown(button.id == 1).setTilePos(_crafter));\n\t\t}\n\t}\n\n\tprivate boolean isMouseInFuzzyPanel(int mx, int my) {\n\t\tif (fuzzyPanelSelection == -1) {\n\t\t\treturn false;\n\t\t}\n\t\tint posX = -60;\n\t\tint posY = 0;\n\t\treturn mx >= posX && my >= posY && mx <= posX + 60 && my <= posY + 52;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiLogisticsSettings.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.PlayerConfigToServerPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.LogisticsBaseTabGuiScreen;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiLogisticsSettings extends LogisticsBaseTabGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.settings.\";\n\n\tpublic GuiLogisticsSettings(final EntityPlayer player) {\n\t\tsuper(180, 220);\n\t\tDummyContainer dummy = new DummyContainer(player, null);\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 135);\n\n\t\taddTab(new PipeRenderSettings());\n\n\t\tinventorySlots = dummy;\n\t}\n\n\tprivate class PipeRenderSettings extends TabSubGui {\n\n\t\tprivate InputBar renderDistance;\n\t\tprivate InputBar contentRenderDistance;\n\t\tprivate GuiCheckBox useNewRendererButton;\n\t\tprivate GuiCheckBox useFallbackRendererButton;\n\n\t\tprivate PipeRenderSettings() {}\n\n\t\t@Override\n\t\tpublic void initTab() {\n\t\t\tKeyboard.enableRepeatEvents(true);\n\n\t\t\tClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\t\t\tif (renderDistance == null) {\n\t\t\t\trenderDistance = new InputBar(fontRenderer, getBaseScreen(), 15, 75, 30, 15, false, true, InputBar.Align.RIGHT);\n\t\t\t\trenderDistance.setInteger(config.getRenderPipeDistance());\n\t\t\t}\n\t\t\trenderDistance.reposition(15, 80, 30, 15);\n\t\t\tif (contentRenderDistance == null) {\n\t\t\t\tcontentRenderDistance = new InputBar(fontRenderer, getBaseScreen(), 15, 105, 30, 15, false, true, InputBar.Align.RIGHT);\n\t\t\t\tcontentRenderDistance.setInteger(config.getRenderPipeContentDistance());\n\t\t\t}\n\t\t\tcontentRenderDistance.reposition(15, 110, 30, 15);\n\t\t\t//useNewRendererButton = (GuiCheckBox) addButton(new GuiCheckBox(0, guiLeft + 15, guiTop + 30, 16, 16, config.isUseNewRenderer()));\n\t\t\t//useFallbackRendererButton = (GuiCheckBox) addButton(new GuiCheckBox(0, guiLeft + 15, guiTop + 50, 16, 16, config.isUseFallbackRenderer()));\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderIcon(int x, int y) {\n\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\tItemStack stack = new ItemStack(LPItems.pipeBasic, 1);\n\t\t\titemRender.renderItemAndEffectIntoGUI(stack, x, y);\n\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\titemRender.zLevel = 0.0F;\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderBackgroundContent() {}\n\n\t\t@Override\n\t\tpublic void buttonClicked(GuiButton button) {\n\t\t\tif (button == useNewRendererButton) {\n\t\t\t\tuseNewRendererButton.change();\n\t\t\t}\n\t\t\tif (button == useFallbackRendererButton) {\n\t\t\t\tuseFallbackRendererButton.change();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForegroundContent() {\n\t\t\trenderDistance.drawTextBox();\n\t\t\tcontentRenderDistance.drawTextBox();\n\t\t\t//fontRenderer.drawString(StringUtil.translate(PREFIX + \"pipenewrenderer\"), 38, 34, 0x404040);\n\t\t\t//fontRenderer.drawString(StringUtil.translate(PREFIX + \"pipefallbackrenderer\"), 38, 54, 0x404040);\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"piperenderdistance\"), 10, 70, 0x404040);\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"pipecontentrenderdistance\"), 10, 100, 0x404040);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean handleClick(int x, int y, int type) {\n\t\t\tboolean val1 = renderDistance.handleClick(x - guiLeft, y - guiTop, type);\n\t\t\tboolean val2 = contentRenderDistance.handleClick(x - guiLeft, y - guiTop, type);\n\t\t\treturn val1 || val2;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean handleKey(int code, char c) {\n\t\t\treturn renderDistance.handleKey(c, code) || contentRenderDistance.handleKey(c, code);\n\t\t}\n\n\t\t@Override\n\t\tpublic void guiClose() {\n\t\t\tClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\t\t\ttry {\n\t\t\t\tconfig.setRenderPipeDistance(renderDistance.getInteger());\n\t\t\t\tconfig.setRenderPipeContentDistance(contentRenderDistance.getInteger());\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\t//config.setUseNewRenderer(useNewRendererButton.getState());\n\t\t\t//config.setUseFallbackRenderer(useFallbackRendererButton.getState());\n\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPacketHandler.getPacket(PlayerConfigToServerPacket.class).setConfig(config));\n\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiPipeController.java",
    "content": "package logisticspipes.gui;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.LogicControllerPacket;\nimport logisticspipes.network.packets.gui.OpenUpgradePacket;\nimport logisticspipes.network.packets.pipe.PipeManagerWatchingPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\nimport logisticspipes.pipes.upgrades.SneakyUpgradeConfig;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.LogisticsBaseTabGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.string.ChatColor;\nimport logisticspipes.utils.string.StringUtils;\nimport network.rs485.logisticspipes.util.TextUtil;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class GuiPipeController extends LogisticsBaseTabGuiScreen {\n\n\tprivate final String PREFIX = \"gui.pipecontroller.\";\n\n\tprivate final CoreRoutedPipe pipe;\n\n\tpublic GuiPipeController(final EntityPlayer player, final CoreRoutedPipe pipe) {\n\t\tsuper(180, 220);\n\t\tthis.pipe = pipe;\n\t\tDummyContainer dummy = new DummyContainer(player, null, pipe.getOriginalUpgradeManager().getGuiController());\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 135);\n\n\t\t//Order is important here: (Slot Server/Client sync)\n\t\tUpgrades upgrades = new Upgrades(dummy);\n\t\tSecurity security = new Security(dummy);\n\t\tStatistics statistics = new Statistics();\n\t\t//Logic logic = new Logic();\n\t\taddHiddenSlot(dummy.addRestrictedSlot(0, pipe.container.logicController.diskInv, 14, 36, LPItems.disk)); //Keep it for now, but hidden. Maybe it will be used again later\n\t\tTasks tasks = new Tasks();\n\n\t\t//Here order doesn't matter/can be changed to reorganise tabs\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\taddTab(upgrades);\n\t\t\taddTab(security);\n\t\t\taddTab(statistics);\n\t\t\t//addTab(logic);\n\t\t\taddTab(tasks);\n\t\t} else {\n\t\t\taddTab(statistics);\n\t\t\taddTab(upgrades);\n\t\t\taddTab(security);\n\t\t\t//addTab(logic);\n\t\t\taddTab(tasks);\n\t\t}\n\n\t\tinventorySlots = dummy;\n\t}\n\n\tprivate class Upgrades extends TabSubGui {\n\n\t\tprivate final List<Slot> TAB_SLOTS_SNEAKY_INV = new ArrayList<>();\n\t\tprivate final Slot[] upgradeSlot = new Slot[18];\n\t\tprivate GuiButton[] upgradeConfig = new GuiButton[18];\n\n\t\tprivate Upgrades(DummyContainer dummy) {\n\t\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\t\taddSlot(upgradeSlot[pipeSlot] = dummy.addUpgradeSlot(pipeSlot, pipe.getOriginalUpgradeManager(), pipeSlot, 10 + pipeSlot * 18, 42, itemStack ->\n\t\t\t\t\t\t!itemStack.isEmpty() && itemStack.getItem() instanceof ItemUpgrade && ((ItemUpgrade) itemStack.getItem()).getUpgradeForItem(itemStack, null).isAllowedForPipe(pipe)));\n\t\t\t}\n\n\t\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\t\tTAB_SLOTS_SNEAKY_INV.add(addSlot(upgradeSlot[pipeSlot + 9] = dummy.addSneakyUpgradeSlot(pipeSlot, pipe.getOriginalUpgradeManager(), pipeSlot + 9, 10 + pipeSlot * 18, 88, itemStack -> {\n\t\t\t\t\tif (itemStack.isEmpty()) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tif (itemStack.getItem() instanceof ItemUpgrade) {\n\t\t\t\t\t\tIPipeUpgrade upgrade = ((ItemUpgrade) itemStack.getItem()).getUpgradeForItem(itemStack, null);\n\t\t\t\t\t\treturn upgrade instanceof SneakyUpgradeConfig && upgrade.isAllowedForPipe(pipe);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t})));\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void initTab() {\n\t\t\tint x = 0;\n\t\t\tint y = 0;\n\t\t\tfor (int i = 0; i < upgradeConfig.length; i++) {\n\t\t\t\tupgradeConfig[i] = addButton(new SmallGuiButton(20 + i, guiLeft + 13 + x, guiTop + 61 + y, 10, 10, \"!\"));\n\t\t\t\tupgradeConfig[i].visible = pipe.getOriginalUpgradeManager().hasGuiUpgrade(i);\n\t\t\t\tx += 18;\n\t\t\t\tif (x > 160 && y == 0) {\n\t\t\t\t\tx = 0;\n\t\t\t\t\ty = 46;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void checkButton(GuiButton button, boolean isTabActive) {\n\t\t\tsuper.checkButton(button, isTabActive);\n\t\t\tfor (int i = 0; i < upgradeConfig.length; i++) {\n\t\t\t\tupgradeConfig[i].visible &= pipe.getOriginalUpgradeManager().hasGuiUpgrade(i);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean showSlot(Slot slot) {\n\t\t\treturn pipe.getOriginalUpgradeManager().hasCombinedSneakyUpgrade() || !TAB_SLOTS_SNEAKY_INV.contains(slot);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderIcon(int x, int y) {\n\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\tItemStack stack = new ItemStack(ItemUpgrade.getAndCheckUpgrade(LPItems.upgrades.get(SneakyUpgradeConfig.getName())));\n\t\t\titemRender.renderItemAndEffectIntoGUI(stack, x, y);\n\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\titemRender.zLevel = 0.0F;\n\t\t}\n\n\t\t@Override\n\t\tpublic void buttonClicked(GuiButton button) {\n\t\t\tfor (int i = 0; i < upgradeConfig.length; i++) {\n\t\t\t\tif (upgradeConfig[i] == button) {\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OpenUpgradePacket.class).setSlot(upgradeSlot[i]));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderBackgroundContent() {\n\t\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 9 + pipeSlot * 18, guiTop + 41);\n\t\t\t}\n\t\t\tif (pipe.getOriginalUpgradeManager().hasCombinedSneakyUpgrade()) {\n\t\t\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 9 + pipeSlot * 18, guiTop + 87);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForegroundContent() {\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"upgrade\"), 10, 28, Color.getValue(Color.DARKER_GREY), false);\n\t\t\tif (pipe.getOriginalUpgradeManager().hasCombinedSneakyUpgrade()) {\n\t\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"sneakyUpgrades\"), 10, 74, Color.getValue(Color.DARKER_GREY), false);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate class Security extends TabSubGui {\n\n\t\tpublic Security(DummyContainer dummy) {\n\t\t\taddSlot(dummy\n\t\t\t\t\t.addStaticRestrictedSlot(0, pipe.getOriginalUpgradeManager().secInv, 10, 42, itemStack -> {\n\t\t\t\t\t\tif (itemStack.isEmpty()) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (itemStack.getItem() != LPItems.itemCard) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (itemStack.getItemDamage() != LogisticsItemCard.SEC_CARD) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn SimpleServiceLocator.securityStationManager\n\t\t\t\t\t\t\t\t.isAuthorized(UUID.fromString(itemStack.getTagCompound().getString(\"UUID\")));\n\t\t\t\t\t}, 1));\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderIcon(int x, int y) {\n\t\t\tGuiGraphics.drawLockBackground(mc, x + 1, y);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderBackgroundContent() {\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 9, guiTop + 41);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForegroundContent() {\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"security\"), 10, 28, Color.getValue(Color.DARKER_GREY), false);\n\t\t\tItemStack itemStack = pipe.getOriginalUpgradeManager().secInv.getStackInSlot(0);\n\t\t\tif (!itemStack.isEmpty()) {\n\t\t\t\tUUID id = UUID.fromString(itemStack.getTagCompound().getString(\"UUID\"));\n\t\t\t\tfontRenderer.drawString(\"Id: \", 10, 68, Color.getValue(Color.DARKER_GREY), false);\n\t\t\t\tGL11.glTranslated(10, 80, 0);\n\t\t\t\tGL11.glScaled(0.75D, 0.75D, 1.0D);\n\t\t\t\tfontRenderer.drawString(ChatColor.BLUE.toString() + id.toString(), 0, 0, Color.getValue(Color.DARKER_GREY), false);\n\t\t\t\tGL11.glScaled(1 / 0.75D, 1 / 0.75D, 1.0D);\n\t\t\t\tGL11.glTranslated(-10, -80, 0);\n\t\t\t\tfontRenderer.drawString(\"Authorization: \" + (SimpleServiceLocator.securityStationManager.isAuthorized(id) ? ChatColor.GREEN + \"Authorized\" : ChatColor.RED + \"Unauthorized\"), 10, 94, Color.getValue(Color.DARKER_GREY), false);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate class Statistics extends TabSubGui {\n\n\t\t@Override\n\t\tpublic void renderIcon(int x, int y) {\n\t\t\tGuiGraphics.drawStatsBackground(mc, x, y);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderBackgroundContent() {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForegroundContent() {\n\t\t\tString pipeName = ItemIdentifier.get(pipe.item, 0, null).getFriendlyName();\n\t\t\tfontRenderer.drawString(pipeName, (170 - fontRenderer.getStringWidth(pipeName)) / 2, 28, 0x83601c);\n\n\t\t\tint sessionXCenter = 85;\n\t\t\tint lifetimeXCenter = 140;\n\t\t\tString s;\n\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"Session\"), sessionXCenter - fontRenderer\n\t\t\t\t\t.getStringWidth(TextUtil.translate(PREFIX + \"Session\")) / 2, 40, 0x303030);\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"Lifetime\"), lifetimeXCenter - fontRenderer\n\t\t\t\t\t.getStringWidth(TextUtil.translate(PREFIX + \"Lifetime\")) / 2, 40, 0x303030);\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"Sent\") + \":\", 55 - fontRenderer\n\t\t\t\t\t.getStringWidth(TextUtil.translate(PREFIX + \"Sent\") + \":\"), 55, 0x303030);\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"Recieved\") + \":\", 55 - fontRenderer\n\t\t\t\t\t.getStringWidth(TextUtil.translate(PREFIX + \"Recieved\") + \":\"), 70, 0x303030);\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"Relayed\") + \":\", 55 - fontRenderer\n\t\t\t\t\t.getStringWidth(TextUtil.translate(PREFIX + \"Relayed\") + \":\"), 85, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.stat_session_sent);\n\t\t\tfontRenderer.drawString(s, sessionXCenter - fontRenderer.getStringWidth(s) / 2, 55, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.stat_session_recieved);\n\t\t\tfontRenderer.drawString(s, sessionXCenter - fontRenderer.getStringWidth(s) / 2, 70, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.stat_session_relayed);\n\t\t\tfontRenderer.drawString(s, sessionXCenter - fontRenderer.getStringWidth(s) / 2, 85, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.stat_lifetime_sent);\n\t\t\tfontRenderer.drawString(s, lifetimeXCenter - fontRenderer.getStringWidth(s) / 2, 55, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.stat_lifetime_recieved);\n\t\t\tfontRenderer.drawString(s, lifetimeXCenter - fontRenderer.getStringWidth(s) / 2, 70, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.stat_lifetime_relayed);\n\t\t\tfontRenderer.drawString(s, lifetimeXCenter - fontRenderer.getStringWidth(s) / 2, 85, 0x303030);\n\n\t\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"RoutingTableSize\") + \":\", 110 - fontRenderer\n\t\t\t\t\t.getStringWidth(TextUtil.translate(PREFIX + \"RoutingTableSize\") + \":\"), 110, 0x303030);\n\n\t\t\ts = StringUtils.getStringWithSpacesFromLong(pipe.server_routing_table_size);\n\t\t\tfontRenderer.drawString(s, 130 - fontRenderer.getStringWidth(s) / 2, 110, 0x303030);\n\t\t}\n\t}\n\n\tprivate class Logic extends TabSubGui {\n\n\t\tprivate GuiButton editButton;\n\n\t\t@Override\n\t\tpublic void initTab() {\n\t\t\teditButton = addButton(new GuiButton(0, guiLeft + 10, guiTop + 70, 160, 20, \"Edit Logic Controller\"));\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderIcon(int x, int y) {\n\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\tItemStack stack2 = new ItemStack(Blocks.REDSTONE_TORCH);\n\t\t\titemRender.renderItemAndEffectIntoGUI(stack2, x, y);\n\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\titemRender.zLevel = 0.0F;\n\t\t}\n\n\t\t@Override\n\t\tpublic void buttonClicked(GuiButton button) {\n\t\t\tif (button == editButton) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(LogicControllerPacket.class)\n\t\t\t\t\t\t.setTilePos(pipe.container));\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderBackgroundContent() {\n\n\t\t\tdrawRect(guiLeft + 12, guiTop + 34, guiLeft + 32, guiTop + 54, Color.BLACK);\n\t\t\tdrawRect(guiLeft + 14, guiTop + 36, guiLeft + 30, guiTop + 52, Color.DARKER_GREY);\n\t\t}\n\n\t\t@Override\n\t\tpublic void checkButton(GuiButton button, boolean isTabActive) {\n\t\t\tif (isTabActive) {\n\t\t\t\tbutton.enabled = pipe.container.logicController.diskInv.getStackInSlot(0) != null;\n\t\t\t}\n\t\t\tsuper.checkButton(button, isTabActive);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForegroundContent() {\n\n\t\t}\n\t}\n\n\tprivate class Tasks extends TabSubGui {\n\n\t\tprivate GuiButton leftButton;\n\t\tprivate GuiButton rightButton;\n\t\tprivate ItemDisplay _itemDisplay_5;\n\t\tprivate boolean managerWatching;\n\n\t\t@Override\n\t\tpublic void initTab() {\n\t\t\tKeyboard.enableRepeatEvents(true);\n\n\t\t\tleftButton = addButton(new SmallGuiButton(1, guiLeft + 95, guiTop + 26, 10, 10, \"<\"));\n\t\t\trightButton = addButton(new SmallGuiButton(2, guiLeft + 165, guiTop + 26, 10, 10, \">\"));\n\t\t\tif (_itemDisplay_5 == null) {\n\t\t\t\t_itemDisplay_5 = new ItemDisplay(null, fontRenderer, GuiPipeController.this, null, 10, 40, 20, 60, 0, 0, 0, new int[] { 1, 1, 1, 1 }, true);\n\t\t\t}\n\t\t\t_itemDisplay_5.reposition(10, 40, 20, 60, 0, 0);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderIcon(int x, int y) {\n\t\t\tGuiGraphics.drawLinesBackground(mc, x, y);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderBackgroundContent() {\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void leavingTab() {\n\t\t\tif (managerWatching) {\n\t\t\t\tmanagerWatching = false;\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PipeManagerWatchingPacket.class).setStart(false).setTilePos(pipe.container));\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void enteringTab() {\n\t\t\tif (!managerWatching) {\n\t\t\t\tmanagerWatching = true;\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PipeManagerWatchingPacket.class).setStart(true).setTilePos(pipe.container));\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void buttonClicked(GuiButton button) {\n\t\t\tif (button == leftButton) {\n\t\t\t\t_itemDisplay_5.prevPage();\n\t\t\t} else if (button == rightButton) {\n\t\t\t\t_itemDisplay_5.nextPage();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderForegroundContent() {\n\t\t\tList<ItemIdentifierStack> _allItems = pipe.getClientSideOrderManager().stream()\n\t\t\t\t\t.map(IOrderInfoProvider::getAsDisplayItem).collect(Collectors.toCollection(LinkedList::new));\n\t\t\t_itemDisplay_5.setItemList(_allItems);\n\t\t\t_itemDisplay_5.renderItemArea(zLevel);\n\t\t\t_itemDisplay_5.renderPageNumber(right - guiLeft - 45, 28);\n\t\t\tint start = _itemDisplay_5.getPage() * 3;\n\t\t\tint stringPos = 40;\n\t\t\tfor (int i = start; i < start + 3 && i < pipe.getClientSideOrderManager().size(); i++) {\n\t\t\t\tIOrderInfoProvider order = pipe.getClientSideOrderManager().get(i);\n\t\t\t\tItemIdentifier target = order.getTargetType();\n\t\t\t\tString s;\n\t\t\t\tif (target != null) {\n\t\t\t\t\ts = target.getFriendlyName();\n\t\t\t\t\tfontRenderer.drawString(s, 35, stringPos, 0x303030);\n\t\t\t\t}\n\t\t\t\ts = Integer.toString(i + 1);\n\t\t\t\tstringPos += 6;\n\t\t\t\tfontRenderer.drawString(s, 3, stringPos, 0x303030);\n\t\t\t\tstringPos += 4;\n\t\t\t\tDoubleCoordinates pos = order.getTargetPosition();\n\t\t\t\tif (pos != null) {\n\t\t\t\t\ts = pos.toIntBasedString();\n\t\t\t\t\tfontRenderer.drawString(s, 40, stringPos, 0x303030);\n\t\t\t\t}\n\t\t\t\tstringPos += 10;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiPowerJunction.java",
    "content": "package logisticspipes.gui;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.PowerJunctionCheatPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiPowerJunction extends LogisticsBaseGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.powerjunction.\";\n\n\tprivate final LogisticsPowerJunctionTileEntity junction;\n\n\tpublic GuiPowerJunction(EntityPlayer player, LogisticsPowerJunctionTileEntity junction) {\n\t\tsuper(176, 166, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player, null, junction);\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 80);\n\t\tinventorySlots = dummy;\n\t\tthis.junction = junction;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/power_junction.png\");\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiPowerJunction.TEXTURE);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t\tint level = 100 - junction.getChargeState();\n\t\tdrawTexturedModalRect(j + 10, k + 11 + (level * 59 / 100), 176, level * 59 / 100, 5, 59 - (level * 59 / 100));\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiPowerJunction.PREFIX + \"LogisticsPowerJunction\"), guiLeft + 30, guiTop + 8, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiPowerJunction.PREFIX + \"StoredEnergy\") + \":\", guiLeft + 40, guiTop + 23, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.formatNumberWithCommas(junction.getPowerLevel()) + \" LP\", guiLeft + 40, guiTop + 33, 0x404040);\n\t\tmc.fontRenderer.drawString(\"/ \" + TextUtil.formatNumberWithCommas(LogisticsPowerJunctionTileEntity.MAX_STORAGE) + \" LP\", guiLeft + 40, guiTop + 43, 0x404040);\n\t\tmc.fontRenderer.drawString(\"1 MJ = 5 LP\", guiLeft + 30, guiTop + 58, 0x404040);\n\t\tmc.fontRenderer.drawString(\"1 EU = 2 LP\", guiLeft + 100, guiTop + 58, 0x404040);\n\t\tmc.fontRenderer.drawString(\"10 RF = 5 LP\", guiLeft + 24, guiTop + 68, 0x404040);\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tbuttonList.add(new GuiButton(0, guiLeft + 140, guiTop + 20, 20, 20, \"+\"));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton par1GuiButton) throws IOException {\n\t\tif (par1GuiButton.id == 0) {\n\t\t\tjunction.addEnergy(100000);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PowerJunctionCheatPacket.class).setPosX(junction.getX()).setPosY(junction.getY()).setPosZ(junction.getZ()));\n\t\t} else {\n\t\t\tsuper.actionPerformed(par1GuiButton);\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiPowerProvider.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerProviderTileEntity;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.string.StringUtils;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiPowerProvider extends LogisticsBaseGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.powerprovider.\";\n\n\tprivate final LogisticsPowerProviderTileEntity junction;\n\n\tpublic GuiPowerProvider(EntityPlayer player, LogisticsPowerProviderTileEntity junction) {\n\t\tsuper(176, 166, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player, null, junction);\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 80);\n\t\tinventorySlots = dummy;\n\t\tthis.junction = junction;\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/power_junction.png\");\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiPowerProvider.TEXTURE);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t\tint level = 100 - junction.getChargeState();\n\t\tdrawTexturedModalRect(j + 10, k + 11 + (level * 59 / 100), 176, level * 59 / 100, 5, 59 - (level * 59 / 100));\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiPowerProvider.PREFIX + \"Logistics\" + junction.getBrand() + \"PowerProvider\"), guiLeft + 25, guiTop + 8, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiPowerProvider.PREFIX + \"StoredEnergy\") + \":\", guiLeft + 40, guiTop + 25, 0x404040);\n\t\tmc.fontRenderer.drawString(StringUtils.getStringWithSpacesFromInteger(junction.getDisplayPowerLevel()) + \" \" + junction.getBrand(), guiLeft + 40, guiTop + 35, 0x404040);\n\t\tmc.fontRenderer.drawString(\"/ \" + StringUtils.getStringWithSpacesFromInteger(junction.getMaxStorage()) + \" \" + junction.getBrand(), guiLeft + 40, guiTop + 45, 0x404040);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiProgramCompiler.java",
    "content": "package logisticspipes.gui;\n\nimport java.io.IOException;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport java.util.stream.StreamSupport;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagString;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.CompilerTriggerTaskPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.TextListDisplay;\nimport network.rs485.logisticspipes.util.TextUtil;\n\n//TODO: Config Option for disabling program compilation\npublic class GuiProgramCompiler extends LogisticsBaseGuiScreen {\n\n\tprivate final LogisticsProgramCompilerTileEntity compiler;\n\tprivate final TextListDisplay.List categoryTextList;\n\tprivate final TextListDisplay.List programTextList;\n\tprivate final TextListDisplay categoryList;\n\tprivate final TextListDisplay programList;\n\tprivate final TextListDisplay programListLarge;\n\tprivate SmallGuiButton programmerButton;\n\tprivate InputBar search;\n\n\tpublic GuiProgramCompiler(EntityPlayer player, LogisticsProgramCompilerTileEntity compiler) {\n\t\tsuper(180, 190, 0, 0);\n\t\tthis.compiler = compiler;\n\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, compiler.getInventory());\n\n\t\tdummy.addRestrictedSlot(0, compiler.getInventory(), 10, 10, LPItems.disk);\n\t\tdummy.addRestrictedSlot(1, compiler.getInventory(), 154, 10, LPItems.logisticsProgrammer);\n\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 105);\n\n\t\tcategoryTextList = new TextListDisplay.List() {\n\n\t\t\t@Override\n\t\t\tpublic int getSize() {\n\t\t\t\tif (compiler.getInventory().getStackInSlot(0).isEmpty()) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\treturn (int) LogisticsProgramCompilerTileEntity.programByCategory.keySet().stream()\n\t\t\t\t\t\t.filter(it -> StreamSupport.stream(list.spliterator(), false).noneMatch(nbtBase -> ((NBTTagString) nbtBase).getString().equals(it.toString()))).count();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String getTextAt(int index) {\n\t\t\t\tif (compiler.getInventory().getStackInSlot(0).isEmpty()) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\treturn TextUtil.translate(\"gui.compiler.\" + LogisticsProgramCompilerTileEntity.programByCategory.keySet().stream()\n\t\t\t\t\t\t.filter(it -> StreamSupport.stream(list.spliterator(), false).noneMatch(nbtBase -> ((NBTTagString) nbtBase).getString().equals(it.toString())))\n\t\t\t\t\t\t.skip(index)\n\t\t\t\t\t\t.findFirst()\n\t\t\t\t\t\t.map(it -> String.format(\"%s.%s\", it.getNamespace(), it.getPath()))\n\t\t\t\t\t\t.orElse(null));\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getTextColor(int index) {\n\t\t\t\treturn 0xFFFFFF;\n\t\t\t}\n\t\t};\n\t\tcategoryList = new TextListDisplay(this, 8, 30, 110, 104, 5, categoryTextList);\n\n\t\tprogramTextList = new TextListDisplay.List() {\n\n\t\t\t@Override\n\t\t\tpublic int getSize() {\n\t\t\t\tif (compiler.getInventory().getStackInSlot(0).isEmpty()) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\n\t\t\t\treturn getProgramListForSelectionIndex(list).size();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String getTextAt(int index) {\n\t\t\t\tif (compiler.getInventory().getStackInSlot(0).isEmpty()) {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\tResourceLocation sel = getProgramListForSelectionIndex(list).get(index);\n\n\t\t\t\tItem selItem = Item.REGISTRY.getObject(sel);\n\t\t\t\tif (selItem != null) {\n\t\t\t\t\treturn TextUtil.translate(selItem.getTranslationKey() + \".name\");\n\t\t\t\t}\n\t\t\t\treturn \"UNDEFINED\";\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getTextColor(int index) {\n\t\t\t\tif (compiler.getInventory().getStackInSlot(0).isEmpty()) {\n\t\t\t\t\treturn 0xFFFFFF;\n\t\t\t\t}\n\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\tResourceLocation sel = getProgramListForSelectionIndex(list).get(index);\n\n\t\t\t\tNBTTagList listPrograms = compiler.getNBTTagListForKey(\"compilerPrograms\");\n\t\t\t\treturn StreamSupport.stream(listPrograms.spliterator(), false).anyMatch(it -> new ResourceLocation(((NBTTagString) it).getString()).equals(sel))\n\t\t\t\t\t\t? 0xAAFFAA : 0xFFAAAA;\n\t\t\t}\n\t\t};\n\n\t\tprogramList = new TextListDisplay(this, 80, 30, 8, 104, 5, programTextList);\n\t\tprogramListLarge = new TextListDisplay(this, 8, 30, 8, 104, 5, programTextList);\n\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, guiLeft + 8, guiTop + 90, 15, 10, \"/\\\\\"));\n\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 24, guiTop + 90, 15, 10, \"\\\\/\"));\n\t\tbuttonList.add(new SmallGuiButton(2, guiLeft + 40, guiTop + 90, 40, 10, \"Unlock\"));\n\t\tbuttonList.add(new SmallGuiButton(3, guiLeft + 100, guiTop + 90, 15, 10, \"/\\\\\"));\n\t\tbuttonList.add(new SmallGuiButton(4, guiLeft + 116, guiTop + 90, 15, 10, \"\\\\/\"));\n\t\tbuttonList.add(programmerButton = new SmallGuiButton(5, guiLeft + 132, guiTop + 90, 40, 10, \"Compile\"));\n\n\t\tsearch = new InputBar(fontRenderer, this, guiLeft + 30, guiTop + 11, 120, 16);\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) throws IOException {\n\t\tsuper.actionPerformed(button);\n\t\tswitch (button.id) {\n\t\t\tcase 0:\n\t\t\t\tcategoryList.scrollDown();\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tcategoryList.scrollUp();\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif (categoryList.getSelected() != -1) {\n\t\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\t\tLogisticsProgramCompilerTileEntity.programByCategory.keySet().stream()\n\t\t\t\t\t\t\t.filter(it -> StreamSupport.stream(list.spliterator(), false).noneMatch(nbtBase -> ((NBTTagString) nbtBase).getString().equals(it.toString())))\n\t\t\t\t\t\t\t.skip(categoryList.getSelected())\n\t\t\t\t\t\t\t.findFirst()\n\t\t\t\t\t\t\t.ifPresent(it -> {\n\t\t\t\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(CompilerTriggerTaskPacket.class).setCategory(it).setType(\"category\").setTilePos(compiler));\n\t\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\t\tprogramListLarge.scrollDown();\n\t\t\t\t} else {\n\t\t\t\t\tprogramList.scrollDown();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\t\tprogramListLarge.scrollUp();\n\t\t\t\t} else {\n\t\t\t\t\tprogramList.scrollUp();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tint selIndex = programList.getSelected();\n\t\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\t\tselIndex = programListLarge.getSelected();\n\t\t\t\t}\n\t\t\t\tif (selIndex != -1) {\n\t\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\t\tResourceLocation sel = getProgramListForSelectionIndex(list).get(selIndex);\n\n\t\t\t\t\tNBTTagList listPrograms = compiler.getNBTTagListForKey(\"compilerPrograms\");\n\t\t\t\t\tboolean flag = StreamSupport.stream(listPrograms.spliterator(), false)\n\t\t\t\t\t\t\t.anyMatch(it -> new ResourceLocation(((NBTTagString) it).getString()).equals(sel));\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(CompilerTriggerTaskPacket.class).setCategory(sel).setType(flag ? \"flash\" : \"program\").setTilePos(compiler));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 105);\n\t\tGuiGraphics.drawSlotDiskBackground(mc, guiLeft + 9, guiTop + 9);\n\t\tGuiGraphics.drawSlotProgrammerBackground(mc, guiLeft + 153, guiTop + 9);\n\n\t\tif (compiler.getCurrentTask() != null) {\n\t\t\tfontRenderer.drawString(TextUtil.translate(\"gui.compiler.processing\"), guiLeft + 10, guiTop + 39, 0x000000);\n\t\t\tString name;\n\t\t\tItem item = Item.REGISTRY.getObject(compiler.getCurrentTask());\n\t\t\tif (item != null) {\n\t\t\t\tname = item.getTranslationKey() + \".name\";\n\t\t\t} else {\n\t\t\t\tname = \"gui.compiler.\" + compiler.getCurrentTask().toString().replace(':', '.');\n\t\t\t}\n\t\t\tString text = TextUtil.getTrimmedString(TextUtil.translate(name),\n\t\t\t\t\t160, fontRenderer, \"...\");\n\t\t\tfontRenderer.drawString(text, guiLeft + 10, guiTop + 70, 0x000000);\n\t\t\tdrawRect(guiLeft + 9, guiTop + 50, guiLeft + 171, guiTop + 66, Color.BLACK);\n\t\t\tdrawRect(guiLeft + 10, guiTop + 51, guiLeft + 170, guiTop + 65, Color.WHITE);\n\t\t\tdrawRect(guiLeft + 11, guiTop + 52, guiLeft + 11 + (int) (158 * compiler.getTaskProgress()), guiTop + 64, Color.GREEN);\n\n\t\t\tif (!compiler.isWasAbleToConsumePower()) {\n\t\t\t\tfontRenderer.drawString(TextUtil.translate(\"gui.compiler.nopower.1\"), guiLeft + 68, guiTop + 10, 0x000000);\n\t\t\t\tfontRenderer.drawString(TextUtil.translate(\"gui.compiler.nopower.2\"), guiLeft + 35, guiTop + 20, 0x000000);\n\t\t\t}\n\n\t\t\tbuttonList.forEach(b -> b.visible = false);\n\t\t} else {\n\t\t\tbuttonList.forEach(b -> b.visible = true);\n\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\tbuttonList.stream().limit(3).forEach(b -> b.visible = false);\n\t\t\t\tprogramListLarge.renderGuiBackground(var2, var3);\n\t\t\t} else {\n\t\t\t\tbuttonList.stream().limit(3).forEach(b -> b.visible = true);\n\t\t\t\tcategoryList.renderGuiBackground(var2, var3);\n\t\t\t\tprogramList.renderGuiBackground(var2, var3);\n\t\t\t}\n\n\t\t\tsearch.drawTextBox();\n\n\t\t\tint selIndex = programList.getSelected();\n\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\tselIndex = programListLarge.getSelected();\n\t\t\t}\n\n\t\t\tif (selIndex != -1) {\n\t\t\t\tNBTTagList list = compiler.getNBTTagListForKey(\"compilerCategories\");\n\t\t\t\tResourceLocation sel = getProgramListForSelectionIndex(list).get(selIndex);\n\n\t\t\t\tNBTTagList listPrograms = compiler.getNBTTagListForKey(\"compilerPrograms\");\n\t\t\t\tif (StreamSupport.stream(listPrograms.spliterator(), false).anyMatch(it -> new ResourceLocation(((NBTTagString) it).getString()).equals(sel))) {\n\t\t\t\t\tprogrammerButton.displayString = \"Flash\";\n\t\t\t\t\tprogrammerButton.enabled = !compiler.getInventory().getStackInSlot(1).isEmpty();\n\t\t\t\t} else {\n\t\t\t\t\tprogrammerButton.displayString = \"Compile\";\n\t\t\t\t\tprogrammerButton.enabled = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate List<ResourceLocation> getProgramListForSelectionIndex(NBTTagList list) {\n\t\treturn StreamSupport.stream(list.spliterator(), false).flatMap(\n\t\t\t\tnbtBase -> LogisticsProgramCompilerTileEntity.programByCategory.get(new ResourceLocation(((NBTTagString) nbtBase).getString()))\n\t\t\t\t\t\t.stream())\n\t\t\t\t.filter(it -> TextUtil.translate(Item.REGISTRY.getObject(it).getTranslationKey() + \".name\").toLowerCase().contains(search.getText().toLowerCase()))\n\t\t\t\t.sorted(Comparator.comparing(o -> getSortingClass(Item.REGISTRY.getObject((ResourceLocation) o)))\n\t\t\t\t\t\t.thenComparing(o -> TextUtil.translate(Item.REGISTRY.getObject((ResourceLocation) o).getTranslationKey() + \".name\").toLowerCase())\n\t\t\t\t)\n\t\t\t\t.collect(Collectors.toList());\n\t}\n\n\tprivate int getSortingClass(Item object) {\n\t\tif (object instanceof ItemLogisticsPipe) {\n\t\t\treturn 0;\n\t\t} else if (object instanceof ItemModule) {\n\t\t\treturn 1;\n\t\t} else if (object instanceof ItemUpgrade) {\n\t\t\treturn 2;\n\t\t}\n\t\treturn 10;\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tint wheel = org.lwjgl.input.Mouse.getDWheel() / 120;\n\t\tif (wheel == 0) {\n\t\t\tsuper.handleMouseInputSub();\n\t\t}\n\t\tif (compiler.getCurrentTask() == null) {\n\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\tif (wheel < 0) {\n\t\t\t\t\tprogramListLarge.mouseScrollUp();\n\t\t\t\t} else if (wheel > 0) {\n\t\t\t\t\tprogramListLarge.mouseScrollDown();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (wheel < 0) {\n\t\t\t\t\tcategoryList.mouseScrollUp();\n\t\t\t\t\tprogramList.mouseScrollUp();\n\t\t\t\t} else if (wheel > 0) {\n\t\t\t\t\tcategoryList.mouseScrollDown();\n\t\t\t\t\tprogramList.mouseScrollDown();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void keyTyped(char typedChar, int keyCode) throws IOException {\n\t\tif (compiler.getCurrentTask() == null) {\n\t\t\tif (!search.handleKey(typedChar, keyCode)) {\n\t\t\t\tsuper.keyTyped(typedChar, keyCode);\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.keyTyped(typedChar, keyCode);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int par1, int par2, int par3) throws IOException {\n\t\tsuper.mouseClicked(par1, par2, par3);\n\t\tif (compiler.getCurrentTask() == null) {\n\t\t\tsearch.handleClick(par1, par2, par3);\n\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\tprogramListLarge.mouseClicked(par1, par2, par3);\n\t\t\t} else {\n\t\t\t\tcategoryList.mouseClicked(par1, par2, par3);\n\t\t\t\tprogramList.mouseClicked(par1, par2, par3);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tif (compiler.getCurrentTask() == null) {\n\t\t\tif (categoryTextList.getSize() == 0 && programTextList.getSize() != 0) {\n\t\t\t\tprogramListLarge.renderGuiForeground();\n\t\t\t} else {\n\t\t\t\tcategoryList.renderGuiForeground();\n\t\t\t\tprogramList.renderGuiForeground();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiSatellitePipe.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui;\n\nimport java.io.IOException;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.tileentity.TileEntity;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.satpipe.SatelliteSetNamePacket;\nimport logisticspipes.pipes.SatelliteNamingResult;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport network.rs485.logisticspipes.SatellitePipe;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiSatellitePipe extends LogisticsBaseGuiScreen {\n\n\t@Nonnull\n\tprivate final SatellitePipe satellitePipe;\n\n\t@Nonnull\n\tprivate String response = \"\";\n\n\tprivate InputBar input;\n\n\tpublic GuiSatellitePipe(@Nonnull SatellitePipe satellitePipe) {\n\t\tsuper(new Container() {\n\n\t\t\t@Override\n\t\t\tpublic boolean canInteractWith(@Nonnull EntityPlayer entityplayer) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\t\txSize = 116;\n\t\tySize = 77;\n\t\tthis.satellitePipe = satellitePipe;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\t\tbuttonList.add(new SmallGuiButton(0, (width / 2) - (30 / 2) + 35, (height / 2) + 20, 30, 10, \"Save\"));\n\t\tinput = new InputBar(fontRenderer, this, guiLeft + 8, guiTop + 40, 100, 16);\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) {\n\t\t\tfinal TileEntity container = satellitePipe.getContainer();\n\t\t\tif (container != null) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SatelliteSetNamePacket.class).setString(input.getText()).setTilePos(container));\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tdrawCenteredString(TextUtil.translate(\"gui.satellite.SatelliteName\"), 59, 7, 0x404040);\n\t\tString name = TextUtil.getTrimmedString(satellitePipe.getSatellitePipeName(), 100, mc.fontRenderer, \"...\");\n\t\tint yOffset = 0;\n\t\tif (!response.isEmpty()) {\n\t\t\tdrawCenteredString(TextUtil.translate(\"gui.satellite.naming_result.\" + response), xSize / 2, 30, response.equals(\"success\") ? 0x404040 : 0x5c1111);\n\t\t\tyOffset = 4;\n\t\t}\n\t\tdrawCenteredString(name, xSize / 2, 24 - yOffset, 0x404040);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tsuper.drawGuiContainerBackgroundLayer(f, x, y);\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tinput.drawTextBox();\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int x, int y, int k) throws IOException {\n\t\tif (!input.handleClick(x, y, k)) {\n\t\t\tsuper.mouseClicked(x, y, k);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void keyTyped(char c, int i) throws IOException {\n\t\tif (!input.handleKey(c, i)) {\n\t\t\tsuper.keyTyped(c, i);\n\t\t}\n\t}\n\n\tpublic void handleResponse(SatelliteNamingResult result, String newName) {\n\t\tresponse = result.toString();\n\t\tif (result == SatelliteNamingResult.SUCCESS) {\n\t\t\tsatellitePipe.setSatellitePipeName(newName);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiSecurityStation.java",
    "content": "package logisticspipes.gui;\n\nimport java.io.IOException;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.gui.popup.GuiEditCCAccessTable;\nimport logisticspipes.gui.popup.GuiSecurityStationPopup;\nimport logisticspipes.interfaces.PlayerListReciver;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.PlayerListRequest;\nimport logisticspipes.network.packets.block.SecurityAuthorizationPacket;\nimport logisticspipes.network.packets.block.SecurityCardPacket;\nimport logisticspipes.network.packets.block.SecurityRequestCCIdsPacket;\nimport logisticspipes.network.packets.block.SecurityStationAutoDestroy;\nimport logisticspipes.network.packets.block.SecurityStationCC;\nimport logisticspipes.network.packets.block.SecurityStationOpenPlayerRequest;\nimport logisticspipes.network.packets.gui.OpenSecurityChannelManagerPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiSecurityStation extends LogisticsBaseGuiScreen implements PlayerListReciver {\n\n\tprivate static final String PREFIX = \"gui.securitystation.\";\n\n\tprivate final LogisticsSecurityTileEntity _tile;\n\tprivate final List<String> players = new LinkedList<>();\n\n\t//Player name:\n\tprotected static final int searchWidth = 250;\n\tprotected int lastClickedX = 0;\n\tprotected int lastClickedY = 0;\n\tprotected int lastClickedK = 0;\n\tprivate int addition;\n\tprivate boolean authorized;\n\tprivate InputBar searchBar;\n\n\tprotected final String _title = \"Request items\";\n\tprotected boolean clickWasButton = false;\n\n\tpublic GuiSecurityStation(LogisticsSecurityTileEntity tile, EntityPlayer player) {\n\t\tsuper(280, 260, 0, 0);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, tile.inv);\n\t\tdummy.addRestrictedSlot(0, tile.inv, 82, 141, (Item) null);\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 175);\n\t\tinventorySlots = dummy;\n\t\t_tile = tile;\n\t\tauthorized = SimpleServiceLocator.securityStationManager.isAuthorized(tile.getSecId());\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, guiLeft + 10, guiTop + 179, 30, 20, \"--\"));\n\t\tbuttonList.get(0).visible = false;\n\t\tbuttonList.add(new GuiButton(1, guiLeft + 10, guiTop + 139, 30, 20, \"-\"));\n\t\tbuttonList.add(new GuiButton(2, guiLeft + 45, guiTop + 139, 30, 20, \"+\"));\n\t\tbuttonList.add(new GuiButton(3, guiLeft + 140, guiTop + 179, 30, 20, \"++\"));\n\t\tbuttonList.get(3).visible = false;\n\t\tbuttonList.add(new SmallGuiButton(4, guiLeft + 241, guiTop + 217, 30, 10, TextUtil\n\t\t\t\t.translate(GuiSecurityStation.PREFIX + \"Open\")));\n\t\tbuttonList.add(new GuiCheckBox(5, guiLeft + 160, guiTop + 42, 16, 16, _tile.allowCC));\n\t\tbuttonList.add(new SmallGuiButton(6, guiLeft + 162, guiTop + 60, 60, 10, TextUtil.translate(GuiSecurityStation.PREFIX + \"EditTable\")));\n\t\tif (!SimpleServiceLocator.ccProxy.isCC() && !LogisticsPipes.isDEBUG()) {\n\t\t\tbuttonList.get(5).visible = false;\n\t\t\tbuttonList.get(6).visible = false;\n\t\t}\n\t\tbuttonList.add(new GuiButton(7, guiLeft + 55, guiTop + 95, 70, 20, TextUtil.translate(GuiSecurityStation.PREFIX + \"Authorize\")));\n\t\tbuttonList.add(new GuiButton(8, guiLeft + 175, guiTop + 95, 70, 20, TextUtil.translate(GuiSecurityStation.PREFIX + \"Deauthorize\")));\n\t\tbuttonList.add(new GuiCheckBox(9, guiLeft + 160, guiTop + 74, 16, 16, _tile.allowAutoDestroy));\n\t\tbuttonList.add(new GuiButton(10, guiLeft + 177, guiTop + 230, 95, 20, TextUtil.translate(GuiSecurityStation.PREFIX + \"ChannelManager\")));\n\t\tif (searchBar == null) {\n\t\t\tsearchBar = new InputBar(this.fontRenderer, this, guiLeft + 180, bottom - 120, right - 8 + addition - guiLeft - 180, 17);\n\t\t\tlastClickedX = -10000000;\n\t\t\tlastClickedY = -10000000;\n\t\t}\n\t\tsearchBar.reposition(guiLeft + 180, bottom - 120, right - 8 + addition - guiLeft - 180, 17);\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PlayerListRequest.class));\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) throws IOException {\n\t\tif (button.id < 4) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityCardPacket.class).setInteger(button.id).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 4) {\n\t\t\tif (!searchBar.getText().isEmpty()) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityStationOpenPlayerRequest.class).setString(searchBar.getText()).setBlockPos(_tile.getPos()));\n\t\t\t}\n\t\t} else if (button.id == 5) {\n\t\t\t_tile.allowCC = !_tile.allowCC;\n\t\t\trefreshCheckBoxes();\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityStationCC.class).setInteger(_tile.allowCC ? 1 : 0).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 6) {\n\t\t\tsetSubGui(new GuiEditCCAccessTable(_tile));\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityRequestCCIdsPacket.class).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 7) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityAuthorizationPacket.class).setInteger(1).setBlockPos(_tile.getPos()));\n\t\t\tauthorized = true;\n\t\t} else if (button.id == 8) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityAuthorizationPacket.class).setInteger(0).setBlockPos(_tile.getPos()));\n\t\t\tauthorized = false;\n\t\t} else if (button.id == 9) {\n\t\t\t_tile.allowAutoDestroy = !_tile.allowAutoDestroy;\n\t\t\trefreshCheckBoxes();\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityStationAutoDestroy.class).setInteger(_tile.allowAutoDestroy ? 1 : 0).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 10) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OpenSecurityChannelManagerPacket.class).setBlockPos(_tile.getPos()));\n\t\t} else {\n\t\t\tsuper.actionPerformed(button);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 175);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 81, guiTop + 140);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"SecurityStation\"), guiLeft + 105, guiTop + 10, 0x404040);\n\t\tmc.fontRenderer.drawString(_tile.getSecId() == null ? \"null\" : _tile.getSecId().toString(), guiLeft + 32, guiTop + 25, 0x404040);\n\t\tif (SimpleServiceLocator.ccProxy.isCC() || LogisticsPipes.isDEBUG()) {\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"allowCCAccess\") + \":\", guiLeft + 10, guiTop + 46, 0x404040);\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"excludeIDs\") + \":\", guiLeft + 10, guiTop + 61, 0x404040);\n\t\t}\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"pipeRemove\") + \":\", guiLeft + 10, guiTop + 78, 0x404040);\n\t\t//mc.fontRenderer.drawString(\"---------------------------------------------\", guiLeft + 5, guiTop + 90, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"Player\") + \":\", guiLeft + 180, guiTop + 127, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"SecurityCards\") + \":\", guiLeft + 10, guiTop + 127, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStation.PREFIX + \"Inventory\") + \":\", guiLeft + 10, guiTop + 163, 0x404040);\n\n\t\taddition = (mc.fontRenderer.getStringWidth(searchBar.getText()) - 82);\n\n\t\tif (addition < 0) {\n\t\t\taddition = 0;\n\t\t}\n\n\t\tsearchBar.drawTextBox();\n\n\t\tint pos = bottom - 95;\n\t\tfor (String player : players) {\n\t\t\tif (player.contains(searchBar.getText())) {\n\t\t\t\tmc.fontRenderer.drawString(player, guiLeft + 180, pos, 0x404040);\n\t\t\t\tpos += 11;\n\t\t\t}\n\t\t\t//Check mouse click\n\t\t\tif (guiLeft + 180 < lastClickedX && lastClickedX < guiLeft + 280 && pos - 11 < lastClickedY && lastClickedY < pos) {\n\t\t\t\tlastClickedX = -10000000;\n\t\t\t\tlastClickedY = -10000000;\n\t\t\t\tsearchBar.setText(player);\n\t\t\t}\n\t\t\tif (pos > bottom - 12) {\n\t\t\t\tmc.fontRenderer.drawString(\"...\", guiLeft + 180, pos - 5, 0x404040);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (authorized) {\n\t\t\tGui.drawRect(guiLeft + 127, guiTop + 101, guiLeft + 147, guiTop + 108, Color.getValue(Color.GREEN));\n\t\t} else {\n\t\t\tGui.drawRect(guiLeft + 153, guiTop + 101, guiLeft + 173, guiTop + 108, Color.getValue(Color.RED));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tif (searchBar.handleClick(i, j, k))\n\t\t\treturn;\n\t\tsuper.mouseClicked(i, j, k);\n\n\t\tif ((i >= guiLeft + 5 && i < right - 5 + addition && j >= guiTop + 5 && j < bottom - 5) && !searchBar.isFocused()) {\n\t\t\tlastClickedX = i;\n\t\t\tlastClickedY = j;\n\t\t\tlastClickedK = k;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) throws IOException {\n\t\tif (searchBar.isFocused()) {\n\t\t\tif ((c == 13) || (i == 1) || (i == 28)) {\n\t\t\t\tsearchBar.setFocused(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (searchBar.handleKey(c, i))\n\t\t\t\treturn;\n\t\t}\n\t\tsuper.keyTyped(c, i);\n\t}\n\n\t@Override\n\tpublic void receivePlayerList(List<String> list) {\n\t\tplayers.clear();\n\t\tplayers.addAll(list);\n\t}\n\n\tpublic void handlePlayerSecurityOpen(SecuritySettings setting) {\n\t\tsearchBar.setText(\"\");\n\t\tsetSubGui(new GuiSecurityStationPopup(setting, _tile));\n\t}\n\n\tpublic void refreshCheckBoxes() {\n\t\t((GuiCheckBox) buttonList.get(5)).setState(_tile.allowCC);\n\t\t((GuiCheckBox) buttonList.get(9)).setState(_tile.allowAutoDestroy);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiStatistics.java",
    "content": "package logisticspipes.gui;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.item.ItemStack;\n\nimport static java.lang.Math.max;\nimport static java.lang.Math.min;\nimport static java.lang.Math.pow;\nimport static java.lang.Math.round;\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.input.Mouse;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.blocks.stats.TrackingTask;\nimport logisticspipes.gui.popup.GuiAddTracking;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.RemoveAmoundTask;\nimport logisticspipes.network.packets.block.RequestAmountTaskSubGui;\nimport logisticspipes.network.packets.block.RequestRunningCraftingTasks;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.math.Vec2;\nimport logisticspipes.utils.string.StringUtils;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiStatistics extends LogisticsBaseGuiScreen {\n\n\tprivate final String PREFIX = \"gui.networkstatistics.\";\n\n\tprivate int currentTab;\n\tprivate final TabTracker tabTracker = new TabTracker();\n\tprivate final TabCrafting tabCrafting = new TabCrafting();\n\tprivate final List<StatisticsTab> tabs = Arrays.asList(tabTracker, tabCrafting);\n\n\tprivate final LogisticsStatisticsTileEntity tile;\n\n\tprivate int prevMouseDragX;\n\tprivate int prevMouseDragY;\n\n\tpublic GuiStatistics(final LogisticsStatisticsTileEntity tile) {\n\t\tsuper(180, 220, 0, 0);\n\t\tthis.tile = tile;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\n\t\ttabs.forEach(StatisticsTab::init);\n\n\t\ttabTracker.updateItemList();\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tpublic void resetSubGui() {\n\t\tsuper.resetSubGui();\n\t\ttabTracker.updateItemList();\n\t}\n\n\tprivate StatisticsTab getActiveTab() {\n\t\treturn tabs.get(currentTab);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tgetActiveTab().actionPerformed(button);\n\t}\n\n\t@Override\n\tprotected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {\n\t\tgetActiveTab().onMouseDrag(mouseX, mouseY, mouseX - prevMouseDragX, mouseY - prevMouseDragY);\n\t\tprevMouseDragX = mouseX;\n\t\tprevMouseDragY = mouseY;\n\t\tsuper.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {\n\t\tGlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);\n\n\t\tdrawBG();\n\t\tgetActiveTab().draw(mouseX, mouseY);\n\n\t\tsuper.drawGuiContainerBackgroundLayer(f, mouseX, mouseY);\n\t}\n\n\tprivate void drawBG() {\n\t\t// background\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop + 20, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft + (25 * currentTab) + 2, guiTop - 2, guiLeft + 27 + (25 * currentTab), guiTop + 38, zLevel, true, true, true, false, true);\n\n\t\t// tab selector panes\n\t\tfor (int i = 0; i < tabs.size(); i++) {\n\t\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft + (25 * i) + 2, guiTop - 2, guiLeft + 27 + (25 * i), guiTop + 35, zLevel, false, true, true, false, true);\n\t\t}\n\n\t\t// First Tab\n\t\tGuiGraphics.drawStatsBackground(mc, guiLeft + 6, guiTop + 3);\n\n\t\t// Second Tab\n\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\tItemStack stack = new ItemStack(Blocks.CRAFTING_TABLE, 1);\n\t\tGlStateManager.enableDepth();\n\t\titemRender.renderItemAndEffectIntoGUI(stack, guiLeft + 31, guiTop + 3);\n\t\tGlStateManager.disableDepth();\n\t\titemRender.zLevel = 0.0F;\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) throws IOException {\n\t\tsuper.keyTyped(c, i);\n\t\tgetActiveTab().keyTyped(c, i);\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {\n\t\tprevMouseDragX = mouseX;\n\t\tprevMouseDragY = mouseY;\n\n\t\tif (mouseButton == 0 && mouseX > guiLeft && mouseX < guiLeft + 220 && mouseY > guiTop && mouseY < guiTop + 20) {\n\t\t\tmouseX -= guiLeft + 3;\n\t\t\tcurrentTab = max(0, min(mouseX / 25, tabs.size() - 1));\n\t\t} else {\n\t\t\tgetActiveTab().handleClick(mouseX, mouseY, mouseButton);\n\t\t\tsuper.mouseClicked(mouseX, mouseY, mouseButton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {\n\t\tsuper.drawGuiContainerForegroundLayer(mouseX, mouseY);\n\t\tgetActiveTab().drawForegroundLayer(mouseX, mouseY);\n\t}\n\n\t@Override\n\tprotected void checkButtons() {\n\t\tsuper.checkButtons();\n\t\ttabs.forEach(StatisticsTab::checkButtons);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tgetActiveTab().onMouseScroll(Mouse.getEventDWheel());\n\t\tsuper.handleMouseInputSub();\n\t}\n\n\tpublic void handlePacket1(List<ItemIdentifierStack> identList) {\n\t\ttabTracker.handlePacket(identList);\n\t}\n\n\tpublic void handlePacket2(List<ItemIdentifierStack> identList) {\n\t\ttabCrafting.handlePacket(identList);\n\t}\n\n\tprivate interface StatisticsTab {\n\n\t\tvoid init();\n\n\t\tvoid draw(int mouseX, int mouseY);\n\n\t\tdefault void drawForegroundLayer(int mouseX, int mouseY) {}\n\n\t\tdefault void checkButtons() {}\n\n\t\tdefault void actionPerformed(GuiButton button) {}\n\n\t\tdefault void keyTyped(char c, int i) {}\n\n\t\tdefault void handleClick(int mouseX, int mouseY, int mouseButton) {}\n\n\t\tdefault void onMouseDrag(int x, int y, int dx, int dy) {}\n\n\t\tdefault void onMouseScroll(int dw) {}\n\n\t}\n\n\tprivate class TabTracker implements StatisticsTab {\n\n\t\tprivate ItemDisplay itemDisplay;\n\n\t\tprivate float xViewportOffset = -1434;\n\t\tprivate float yViewportOffset;\n\t\tprivate float xViewportScale = 15;\n\t\tprivate float yViewportScale = 15;\n\n\t\tprivate boolean isDraggingGraph = false;\n\t\tprivate boolean isDraggingXBar = false;\n\t\tprivate boolean isDraggingYBar = false;\n\n\t\tprivate final List<GuiButton> BUTTONS = new ArrayList<>();\n\n\t\t@Override\n\t\tpublic void init() {\n\t\t\tBUTTONS.add(addButton(new GuiButton(0, guiLeft + 10, guiTop + 70, 20, 20, \"<\")));\n\t\t\tBUTTONS.add(addButton(new GuiButton(1, guiLeft + 150, guiTop + 70, 20, 20, \">\")));\n\t\t\tBUTTONS.add(addButton(new GuiButton(2, guiLeft + 37, guiTop + 70, 40, 20, \"Add\")));\n\t\t\tBUTTONS.add(addButton(new GuiButton(3, guiLeft + 83, guiTop + 70, 60, 20, \"Remove\")));\n\n\t\t\tif (itemDisplay == null) {\n\t\t\t\titemDisplay = new ItemDisplay(null, fontRenderer, GuiStatistics.this, null, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, 0, 0, 0, new int[] { 1, 10, 64, 64 }, true);\n\t\t\t}\n\t\t\titemDisplay.reposition(guiLeft + 10, guiTop + 40, xSize - 20, 20, 0, 0);\n\t\t}\n\n\t\t@Override\n\t\tpublic void draw(int mouseX, int mouseY) {\n\t\t\titemDisplay.renderItemArea(zLevel);\n\t\t\titemDisplay.renderPageNumber(right - 40, guiTop + 28);\n\t\t\tif (itemDisplay.getSelectedItem() != null) {\n\t\t\t\tTrackingTask task = getSelectedTask();\n\n\t\t\t\tif (task != null) {\n\t\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 10, guiTop + 99);\n\t\t\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\t\t\tGlStateManager.enableDepth();\n\t\t\t\t\titemRender.renderItemAndEffectIntoGUI(task.item.makeNormalStack(1), guiLeft + 11, guiTop + 100);\n\t\t\t\t\tGlStateManager.disableDepth();\n\t\t\t\t\titemRender.zLevel = 0.0F;\n\t\t\t\t\tmc.fontRenderer.drawString(StringUtils.getWithMaxWidth(task.item.getFriendlyName(), 136, fontRenderer), guiLeft + 32, guiTop + 104, Color.getValue(Color.DARKER_GREY), false);\n\n\t\t\t\t\tint xOrigo = xCenter - 72;\n\t\t\t\t\tint yOrigo = yCenter + 90;\n\t\t\t\t\tGlStateManager.pushMatrix();\n\t\t\t\t\tGlStateManager.translate(xOrigo, yOrigo, 0);\n\n\t\t\t\t\tdrawLine(0, 0, 150, 0, Color.DARKER_GREY);\n\t\t\t\t\tdrawLine(0, 0, 0, -80, Color.DARKER_GREY);\n\n\t\t\t\t\tdrawLine(-4, -90 + 50 + -40, 0, -90 + 50 + -40, Color.DARKER_GREY);\n\n\t\t\t\t\tdrawLine(150, -1, 150, 4, Color.DARKER_GREY);\n\n\t\t\t\t\tlong[] data = getTaskData(task);\n\n\t\t\t\t\tfloat xViewportCenter = 75;\n\t\t\t\t\tfloat yViewportCenter = 40;\n\n\t\t\t\t\tint rightLimit = 2; // we want to draw one more graph part past the right edge\n\t\t\t\t\tfor (int i = 0; i < data.length; i++) {\n\t\t\t\t\t\trightLimit--;\n\t\t\t\t\t\tif (rightLimit == 0) break;\n\n\t\t\t\t\t\tfloat x = i;\n\t\t\t\t\t\tfloat y = data[i];\n\t\t\t\t\t\tfloat prevX = x;\n\t\t\t\t\t\tfloat prevY = y;\n\t\t\t\t\t\tif (i > 0) {\n\t\t\t\t\t\t\tprevX = x - 1;\n\t\t\t\t\t\t\tprevY = data[i - 1];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tx += xViewportOffset;\n\t\t\t\t\t\tx *= xViewportScale;\n\t\t\t\t\t\tx += xViewportCenter;\n\t\t\t\t\t\tprevX += xViewportOffset;\n\t\t\t\t\t\tprevX *= xViewportScale;\n\t\t\t\t\t\tprevX += xViewportCenter;\n\n\t\t\t\t\t\ty -= yViewportOffset;\n\t\t\t\t\t\ty *= yViewportScale;\n\t\t\t\t\t\ty += yViewportCenter;\n\t\t\t\t\t\tprevY -= yViewportOffset;\n\t\t\t\t\t\tprevY *= yViewportScale;\n\t\t\t\t\t\tprevY += yViewportCenter;\n\n\t\t\t\t\t\tif (x <= 150) rightLimit = 2;\n\t\t\t\t\t\tif (x < 0) continue;\n\n\t\t\t\t\t\tif (x <= 150) {\n\t\t\t\t\t\t\tint interval = max(1, (int) (40 / xViewportScale) + 1);\n\t\t\t\t\t\t\tif (i % interval == 0) {\n\t\t\t\t\t\t\t\tString s = formatTime(data.length - i - 1);\n\t\t\t\t\t\t\t\tint w = mc.fontRenderer.getStringWidth(s);\n\t\t\t\t\t\t\t\tdrawLine((int) x, -1, (int) x, 4, Color.DARKER_GREY);\n\t\t\t\t\t\t\t\tmc.fontRenderer.drawString(s, (int) x - w / 2f, 6, Color.DARKER_GREY.getValue(), false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (y > 0 && y < 80) {\n\t\t\t\t\t\t\tdrawLine(-4, (int) -y, 0, (int) -y, Color.DARKER_GREY);\n\t\t\t\t\t\t\tGlStateManager.pushMatrix();\n\t\t\t\t\t\t\tGlStateManager.rotate(90, 0, 0, 1);\n\t\t\t\t\t\t\tString s = data[i] + \"\";\n\t\t\t\t\t\t\tint w = mc.fontRenderer.getStringWidth(s);\n\t\t\t\t\t\t\tmc.fontRenderer.drawString(s, (int) -y - w / 2f, 6, Color.DARKER_GREY.getValue(), false);\n\t\t\t\t\t\t\tGlStateManager.popMatrix();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdrawGraphPart((int) prevX, (int) prevY, (int) x, (int) y);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tGlStateManager.popMatrix();\n\t\t\t}\n\t\t}\n\n\t\t@Nullable\n\t\tprivate TrackingTask getSelectedTask() {\n\t\t\tfor (TrackingTask taskLoop : tile.tasks) {\n\t\t\t\tif (taskLoop.item == itemDisplay.getSelectedItem().getItem()) {\n\t\t\t\t\treturn taskLoop;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tprivate long[] getTaskData(TrackingTask task) {\n\t\t\tlong[] data = new long[task.amountRecorded.length];\n\t\t\tSystem.arraycopy(task.amountRecorded, task.arrayPos, data, 0, task.amountRecorded.length - task.arrayPos);\n\t\t\tSystem.arraycopy(task.amountRecorded, 0, data, task.amountRecorded.length - task.arrayPos, task.arrayPos);\n\t\t\treturn data;\n\t\t}\n\n\t\t@Override\n\t\tpublic void drawForegroundLayer(int mouseX, int mouseY) {\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(PREFIX + \"amount\"), 10, 28, Color.getValue(Color.DARKER_GREY), false);\n\t\t}\n\n\t\t@Override\n\t\tpublic void actionPerformed(GuiButton button) {\n\t\t\tif (button.id == 0) {\n\t\t\t\titemDisplay.prevPage();\n\t\t\t} else if (button.id == 1) {\n\t\t\t\titemDisplay.prevPage();\n\t\t\t} else if (button.id == 2) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestAmountTaskSubGui.class).setTilePos(tile));\n\t\t\t} else if (button.id == 3 && itemDisplay.getSelectedItem() != null) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RemoveAmoundTask.class).setItem(itemDisplay.getSelectedItem().getItem()).setTilePos(tile));\n\t\t\t\tIterator<TrackingTask> iter = tile.tasks.iterator();\n\t\t\t\twhile (iter.hasNext()) {\n\t\t\t\t\tTrackingTask task = iter.next();\n\t\t\t\t\tif (task.item == itemDisplay.getSelectedItem().getItem()) {\n\t\t\t\t\t\titer.remove();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tupdateItemList();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void keyTyped(char c, int i) {\n\t\t\tif (i == Keyboard.KEY_PRIOR) { //PgUp\n\t\t\t\titemDisplay.prevPage();\n\t\t\t} else if (i == Keyboard.KEY_NEXT) { //PgDn\n\t\t\t\titemDisplay.nextPage();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void handleClick(int mouseX, int mouseY, int mouseButton) {\n\t\t\tif (itemDisplay.handleClick(mouseX, mouseY, mouseButton)) {\n\t\t\t\txViewportOffset = max(-1439, min(xViewportOffset, 0));\n\t\t\t\tTrackingTask task = getSelectedTask();\n\t\t\t\tif (task != null) {\n\t\t\t\t\tlong[] data = getTaskData(task);\n\t\t\t\t\tyViewportOffset = data[round(-xViewportOffset)];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tint xOrigo = xCenter - 72;\n\t\t\tint yOrigo = yCenter + 90;\n\t\t\tisDraggingGraph = mouseButton == 0 && mouseX > xOrigo && mouseX < xOrigo + 150 && mouseY < yOrigo && mouseY > yOrigo - 80;\n\t\t\tisDraggingXBar = mouseButton == 0 && mouseX > xOrigo && mouseX < xOrigo + 150 && mouseY < yOrigo + 16 && mouseY > yOrigo + 4;\n\t\t\tisDraggingYBar = mouseButton == 0 && mouseX > xOrigo - 16 && mouseX < xOrigo - 4 && mouseY < yOrigo && mouseY > yOrigo - 80;\n\t\t}\n\n\t\t@Override\n\t\tpublic void checkButtons() {\n\t\t\tfor (GuiButton button : BUTTONS) {\n\t\t\t\tbutton.visible = getActiveTab() == this;\n\t\t\t\tif (button.displayString.equals(\"Remove\")) {\n\t\t\t\t\tbutton.enabled = itemDisplay.getSelectedItem() != null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onMouseDrag(int x, int y, int dx, int dy) {\n\t\t\tif (isDraggingGraph) {\n\t\t\t\txViewportOffset += dx / xViewportScale;\n\t\t\t\tyViewportOffset += dy / yViewportScale;\n\t\t\t} else if (isDraggingXBar) {\n\t\t\t\tfloat mul = (float) pow(1.25, dx / 2f);\n\t\t\t\txViewportScale *= mul;\n\t\t\t} else if (isDraggingYBar) {\n\t\t\t\tfloat mul = (float) pow(1.25, -dy / 2f);\n\t\t\t\tyViewportScale *= mul;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onMouseScroll(int dw) {\n\t\t\tfloat mul = (float) pow(1.25, dw / 60f);\n\t\t\txViewportScale *= mul;\n\t\t\tyViewportScale *= mul;\n\t\t}\n\n\t\tprivate void drawGraphPart(int prevX, int prevY, int x, int y) {\n\t\t\tVec2 left = new Vec2(prevX, prevY);\n\t\t\tVec2 right = new Vec2(x, y);\n\n\t\t\t// bounds check\n\t\t\t{\n\t\t\t\tVec2 min = new Vec2(left.x, min(left.y, right.y));\n\t\t\t\tVec2 max = new Vec2(right.x, max(left.y, right.y));\n\n\t\t\t\tif (!(min.x < 150 && max.x > 0 && min.y < 80 && max.y > 0)) return;\n\t\t\t}\n\n\t\t\t// clamp to the edges of the graph\n\t\t\tright = clampCorner(left, right, Vec2.ORIGIN, true);\n\t\t\tright = clampCorner(left, right, new Vec2(150, 80), false);\n\t\t\tleft = clampCorner(right, left, Vec2.ORIGIN, true);\n\t\t\tleft = clampCorner(right, left, new Vec2(150, 80), false);\n\n\t\t\tdrawLine((int) left.x, (int) -left.y, (int) right.x, (int) -right.y, Color.RED);\n\n\t\t\tint radius = 2;\n\t\t\tif (xViewportScale < 4) radius = 1;\n\n\t\t\tif (prevX >= 0 && prevX <= 150 && prevY >= 0 && prevY <= 80)\n\t\t\t\tdrawRect(prevX - radius + 1, -prevY - radius + 1, prevX + radius, -prevY + radius, Color.BLACK);\n\n\t\t\tif (x >= 0 && x <= 150 && y >= 0 && y <= 80)\n\t\t\t\tdrawRect(x - radius + 1, -y - radius + 1, x + radius, -y + radius, Color.BLACK);\n\t\t}\n\n\t\tprivate Vec2 clampYPlane(Vec2 v, Vec2 toClamp, float x0, boolean greater) {\n\t\t\tif (toClamp.x == x0) return toClamp;\n\t\t\tif (toClamp.x == v.x) return toClamp;\n\n\t\t\tif ((!greater && toClamp.x < x0) || (greater && toClamp.x > x0)) {\n\t\t\t\treturn toClamp;\n\t\t\t}\n\n\t\t\tVec2 dir = toClamp.sub(v);\n\t\t\tdir = dir.div(dir.x); // let dir.x=1 but keep vector's direction\n\t\t\tfloat dist = (x0 - toClamp.x);\n\t\t\treturn toClamp.add(dir.mul(dist));\n\t\t}\n\n\t\t@SuppressWarnings(\"SuspiciousNameCombination\")\n\t\tprivate Vec2 clampXPlane(Vec2 from, Vec2 to, float y0, boolean greater) {\n\t\t\tfinal Vec2 vec2 = clampYPlane(new Vec2(from.y, from.x), new Vec2(to.y, to.x), y0, greater);\n\t\t\treturn new Vec2(vec2.y, vec2.x);\n\t\t}\n\n\t\tprivate Vec2 clampCorner(Vec2 from, Vec2 to, Vec2 corner, boolean greater) {\n\t\t\treturn clampXPlane(from, clampYPlane(from, to, corner.x, greater), corner.y, greater);\n\t\t}\n\n\t\tprivate String formatTime(int minutes) {\n\t\t\tif (minutes == 0) return \"Now\";\n\n\t\t\tint mins = minutes % 60;\n\t\t\tminutes /= 60;\n\t\t\tint hours = minutes;\n\n\t\t\tStringBuilder sb = new StringBuilder();\n\n\t\t\tif (hours > 0) sb.append(hours).append(\"h\");\n\t\t\tif (mins > 0) sb.append(mins).append(\"min\");\n\n\t\t\treturn sb.toString();\n\t\t}\n\n\t\tpublic void updateItemList() {\n\t\t\tList<ItemIdentifierStack> allItems = tile.tasks.stream().map(task -> task.item.makeStack(1))\n\t\t\t\t\t.collect(Collectors.toList());\n\t\t\titemDisplay.setItemList(allItems);\n\t\t}\n\n\t\tpublic void handlePacket(List<ItemIdentifierStack> identList) {\n\t\t\tif (hasSubGui() && getSubGui() instanceof GuiAddTracking) {\n\t\t\t\t((GuiAddTracking) getSubGui()).handlePacket(identList);\n\t\t\t} else if (!hasSubGui()) {\n\t\t\t\tGuiAddTracking sub = new GuiAddTracking(tile);\n\t\t\t\tsetSubGui(sub);\n\t\t\t\tsub.handlePacket(identList);\n\t\t\t}\n\t\t}\n\n\t}\n\n\tprivate class TabCrafting implements StatisticsTab {\n\n\t\tprivate ItemDisplay itemDisplay;\n\n\t\tprivate final List<GuiButton> BUTTONS = new ArrayList<>();\n\n\t\t@Override\n\t\tpublic void init() {\n\t\t\tBUTTONS.add(addButton(new GuiButton(6, guiLeft + 10, guiTop + 40, 160, 20, TextUtil.translate(PREFIX + \"gettasks\"))));\n\t\t\tBUTTONS.add(addButton(new SmallGuiButton(7, guiLeft + 90, guiTop + 65, 10, 10, \"<\")));\n\t\t\tBUTTONS.add(addButton(new SmallGuiButton(8, guiLeft + 160, guiTop + 65, 10, 10, \">\")));\n\n\t\t\tif (itemDisplay == null) {\n\t\t\t\titemDisplay = new ItemDisplay(null, fontRenderer, GuiStatistics.this, null, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, 0, 0, 0, new int[] { 1, 10, 64, 64 }, true);\n\t\t\t\titemDisplay.setItemList(new ArrayList<>());\n\t\t\t}\n\t\t\titemDisplay.reposition(guiLeft + 10, guiTop + 80, xSize - 20, 125, 0, 0);\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void draw(int mouseX, int mouseY) {\n\t\t\titemDisplay.renderItemArea(zLevel);\n\t\t\titemDisplay.renderPageNumber(right - 50, guiTop + 66);\n\t\t}\n\n\t\t@Override\n\t\tpublic void drawForegroundLayer(int mouseX, int mouseY) {\n\t\t\tmc.fontRenderer.drawString(TextUtil.translate(PREFIX + \"crafting\"), 10, 28, Color.getValue(Color.DARKER_GREY), false);\n\t\t\tGuiGraphics.displayItemToolTip(itemDisplay.getToolTip(), GuiStatistics.this, zLevel, guiLeft, guiTop);\n\t\t}\n\n\t\t@Override\n\t\tpublic void actionPerformed(GuiButton button) {\n\t\t\tif (button.id == 6) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestRunningCraftingTasks.class).setTilePos(tile));\n\t\t\t} else if (button.id == 7) {\n\t\t\t\titemDisplay.prevPage();\n\t\t\t} else if (button.id == 8) {\n\t\t\t\titemDisplay.prevPage();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void keyTyped(char c, int i) {\n\t\t\tif (i == Keyboard.KEY_PRIOR) { //PgUp\n\t\t\t\titemDisplay.prevPage();\n\t\t\t} else if (i == Keyboard.KEY_NEXT) { //PgDn\n\t\t\t\titemDisplay.nextPage();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void handleClick(int mouseX, int mouseY, int mouseButton) {\n\t\t\titemDisplay.handleClick(mouseX, mouseY, mouseButton);\n\t\t}\n\n\t\t@Override\n\t\tpublic void checkButtons() {\n\t\t\tfor (GuiButton button : BUTTONS) {\n\t\t\t\tbutton.visible = getActiveTab() == this;\n\t\t\t}\n\t\t}\n\n\t\tpublic void handlePacket(List<ItemIdentifierStack> identList) {\n\t\t\titemDisplay.setItemList(identList);\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/GuiSupplierPipe.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui;\n\nimport java.io.IOException;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.modules.ModuleActiveSupplier.PatternMode;\nimport logisticspipes.modules.ModuleActiveSupplier.SupplyMode;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate;\nimport logisticspipes.network.packets.pipe.SlotFinderOpenGuiPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.EnumProperty;\nimport network.rs485.logisticspipes.property.IntListProperty;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay;\nimport network.rs485.logisticspipes.property.layer.ValuePropertyOverlay;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiSupplierPipe extends LogisticsBaseGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.supplierpipe.\";\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/supplier.png\");\n\tprivate final boolean hasPatternUpgrade;\n\tprivate final PropertyLayer propertyLayer;\n\tprivate final ModuleActiveSupplier supplierModule;\n\tprivate final PropertyOverlay<List<Integer>, IntListProperty> slotAssignmentPatternOverlay;\n\tprivate final ValuePropertyOverlay<SupplyMode, EnumProperty<SupplyMode>> requestModeOverlay;\n\tprivate final ValuePropertyOverlay<PatternMode, EnumProperty<PatternMode>> patternModeOverlay;\n\tprivate ValuePropertyOverlay<Boolean, BooleanProperty> limitedPropertyOverlay;\n\n\tpublic GuiSupplierPipe(IInventory playerInventory, IInventory dummyInventory, ModuleActiveSupplier module,\n\t\t\tBoolean flag, int[] slots) {\n\t\tsuper(null);\n\t\thasPatternUpgrade = flag;\n\t\tsupplierModule = module;\n\n\t\tpropertyLayer = new PropertyLayer(supplierModule.getProperties());\n\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, dummyInventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\n\t\tif (hasPatternUpgrade) {\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tdummy.addDummySlot(i, 18 + i * 18, 20);\n\t\t\t}\n\t\t} else {\n\t\t\tint xOffset = 72;\n\t\t\tint yOffset = 18;\n\t\t\tfor (int row = 0; row < 3; row++) {\n\t\t\t\tfor (int column = 0; column < 3; column++) {\n\t\t\t\t\tdummy.addDummySlot(column + row * 3, xOffset + column * 18, yOffset + row * 18);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinventorySlots = dummy;\n\t\tslotAssignmentPatternOverlay = propertyLayer.overlay(supplierModule.slotAssignmentPattern);\n\t\tslotAssignmentPatternOverlay.write((p) -> p.replaceContent(slots));\n\t\txSize = 194;\n\t\tySize = 186;\n\t\tpatternModeOverlay = propertyLayer\n\t\t\t\t.overlay(supplierModule.patternMode);\n\t\trequestModeOverlay = propertyLayer.overlay(supplierModule.requestMode);\n\t\tlimitedPropertyOverlay = propertyLayer.overlay(supplierModule.isLimited);\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t\tpropertyLayer.unregister();\n\t\tif (this.mc.player != null && !propertyLayer.getProperties().isEmpty()) {\n\t\t\t// send update to server, when there are changed properties\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(supplierModule));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tString name;\n\t\tif (hasPatternUpgrade) {\n\t\t\tname = TextUtil.translate(GuiSupplierPipe.PREFIX + \"TargetInvPattern\");\n\t\t} else {\n\t\t\tname = TextUtil.translate(GuiSupplierPipe.PREFIX + \"TargetInv\");\n\t\t}\n\t\tmc.fontRenderer.drawString(name, xSize / 2 - mc.fontRenderer.getStringWidth(name) / 2, 6, 0x404040);\n\t\tmc.fontRenderer\n\t\t\t\t.drawString(TextUtil.translate(GuiSupplierPipe.PREFIX + \"Inventory\"), 18, ySize - 102, 0x404040);\n\t\tmc.fontRenderer\n\t\t\t\t.drawString(TextUtil.translate(GuiSupplierPipe.PREFIX + \"RequestMode\"), xSize - 140, ySize - 112,\n\t\t\t\t\t\t0x404040);\n\t\tif (hasPatternUpgrade) {\n\t\t\tslotAssignmentPatternOverlay.read((slotAssignments) -> {\n\t\t\t\tfor (int i = 0; i < slotAssignments.size(); i++) {\n\t\t\t\t\tmc.fontRenderer.drawString(Integer.toString(slotAssignments.get(i)), 22 + i * 18, 55, 0x404040);\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tif (!hasPatternUpgrade) {\n\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t\tmc.renderEngine.bindTexture(GuiSupplierPipe.TEXTURE);\n\t\t\tint j = guiLeft;\n\t\t\tint k = guiTop;\n\t\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t\t} else {\n\t\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\t\tGL11.glTranslated(guiLeft, guiTop, 0);\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, 17 + i * 18, 19);\n\t\t\t\tSlot slot = inventorySlots.getSlot(36 + i);\n\t\t\t\tif (slot.getHasStack() && slot.getStack().getCount() > 64) {\n\t\t\t\t\tdrawRect(18 + i * 18, 20, 34 + i * 18, 36, Color.RED);\n\t\t\t\t}\n\t\t\t}\n\t\t\tGuiGraphics.drawPlayerInventoryBackground(mc, 18, 97);\n\t\t\tGL11.glTranslated(-guiLeft, -guiTop, 0);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, width / 2 + 35, height / 2 - 25, 50, 20, getModeText()));\n\t\tif (hasPatternUpgrade) {\n\t\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 5, guiTop + 68, 45, 10, getLimitationText()));\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tbuttonList.add(new SmallGuiButton(i + 2, guiLeft + 18 + i * 18, guiTop + 40, 17, 10, \"Set\"));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) {\n\t\t\tif (hasPatternUpgrade) {\n\t\t\t\tfinal PatternMode newMode = patternModeOverlay.write(EnumProperty::next);\n\t\t\t\tbuttonList.get(0).displayString = newMode.toString();\n\t\t\t} else {\n\t\t\t\tfinal SupplyMode newMode = requestModeOverlay.write(EnumProperty::next);\n\t\t\t\tbuttonList.get(0).displayString = newMode.toString();\n\t\t\t}\n\t\t} else if (hasPatternUpgrade) {\n\t\t\tif (guibutton.id == 1) {\n\t\t\t\tlimitedPropertyOverlay.write(BooleanProperty::toggle);\n\t\t\t\tbuttonList.get(1).displayString = getLimitationText();\n\t\t\t} else if (guibutton.id >= 2 && guibutton.id <= 10) {\n\t\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\t\tPacketHandler.getPacket(SlotFinderOpenGuiPacket.class).setSlot(guibutton.id - 2)\n\t\t\t\t\t\t\t\t.setModulePos(supplierModule));\n\t\t\t}\n\t\t}\n\t\tsuper.actionPerformed(guibutton);\n\t}\n\n\tpublic void refreshMode() {\n\t\tbuttonList.get(0).displayString = getModeText();\n\t\tif (hasPatternUpgrade) {\n\t\t\tlimitedPropertyOverlay = propertyLayer.overlay(supplierModule.isLimited);\n\t\t\tbuttonList.get(1).displayString = getLimitationText();\n\t\t}\n\t}\n\n\t@Nonnull\n\tprivate String getLimitationText() {\n\t\treturn limitedPropertyOverlay.get() ? \"Limited\" : \"Unlimited\";\n\t}\n\n\tprivate String getModeText() {\n\t\treturn (hasPatternUpgrade ? patternModeOverlay : requestModeOverlay).get().toString();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/ItemAmountSignCreationGui.java",
    "content": "package logisticspipes.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.signs.ItemAmountPipeSign;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class ItemAmountSignCreationGui extends LogisticsBaseGuiScreen {\n\n\tpublic ItemAmountSignCreationGui(EntityPlayer player, CoreRoutedPipe pipe, EnumFacing dir) {\n\t\tsuper(180, 125, 0, 0);\n\t\tItemAmountPipeSign sign = ((ItemAmountPipeSign) pipe.getPipeSign(dir));\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, sign.itemTypeInv);\n\t\tdummy.addDummySlot(0, 10, 13);\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 40);\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int i, int j) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 40);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 9, guiTop + 12);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/BasicHUDGui.java",
    "content": "package logisticspipes.gui.hud;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\n\npublic abstract class BasicHUDGui implements IHeadUpDisplayRenderer {\n\n\tprotected final List<IHUDButton> buttons = new ArrayList<>();\n\n\tprotected void addButton(IHUDButton button) {\n\t\tbuttons.add(button);\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double d, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tfor (IHUDButton button : buttons) {\n\t\t\tGL11.glPushMatrix();\n\t\t\tbutton.renderAlways(shifted);\n\t\t\tif (button.shouldRenderButton()) {\n\t\t\t\tbutton.renderButton(button.isFocused(), button.isblockFocused(), shifted);\n\t\t\t}\n\t\t\tGL11.glPopMatrix();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleCursor(int x, int y) {\n\t\tGL11.glPushMatrix();\n\t\tfor (IHUDButton button : buttons) {\n\t\t\tif (!button.buttonEnabled() || !button.shouldRenderButton()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((button.getX() - 1 < x && x < (button.getX() + button.sizeX() + 1)) && (button.getY() - 1 < y && y < (button.getY() + button.sizeY() + 1))) {\n\t\t\t\tif (!button.isFocused() && !button.isblockFocused()) {\n\t\t\t\t\tbutton.setFocused();\n\t\t\t\t} else if (button.focusedTime() > 400 && !button.isblockFocused()) {\n\t\t\t\t\tbutton.clicked();\n\t\t\t\t\tbutton.blockFocused();\n\t\t\t\t}\n\t\t\t} else if (button.isFocused() || button.isblockFocused()) {\n\t\t\t\tbutton.clearFocused();\n\t\t\t}\n\t\t}\n\t\tGL11.glPopMatrix();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/GuiHUDSettings.java",
    "content": "package logisticspipes.gui.hud;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.SneakyThrows;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.hud.HUDConfig;\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.hud.HUDSettingsPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class GuiHUDSettings extends LogisticsBaseGuiScreen {\n\n\tprivate int slot;\n\tprivate EntityPlayer player;\n\n\tpublic GuiHUDSettings(EntityPlayer player, int slot) {\n\t\tsuper(180, 160, 0, 0);\n\t\tthis.slot = slot;\n\t\tthis.player = player;\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, null);\n\t\tdummy.addRestrictedHotbarForPlayerInventory(10, 134);\n\t\tdummy.addRestrictedArmorForPlayerInventory(10, 65);\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\t@SneakyThrows(IOException.class)\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tif (!player.inventory.getStackInSlot(slot).isEmpty()) {\n\t\t\tIHUDConfig config = new HUDConfig(player.inventory.getStackInSlot(slot));\n\t\t\tbuttonList.add(new GuiCheckBox(0, guiLeft + 30, guiTop + 10, 12, 12, config.isChassisHUD()));\n\t\t\tbuttonList.add(new GuiCheckBox(1, guiLeft + 30, guiTop + 30, 12, 12, config.isHUDCrafting()));\n\t\t\tbuttonList.add(new GuiCheckBox(2, guiLeft + 30, guiTop + 50, 12, 12, config.isHUDInvSysCon()));\n\t\t\tbuttonList.add(new GuiCheckBox(3, guiLeft + 30, guiTop + 70, 12, 12, config.isHUDPowerLevel()));\n\t\t\tbuttonList.add(new GuiCheckBox(4, guiLeft + 30, guiTop + 90, 12, 12, config.isHUDProvider()));\n\t\t\tbuttonList.add(new GuiCheckBox(5, guiLeft + 30, guiTop + 110, 12, 12, config.isHUDSatellite()));\n\t\t} else {\n\t\t\tcloseGui();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tif (buttonList.get(button.id) instanceof GuiCheckBox) {\n\t\t\t((GuiCheckBox) buttonList.get(button.id)).change();\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDSettingsPacket.class).setButtonId(button.id).setState(((GuiCheckBox) buttonList.get(button.id)).getState()).setSlot(slot));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tif (player.inventory.getStackInSlot(slot).isEmpty() || player.inventory.getStackInSlot(slot).getItem() != LPItems.hudGlasses) {\n\t\t\tmc.player.closeScreen();\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tmc.fontRenderer.drawString(\"HUD Chassis Pipe\", guiLeft + 50, guiTop + 13, 0x4c4c4c);\n\t\tmc.fontRenderer.drawString(\"HUD Crafting Pipe\", guiLeft + 50, guiTop + 33, 0x4c4c4c);\n\t\tmc.fontRenderer.drawString(\"HUD InvSysCon Pipe\", guiLeft + 50, guiTop + 53, 0x4c4c4c);\n\t\tmc.fontRenderer.drawString(\"HUD Power Junction\", guiLeft + 50, guiTop + 73, 0x4c4c4c);\n\t\tmc.fontRenderer.drawString(\"HUD Provider Pipe\", guiLeft + 50, guiTop + 93, 0x4c4c4c);\n\t\tmc.fontRenderer.drawString(\"HUD Satellite Pipe\", guiLeft + 50, guiTop + 113, 0x4c4c4c);\n\t\tGuiGraphics.drawPlayerHotbarBackground(mc, guiLeft + 10, guiTop + 134);\n\t\tGuiGraphics.drawPlayerArmorBackground(mc, guiLeft + 10, guiTop + 65);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/HUDCrafting.java",
    "content": "package logisticspipes.gui.hud;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HUDCrafting extends BasicHUDGui {\n\n\tprivate final PipeItemsCraftingLogistics pipe;\n\n\tpublic HUDCrafting(PipeItemsCraftingLogistics pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double d, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 64);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t}\n\t\tif (pipe.displayList.size() > 0) {\n\t\t\tGuiGraphics.drawGuiBackGround(mc, -50, -28, 50, 30, 0, false);\n\t\t} else {\n\t\t\tGuiGraphics.drawGuiBackGround(mc, -30, -22, 30, 25, 0, false);\n\t\t}\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t}\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.005F);\n\t\tGL11.glScalef(1.5F, 1.5F, 0.0001F);\n\n\t\tif (pipe.displayList.size() > 0) {\n\t\t\tString message = \"Result:\";\n\t\t\tmc.fontRenderer.drawString(message, -28, -10, 0);\n\t\t\tmessage = \"Todo:\";\n\t\t\tmc.fontRenderer.drawString(message, -28, 5, 0);\n\t\t} else {\n\t\t\tString message = \"Result:\";\n\t\t\tmc.fontRenderer.drawString(message, -16, -10, 0);\n\t\t}\n\t\tGL11.glScalef(0.8F, 0.8F, -1F);\n\t\tList<ItemIdentifierStack> list = new ArrayList<>();\n\t\tList<ItemIdentifierStack> craftables = pipe.getCraftedItems();\n\t\tif (craftables != null && craftables.size() > 0) {\n\t\t\t//TODO: handle multiple craftables.\n\t\t\tlist.add(craftables.get(0));\n\t\t}\n\t\tif (pipe.displayList.size() > 0) {\n\t\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(list, null, 0, 11, -18, 1, 1, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(pipe.displayList, null, 0, 13, 3, 1, 1, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t\t} else {\n\t\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(list, null, 0, -9, -1, 1, 1, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\treturn config.isHUDCrafting() && ((!pipe.hasCraftingSign() && pipe.getCraftedItems() != null) || pipe.displayList.size() > 0);\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\tif (pipe.displayList.size() > 0) {\n\t\t\treturn -50 < x && x < 50 && -28 < y && y < 30;\n\t\t} else {\n\t\t\treturn -30 < x && x < 30 && -22 < y && y < 25;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/HUDInvSysConnector.java",
    "content": "package logisticspipes.gui.hud;\n\nimport net.minecraft.client.Minecraft;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HUDInvSysConnector extends BasicHUDGui {\n\n\tprivate PipeItemsInvSysConnector pipe;\n\tprivate long display = System.currentTimeMillis();\n\n\tpublic HUDInvSysConnector(PipeItemsInvSysConnector pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double distance, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 64);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, -50, -50, 50, 50, 0, false);\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t}\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.005F);\n\t\tGL11.glScalef(1.5F, 1.5F, 0.0001F);\n\t\tString message = \"Expected:\";\n\t\tmc.fontRenderer.drawString(message, -28, -25, 0);\n\t\tGL11.glScalef(0.8F, 0.8F, -1F);\n\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(pipe.displayList, null, 0, -37, -18, 3, 9, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\tif (!config.isHUDInvSysCon()) {\n\t\t\treturn false;\n\t\t}\n\t\tif (display > System.currentTimeMillis()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (pipe.displayList.size() > 0) {\n\t\t\tdisplay = System.currentTimeMillis() + (2 * 1000);\n\t\t}\n\t\treturn pipe.displayList.size() > 0;\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\treturn (-50 < x && x < 50 && -50 < y && y < 50);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/HUDPowerLevel.java",
    "content": "package logisticspipes.gui.hud;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IPowerLevelDisplay;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.string.StringUtils;\n\npublic class HUDPowerLevel extends BasicHUDGui implements IHeadUpDisplayRenderer {\n\n\tprivate final IPowerLevelDisplay junction;\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/power_junction.png\");\n\n\tpublic HUDPowerLevel(IPowerLevelDisplay junction) {\n\t\tthis.junction = junction;\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double distance, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 32);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 32);\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, -60, -40, 60, 40, 0, false);\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t}\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.0005F);\n\t\tsuper.renderHeadUpDisplay(distance, day, shifted, mc, config);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.0005F);\n\t\tmc.renderEngine.bindTexture(HUDPowerLevel.TEXTURE);\n\t\tdrawTexturedModalRect(-50, -30, 9, 10, 7, 61);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.0005F);\n\t\tint level = 100 - junction.getChargeState();\n\t\tdrawTexturedModalRect(-49, -29 + (level * 59 / 100), 176, level * 59 / 100, 5, 59 - (level * 59 / 100));\n\t\tmc.fontRenderer.drawString(\"Stored Energy:\", -30, -15, 0x404040);\n\t\tmc.fontRenderer.drawString(StringUtils.getStringWithSpacesFromInteger(junction.getDisplayPowerLevel()) + \" \" + junction.getBrand(), -30, -5, 0x404040);\n\t\tmc.fontRenderer.drawString(\"/ \" + StringUtils.getStringWithSpacesFromInteger(junction.getMaxStorage()) + \" \" + junction.getBrand(), -30, 5, 0x404040);\n\t\tGL11.glTranslatef(0.0F, 0.0F, 0.0015F);\n\t}\n\n\tpublic void drawTexturedModalRect(int par1, int par2, int par3, int par4, int par5, int par6) {\n\t\tfloat var7 = 0.00390625F;\n\t\tfloat var8 = 0.00390625F;\n\t\tTessellator var9 = Tessellator.getInstance();\n\t\tBufferBuilder buffer = var9.getBuffer();\n\t\tbuffer.begin(7, DefaultVertexFormats.POSITION_TEX);\n\t\tbuffer.pos(par1 + 0, par2 + par6, 0).tex((par3 + 0) * var7, (par4 + par6) * var8).endVertex();\n\t\tbuffer.pos(par1 + par5, par2 + par6, 0).tex((par3 + par5) * var7, (par4 + par6) * var8).endVertex();\n\t\tbuffer.pos(par1 + par5, par2 + 0, 0).tex((par3 + par5) * var7, (par4 + 0) * var8).endVertex();\n\t\tbuffer.pos(par1 + 0, par2 + 0, 0).tex((par3 + 0) * var7, (par4 + 0) * var8).endVertex();\n\t\tvar9.draw();\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\treturn !junction.isHUDInvalid() && config.isHUDPowerLevel();\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\treturn -60 < x && x < 60 && -40 < y && y < 40;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/HUDProvider.java",
    "content": "package logisticspipes.gui.hud;\n\nimport net.minecraft.client.Minecraft;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.pipes.PipeItemsProviderLogistics;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HUDProvider extends BasicHUDGui {\n\n\tprivate final PipeItemsProviderLogistics pipe;\n\tprivate int page = 0;\n\tprivate int pageB = 0;\n\n\tpublic HUDProvider(final PipeItemsProviderLogistics pipe) {\n\t\tthis.pipe = pipe;\n\t\taddButton(new BasicHUDButton(\"<\", -2, -50, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tif (page > 0) {\n\t\t\t\t\tpage--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page > 0;\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\">\", 37, -50, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tif (page + 1 < getMaxPage()) {\n\t\t\t\t\tpage++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page + 1 < getMaxPage();\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\"<\", -2, 21, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tif (pageB > 0) {\n\t\t\t\t\tpageB--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn pageB > 0;\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\">\", 37, 21, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tif (pageB + 1 < getMaxPageOrderer()) {\n\t\t\t\t\tpageB++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn pageB + 1 < getMaxPageOrderer();\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double distance, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 64);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, -50, -55, 50, 55, 0, false);\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t}\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.01F);\n\t\tsuper.renderHeadUpDisplay(distance, day, shifted, mc, config);\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.005F);\n\t\tfloat scaleX = 1.125F;\n\t\tfloat scaleY = 1.125F;\n\t\tfloat scaleZ = -0.0001F;\n\t\tGL11.glScalef(scaleX, scaleY, scaleZ);\n\t\tItemStackRenderer itemStackRenderer = new ItemStackRenderer(0, 0, 0.0F, shifted, true);\n\t\titemStackRenderer.setDisplayAmount(DisplayAmount.ALWAYS);\n\t\titemStackRenderer.setScaleX(scaleX).setScaleY(scaleY).setScaleZ(scaleZ);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(pipe.getDisplayList(), null, page, -36, -37, 4, 12, 18, 18, itemStackRenderer);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(pipe.itemListOrderer, null, pageB, -36, 23, 4, 4, 18, 18, itemStackRenderer);\n\t\tGL11.glScalef(0.875F, 0.875F, -1F);\n\t\tString message = String.format(\"(%d/%d)\", page + 1, getMaxPage());\n\t\tmc.fontRenderer.drawString(message, 9, -50, 0);\n\t\tmessage = String.format(\"(%d/%d)\", pageB + 1, getMaxPageOrderer());\n\t\tmc.fontRenderer.drawString(message, 9, 23, 0);\n\t}\n\n\tpublic int getMaxPage() {\n\t\tint ret = pipe.getDisplayList().size() / 12;\n\t\tif (pipe.getDisplayList().size() % 12 != 0 || ret == 0) {\n\t\t\tret++;\n\t\t}\n\t\treturn ret;\n\t}\n\n\tpublic int getMaxPageOrderer() {\n\t\tint ret = pipe.itemListOrderer.size() / 4;\n\t\tif (pipe.itemListOrderer.size() % 4 != 0 || ret == 0) {\n\t\t\tret++;\n\t\t}\n\t\treturn ret;\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\treturn pipe.getDisplayList().size() > 0 && config.isHUDProvider();\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\treturn -50 < x && x < 50 && -55 < y && y < 55;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/HUDSatellite.java",
    "content": "package logisticspipes.gui.hud;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\nimport network.rs485.logisticspipes.SatellitePipe;\n\npublic class HUDSatellite extends BasicHUDGui {\n\n\t@Nonnull\n\tprivate final SatellitePipe pipe;\n\tprivate int page;\n\n\tpublic HUDSatellite(@Nonnull SatellitePipe pipe) {\n\t\tthis.pipe = pipe;\n\t\taddButton(new BasicHUDButton(\"<\", -2, -40, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tif (page > 0) {\n\t\t\t\t\tpage--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn HUDSatellite.this.pipe.getItemList().size() > 0;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page > 0;\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\">\", 37, -40, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tif (page + 1 < getMaxPage()) {\n\t\t\t\t\tpage++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn HUDSatellite.this.pipe.getItemList().size() > 0;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page + 1 < getMaxPage();\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double distance, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (pipe.getItemList().size() > 0) {\n\t\t\tif (day) {\n\t\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 64);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t\t}\n\t\t\tGuiGraphics.drawGuiBackGround(mc, -50, -50, 50, 50, 0, false);\n\t\t\tif (day) {\n\t\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t\t}\n\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.01F);\n\t\t\tsuper.renderHeadUpDisplay(distance, day, shifted, mc, config);\n\n\t\t\tString message;\n\t\t\tmessage = pipe.getSatellitePipeName();\n\t\t\tif (mc.fontRenderer.getStringWidth(message) > 40) {\n\t\t\t\tGL11.glScalef(0.45F, 0.45F, 0.0001F);\n\t\t\t\tmc.fontRenderer.drawString(message, -100, -85, 0);\n\t\t\t\tGL11.glScalef(1 / 0.45F, 1 / 0.45F, 1);\n\t\t\t} else {\n\t\t\t\tGL11.glScalef(1.0F, 1.0F, 0.0001F);\n\t\t\t\tmc.fontRenderer.drawString(message, -42, -40, 0);\n\t\t\t}\n\t\t\tGL11.glScalef(1.5F, 1.5F, 1);\n\t\t\tGL11.glScalef(0.8F, 0.8F, -1F);\n\t\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(pipe.getItemList(), null, page, -35, -20, 4, 12, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t\t\tGL11.glScalef(0.8F, 0.8F, -1F);\n\t\t\tmessage = String.format(\"(%d/%d)\", page + 1, getMaxPage());\n\t\t\tmc.fontRenderer.drawString(message, 9, -41, 0);\n\t\t} else {\n\t\t\tif (day) {\n\t\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 64);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t\t}\n\t\t\tGuiGraphics.drawGuiBackGround(mc, -50, -15, 50, 20, 0, false);\n\t\t\tif (day) {\n\t\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t\t}\n\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.01F);\n\t\t\tsuper.renderHeadUpDisplay(distance, day, shifted, mc, config);\n\n\t\t\tGL11.glScalef(1F, 1F, 0.0001F);\n\t\t\tString message;\n\t\t\tmessage = pipe.getSatellitePipeName();\n\t\t\tmc.fontRenderer.drawString(message, -(mc.fontRenderer.getStringWidth(message) / 2), -2, 0);\n\t\t}\n\t}\n\n\tpublic int getMaxPage() {\n\t\tint ret = pipe.getItemList().size() / 12;\n\t\tif (pipe.getItemList().size() % 12 != 0 || ret == 0) {\n\t\t\tret++;\n\t\t}\n\t\treturn ret;\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\treturn config.isHUDSatellite();\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\tif (pipe.getItemList().size() > 0) {\n\t\t\treturn -50 < x && x < 50 && -50 < y && y < 50;\n\t\t} else {\n\t\t\treturn -50 < x && x < 50 && -15 < y && y < 20;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/HudChassisPipe.java",
    "content": "package logisticspipes.gui.hud;\n\nimport net.minecraft.client.Minecraft;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HudChassisPipe extends BasicHUDGui {\n\n\tprivate final PipeLogisticsChassis pipe;\n\tprivate final ItemIdentifierInventory moduleInventory;\n\n\tprivate int selected = -1;\n\tprivate int modulePage = 0;\n\n\tprivate int xCursor;\n\tprivate int yCursor;\n\n\tpublic HudChassisPipe(PipeLogisticsChassis pipeLogisticsChassis, ItemIdentifierInventory _moduleInventory) {\n\t\tpipe = pipeLogisticsChassis;\n\t\tmoduleInventory = _moduleInventory;\n\t\tfor (int i = 0; i < pipe.getChassisSize(); i++) {\n\t\t\taddButton(new ItemButton(moduleInventory, i, -45, -35 + ((i % 3) * 27), 20, 25));\n\t\t}\n\n\t\taddButton(new BasicHUDButton(\"<\", -45, -45, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn !isSlotSelected();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tmodulePage--;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn modulePage > 0;\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\">\", -33, -45, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn !isSlotSelected();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tmodulePage++;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn modulePage < ((pipe.getChassisSize() - 1) / 3);\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\"x\", 37, -45, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn isSlotSelected();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tresetSelection();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double distance, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 64);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, -50, -50, 50, 50, 0, false);\n\t\tif (day) {\n\t\t\tGL11.glColor4b((byte) 64, (byte) 64, (byte) 64, (byte) 127);\n\t\t} else {\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t}\n\t\tGL11.glTranslatef(0.0F, 0.0F, (float) (-0.00005F * distance));\n\t\tsuper.renderHeadUpDisplay(distance, day, shifted, mc, config);\n\t\tif (selected != -1) {\n\t\t\tLogisticsModule selectedmodule = pipe.getSubModule(selected);\n\t\t\tif (selectedmodule == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t\tGuiGraphics.drawGuiBackGround(mc, -23, -35, 45, 45, 0, false);\n\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\n\t\t\tif (selectedmodule instanceof IHUDModuleHandler && ((IHUDModuleHandler) selectedmodule).getHUDRenderer() != null) {\n\t\t\t\tGL11.glTranslatef(11.0F, 5.0F, (float) (-0.00005F * distance));\n\t\t\t\t((IHUDModuleHandler) selectedmodule).getHUDRenderer().renderContent(shifted);\n\t\t\t\tif (((IHUDModuleHandler) selectedmodule).getHUDRenderer().getButtons() != null) {\n\t\t\t\t\tfor (IHUDButton button : ((IHUDModuleHandler) selectedmodule).getHUDRenderer().getButtons()) {\n\t\t\t\t\t\tbutton.renderAlways(shifted);\n\t\t\t\t\t\tif (button.shouldRenderButton()) {\n\t\t\t\t\t\t\tbutton.renderButton(button.isFocused(), button.isblockFocused(), shifted);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!button.buttonEnabled() || !button.shouldRenderButton()) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ((button.getX() - 1 < (xCursor - 11) && (xCursor - 11) < (button.getX() + button.sizeX() + 1)) && (button.getY() - 1 < (yCursor - 5) && (yCursor - 5) < (button.getY() + button.sizeY() + 1))) {\n\t\t\t\t\t\t\tif (!button.isFocused() && !button.isblockFocused()) {\n\t\t\t\t\t\t\t\tbutton.setFocused();\n\t\t\t\t\t\t\t} else if (button.focusedTime() > 400 && !button.isblockFocused()) {\n\t\t\t\t\t\t\t\tbutton.clicked();\n\t\t\t\t\t\t\t\tbutton.blockFocused();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (button.isFocused() || button.isblockFocused()) {\n\t\t\t\t\t\t\tbutton.clearFocused();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tGL11.glTranslatef(-11.0F, -5.0F, (float) (0.00005F * distance));\n\t\t\t} else {\n\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, (float) (-0.00005F * distance));\n\t\t\t\tmc.fontRenderer.drawString(\"Nothing\", -5, -15, 0);\n\t\t\t\tmc.fontRenderer.drawString(\"to\", 9, -5, 0);\n\t\t\t\tmc.fontRenderer.drawString(\"display\", -5, 5, 0);\n\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, (float) (0.00005F * distance));\n\t\t\t}\n\t\t} else {\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, (float) (-0.005F * distance));\n\t\t\tGL11.glScalef(1.5F, 1.5F, 0.0001F);\n\t\t\tGL11.glScalef(0.8F, 0.8F, -1F);\n\t\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(pipe.displayList, null, 0, -15, -35, 3, 12, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t\t}\n\t\tGL11.glTranslatef(0.0F, 0.0F, (float) (0.00005F * distance));\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\tif (!config.isChassisHUD()) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (int i = 0; i < moduleInventory.getSizeInventory(); i++) {\n\t\t\tif (moduleInventory.getIDStackInSlot(i) != null) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\treturn -50 < x && x < 50 && -50 < y && y < 50;\n\t}\n\n\t@Override\n\tpublic void handleCursor(int x, int y) {\n\t\tsuper.handleCursor(x, y);\n\t\txCursor = x;\n\t\tyCursor = y;\n\t}\n\n\tprivate void moduleClicked(int number) {\n\t\tselected = number;\n\t\tif (selected != -1) {\n\t\t\tLogisticsModule selectedmodule = pipe.getSubModule(selected);\n\t\t\tif (selectedmodule instanceof IHUDModuleHandler) {\n\t\t\t\t((IHUDModuleHandler) selectedmodule).startHUDWatching();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void resetSelection() {\n\t\tif (selected != -1) {\n\t\t\tLogisticsModule selectedmodule = pipe.getSubModule(selected);\n\t\t\tif (selectedmodule instanceof IHUDModuleHandler) {\n\t\t\t\t((IHUDModuleHandler) selectedmodule).stopHUDWatching();\n\t\t\t}\n\t\t}\n\t\tselected = -1;\n\t}\n\n\tprivate boolean isSlotSelected() {\n\t\treturn selected != -1;\n\t}\n\n\tprivate boolean isSlotSelected(int number) {\n\t\treturn selected == number;\n\t}\n\n\tprivate boolean shouldDisplayButton(int number) {\n\t\treturn modulePage * 3 <= number && number < (modulePage + 1) * 3;\n\t}\n\n\tpublic void stopWatching() {\n\t\tresetSelection();\n\t}\n\n\tprivate class ItemButton extends BasicHUDButton {\n\n\t\tprivate ItemIdentifierInventory inv;\n\t\tprivate int position;\n\n\t\tpublic ItemButton(ItemIdentifierInventory inv, int position, int x, int y, int width, int height) {\n\t\t\tsuper(\"item.\" + position, x, y, width, height);\n\t\t\tthis.inv = inv;\n\t\t\tthis.position = position;\n\t\t}\n\n\t\t@Override\n\t\tpublic void clicked() {\n\t\t\tmoduleClicked(position);\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderButton(boolean hover, boolean clicked, boolean shifted) {\n\t\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\t\tif (shifted || hover || isSlotSelected(position)) {\n\t\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1F);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 0.5F);\n\t\t\t}\n\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.001F);\n\t\t\tGL11.glScaled(0.5D, 0.5D, 1.0D);\n\t\t\tif (isSlotSelected(position)) {\n\t\t\t\tGuiGraphics.drawGuiBackGround(mc, posX * 2, posY * 2, (posX + sizeX) * 2 + 19, (posY + sizeY) * 2, 0, false, true, true, true, false);\n\t\t\t} else {\n\t\t\t\tGuiGraphics.drawGuiBackGround(mc, posX * 2, posY * 2, (posX + sizeX) * 2, (posY + sizeY) * 2, 0, false);\n\t\t\t}\n\t\t\tGL11.glScaled(2.0D, 2.0D, 1.0D);\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, 0.001F);\n\n\t\t\tItemIdentifierStack module = inv.getIDStackInSlot(position);\n\n\t\t\tif (module != null) {\n\t\t\t\tboolean renderInColor = buttonEnabled() || isSlotSelected(position);\n\t\t\t\tItemStackRenderer itemStackRenderer = new ItemStackRenderer(posX + ((sizeX - 16) / 2), posY + ((sizeY - 16) / 2), -0.002F, shifted, renderInColor);\n\t\t\t\titemStackRenderer.setItemIdentStack(module).setDisplayAmount(DisplayAmount.NEVER);\n\n\t\t\t\titemStackRenderer.renderInGui();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderAlways(boolean shifted) {\n\t\t\tif (inv.getIDStackInSlot(position) == null && shouldDisplayButton(position)) {\n\t\t\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\t\t\tif (shifted) {\n\t\t\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t\t\t} else {\n\t\t\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 0.3F);\n\t\t\t\t}\n\t\t\t\tGL11.glScaled(0.5D, 0.5D, 1.0D);\n\t\t\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\t\t\tGuiGraphics.drawGuiBackGround(mc, posX * 2, posY * 2, (posX + sizeX) * 2, (posY + sizeY) * 2, 0, false);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean shouldRenderButton() {\n\t\t\treturn inv.getIDStackInSlot(position) != null && shouldDisplayButton(position);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean buttonEnabled() {\n\t\t\treturn !isSlotSelected();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/modules/HUDAdvancedExtractor.java",
    "content": "package logisticspipes.gui.hud.modules;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\n\npublic class HUDAdvancedExtractor implements IHUDModuleRenderer {\n\n\tprivate final List<IHUDButton> buttons = new ArrayList<>();\n\tprivate final AsyncAdvancedExtractor module;\n\tprivate int selected = 0;\n\n\tpublic HUDAdvancedExtractor(AsyncAdvancedExtractor moduleAdvancedExtractor) {\n\t\tmodule = moduleAdvancedExtractor;\n\t\tbuttons.add(new TabButton(\"Side\", 0, -30, -50, 25, 10));\n\t\tbuttons.add(new TabButton(\"Inv\", 1, -5, -50, 25, 10));\n\t}\n\n\t@Override\n\tpublic void renderContent(boolean shifted) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tif (selected == 0) {\n\t\t\tEnumFacing d = module.getSneakyDirection();\n\t\t\tmc.fontRenderer.drawString(\"Extract\", -22, -22, 0);\n\t\t\tmc.fontRenderer.drawString(\"from:\", -22, -9, 0);\n\t\t\tmc.fontRenderer.drawString(((d == null) ? \"DEFAULT\" : d.name()), -22, 18, 0);\n\t\t} else {\n\t\t\tGL11.glScalef(1.0F, 1.0F, -0.00001F);\n\t\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(\n\t\t\t\t\tItemIdentifierStack.getListFromInventory(module.getFilterInventory()), null, 0, -25, -32, 3, 9, 18,\n\t\t\t\t\t18, 100.0F, DisplayAmount.NEVER, false, shifted);\n\t\t\tGL11.glScalef(1.0F, 1.0F, 1 / -0.00001F);\n\t\t\tif (module.getItemsIncluded().getValue()) {\n\t\t\t\tmc.fontRenderer.drawString(\"Included\", -22, 25, 0);\n\t\t\t} else {\n\t\t\t\tmc.fontRenderer.drawString(\"Excluded\", -22, 25, 0);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<IHUDButton> getButtons() {\n\t\treturn buttons;\n\t}\n\n\tprivate class TabButton extends BasicHUDButton {\n\n\t\tprivate final int mode;\n\n\t\tpublic TabButton(String name, int mode, int x, int y, int width, int height) {\n\t\t\tsuper(name, x, y, width, height);\n\t\t\tthis.mode = mode;\n\t\t}\n\n\t\t@Override\n\t\tpublic void clicked() {\n\t\t\tselected = mode;\n\t\t}\n\n\t\t@Override\n\t\tpublic void renderButton(boolean hover, boolean clicked, boolean shifted) {\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.000005F);\n\t\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\t\tif (hover) {\n\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\t\t\t\tif (!clicked) {\n\t\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.01F);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\t\t}\n\t\t\tGL11.glScaled(0.5D, 0.5D, 1.0D);\n\t\t\tGuiGraphics.drawGuiBackGround(mc,\n\t\t\t\t\tposX * 2,\n\t\t\t\t\tposY * 2,\n\t\t\t\t\t(posX + sizeX) * 2,\n\t\t\t\t\t(posY + sizeY) * 2 + 15,\n\t\t\t\t\t0,\n\t\t\t\t\tfalse,\n\t\t\t\t\ttrue,\n\t\t\t\t\ttrue,\n\t\t\t\t\tfalse,\n\t\t\t\t\ttrue);\n\t\t\tGL11.glScaled(2.0D, 2.0D, 1.0D);\n\n\t\t\tif (clicked) {\n\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.01F);\n\t\t\t}\n\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.000005F);\n\t\t\tint color;\n\t\t\tif (hover && !clicked) {\n\t\t\t\tcolor = Color.getValue(Color.LIGHT_YELLOW);\n\t\t\t} else if (!clicked) {\n\t\t\t\tcolor = Color.getValue(Color.BLACK);\n\t\t\t} else {\n\t\t\t\tcolor = Color.getValue(Color.DARK_GREY);\n\t\t\t}\n\t\t\tGL11.glScaled(0.8D, 0.8D, 1.0D);\n\t\t\tfinal int whateverThisIsX = (int) (\n\t\t\t\t\t(-(mc.fontRenderer.getStringWidth(label) / (2 * (1 / 0.8D))) + posX + sizeX / 2)\n\t\t\t\t\t\t\t* (1 / 0.8D));\n\t\t\tmc.fontRenderer.drawString(label,\n\t\t\t\t\twhateverThisIsX,\n\t\t\t\t\t(int) ((posY + (sizeY - 8) / 2) * (1 / 0.8D)) + 2,\n\t\t\t\t\tcolor);\n\t\t\tGL11.glScaled(1 / 0.8D, 1 / 0.8D, 1.0D);\n\t\t\tif (hover) {\n\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, 0.01F);\n\t\t\t}\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, 0.00001F);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean shouldRenderButton() {\n\t\t\treturn true;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean buttonEnabled() {\n\t\t\treturn mode != selected;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/modules/HUDItemSink.java",
    "content": "package logisticspipes.gui.hud.modules;\n\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HUDItemSink implements IHUDModuleRenderer {\n\n\tprivate final ModuleItemSink module;\n\n\tpublic HUDItemSink(ModuleItemSink module) {\n\t\tthis.module = module;\n\t}\n\n\t@Override\n\tpublic void renderContent(boolean shifted) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tGL11.glScalef(1.0F, 1.0F, -0.00001F);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(ItemIdentifierStack.getListFromInventory(module.getFilterInventory()), null, 0, -25, -32, 3, 9, 18, 18, 100.0F, DisplayAmount.NEVER, false, shifted);\n\t\tGL11.glScalef(1.0F, 1.0F, 1 / -0.00001F);\n\t\tmc.fontRenderer.drawString(\"Default:\", -29, 25, 0);\n\t\tif (module.isDefaultRoute()) {\n\t\t\tmc.fontRenderer.drawString(\"Yes\", 11, 25, 0);\n\t\t} else {\n\t\t\tmc.fontRenderer.drawString(\"No\", 15, 25, 0);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<IHUDButton> getButtons() {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/modules/HUDOreDictItemSink.java",
    "content": "package logisticspipes.gui.hud.modules;\n\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HUDOreDictItemSink implements IHUDModuleRenderer {\n\n\tprivate final ModuleOreDictItemSink itemSink;\n\n\tpublic HUDOreDictItemSink(ModuleOreDictItemSink module) {\n\t\titemSink = module;\n\t}\n\n\t@Override\n\tpublic void renderContent(boolean shifted) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tGL11.glScalef(1.0F, 1.0F, -0.00001F);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(itemSink.getHudItemList(), null, 0, -25, -32, 3, 9, 18, 18, 100.0F, DisplayAmount.NEVER, false, shifted);\n\t\tGL11.glScalef(1.0F, 1.0F, 1 / -0.00001F);\n\t}\n\n\t@Override\n\tpublic List<IHUDButton> getButtons() {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/modules/HUDProviderModule.java",
    "content": "package logisticspipes.gui.hud.modules;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class HUDProviderModule implements IHUDModuleRenderer {\n\n\tprivate List<IHUDButton> buttons = new ArrayList<>();\n\n\tprivate int page = 0;\n\n\tprivate final ModuleProvider module;\n\n\tpublic HUDProviderModule(ModuleProvider moduleProvider) {\n\t\tbuttons.add(new BasicHUDButton(\"<\", 8, -35, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tpage--;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page > 0;\n\t\t\t}\n\t\t});\n\t\tbuttons.add(new BasicHUDButton(\">\", 20, -35, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tpage++;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page + 1 < getMaxPage();\n\t\t\t}\n\t\t});\n\t\tmodule = moduleProvider;\n\t}\n\n\tpublic int getMaxPage() {\n\t\tint ret = module.displayList.size() / 9;\n\t\tif (module.displayList.size() % 9 != 0 || ret == 0) {\n\t\t\tret++;\n\t\t}\n\t\treturn ret;\n\t}\n\n\t@Override\n\tpublic void renderContent(boolean shifted) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tGL11.glScalef(1.0F, 1.0F, -0.00001F);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(module.displayList, null, page, -25, -24, 3, 9, 18, 18, 100.0F, DisplayAmount.ALWAYS, false, shifted);\n\t\tGL11.glScalef(1.0F, 1.0F, 1 / -0.00001F);\n\t}\n\n\t@Override\n\tpublic List<IHUDButton> getButtons() {\n\t\treturn buttons;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/modules/HUDSimpleFilterModule.java",
    "content": "package logisticspipes.gui.hud.modules;\n\nimport java.util.List;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\nimport network.rs485.logisticspipes.module.SimpleFilter;\n\npublic class HUDSimpleFilterModule implements IHUDModuleRenderer {\n\n\tprivate final SimpleFilter filter;\n\n\tpublic HUDSimpleFilterModule(SimpleFilter filter) {\n\t\tthis.filter = filter;\n\t}\n\n\t@Override\n\tpublic void renderContent(boolean shifted) {\n\t\tGL11.glScalef(1.0F, 1.0F, -0.00001F);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(ItemIdentifierStack.getListFromInventory(filter.getFilterInventory()), null,\n\t\t\t\t0, -25, -32, 3, 9, 18, 18, 100.0F, DisplayAmount.NEVER, false, shifted);\n\t\tGL11.glScalef(1.0F, 1.0F, 1 / -0.00001F);\n\t}\n\n\t@Override\n\tpublic List<IHUDButton> getButtons() {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/hud/modules/HUDStringBasedItemSink.java",
    "content": "package logisticspipes.gui.hud.modules;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\n\npublic class HUDStringBasedItemSink implements IHUDModuleRenderer {\n\n\tprivate final IStringBasedModule itemSink;\n\tprivate final List<IHUDButton> list;\n\tprivate int page = 0;\n\n\tpublic HUDStringBasedItemSink(IStringBasedModule module) {\n\t\titemSink = module;\n\t\tlist = new ArrayList<>();\n\t\tlist.add(new BasicHUDButton(\"<\", 10, -35, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tpage--;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn page > 0;\n\t\t\t}\n\t\t});\n\t\tlist.add(new BasicHUDButton(\">\", 20, -35, 8, 8) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tpage++;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn (page + 1) * 6 < itemSink.stringListProperty().size();\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void renderContent(boolean shifted) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tfor (int i = page * 6; i < itemSink.stringListProperty().size() && i < 6 + (page * 6); i++) {\n\t\t\tString mod = itemSink.stringListProperty().get(i);\n\t\t\tmc.fontRenderer.drawString(mod.substring(0, Math.min(12, mod.length())), -28, -25 + ((i - (page * 6)) * 10),\n\t\t\t\t\t0x404040);\n\t\t\t//mc.fontRenderer.drawSplitString(mod, -28, -25 + ((i - (page * 6)) * 10), 50, 0x404040);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<IHUDButton> getButtons() {\n\n\t\treturn list;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/GuiAdvancedExtractor.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui.modules;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.module.AdvancedExtractorSneakyGuiPacket;\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiStringHandlerButton;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.ValuePropertyOverlay;\n\npublic class GuiAdvancedExtractor extends ModuleBaseGui {\n\n\tprivate final AsyncAdvancedExtractor _advancedExtractor;\n\tprivate final PropertyLayer propertyLayer;\n\tprivate final ValuePropertyOverlay<Boolean, BooleanProperty> itemsIncludedOverlay;\n\n\tpublic GuiAdvancedExtractor(IInventory playerInventory, AsyncAdvancedExtractor advancedExtractor) {\n\t\tsuper(null, advancedExtractor);\n\t\t_advancedExtractor = advancedExtractor;\n\n\t\tpropertyLayer = new PropertyLayer(_advancedExtractor.getProperties());\n\n\t\titemsIncludedOverlay = propertyLayer.overlay(_advancedExtractor.getItemsIncluded());\n\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, _advancedExtractor.getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\n\t\tinventorySlots = dummy;\n\t\txSize = 175;\n\t\tySize = 142;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\t//Default item toggle:\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiStringHandlerButton(0, width / 2 + 20, height / 2 - 34, 60, 20,\n\t\t\t\t() -> itemsIncludedOverlay.get() ? \"Included\" : \"Excluded\"));\n\n\t\tbuttonList.add(new GuiButton(1, width / 2 - 25, height / 2 - 34, 40, 20, \"Sneaky\"));\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t\tpropertyLayer.unregister();\n\t\tif (this.mc.player != null && !propertyLayer.getProperties().isEmpty()) {\n\t\t\t// send update to server, when there are changed properties\n\t\t\tMainProxy.sendPacketToServer(ModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(module));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) {\n\t\tswitch (guibutton.id) {\n\t\t\tcase 0:\n\t\t\t\titemsIncludedOverlay.write(BooleanProperty::toggle);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(AdvancedExtractorSneakyGuiPacket.class)\n\t\t\t\t\t\t.setModulePos(_advancedExtractor));\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tmc.fontRenderer.drawString(_advancedExtractor.getFilterInventory().getName(), 8, 6, 0x404040);\n\t\tmc.fontRenderer.drawString(\"Inventory\", 8, ySize - 92, 0x404040);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(LogisticsBaseGuiScreen.ITEMSINK);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/GuiFluidSupplier.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui.modules;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.modules.ModuleFluidSupplier;\nimport logisticspipes.utils.gui.DummyContainer;\n\npublic class GuiFluidSupplier extends ModuleBaseGui {\n\n\tprivate final ModuleFluidSupplier _liquidSupplier;\n\n\tpublic GuiFluidSupplier(IInventory playerInventory, ModuleFluidSupplier module) {\n\t\tsuper(null, module);\n\t\t_liquidSupplier = module;\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, _liquidSupplier.getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\n\t\tinventorySlots = dummy;\n\t\txSize = 175;\n\t\tySize = 142;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tmc.fontRenderer.drawString(_liquidSupplier.getFilterInventory().getName(), 8, 6, 0x404040);\n\t\tmc.fontRenderer.drawString(\"Inventory\", 8, ySize - 92, 0x404040);\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/itemsink.png\");\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiFluidSupplier.TEXTURE);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/GuiOreDictItemSink.java",
    "content": "package logisticspipes.gui.modules;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport kotlin.Unit;\n\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport network.rs485.logisticspipes.property.StringListProperty;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay;\n\npublic class GuiOreDictItemSink extends ModuleBaseGui {\n\n\tprivate final ItemIdentifierInventory tmpInv;\n\tprivate final PropertyLayer propertyLayer;\n\tprivate final PropertyOverlay<List<String>, StringListProperty> oreListOverlay;\n\n\tprivate int mouseX = 0;\n\tprivate int mouseY = 0;\n\n\tprivate final List<String> unsunkNames = new ArrayList<>();\n\tprivate int currentOffset = 0;\n\n\tpublic GuiOreDictItemSink(IInventory playerInventory, ModuleOreDictItemSink oreDictModule) {\n\t\tsuper(null, oreDictModule);\n\n\t\tpropertyLayer = new PropertyLayer(oreDictModule.getProperties());\n\t\toreListOverlay = propertyLayer.overlay(oreDictModule.oreList);\n\n\t\ttmpInv = new ItemIdentifierInventory(1, \"Analyse Slot\", 1);\n\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, tmpInv);\n\t\tdummy.addDummySlot(0, 7, 8);\n\n\t\tdummy.addNormalSlotsForPlayerInventory(7, 126);\n\n\t\tinventorySlots = dummy;\n\t\txSize = 175;\n\t\tySize = 208;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, guiLeft + 159, guiTop + 5, 10, 10, \"\"));\n\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 159, guiTop + 17, 10, 10, \"\"));\n\t\tbuttonList.get(0).enabled = true;\n\t\tbuttonList.get(1).enabled = true;\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t\tpropertyLayer.unregister();\n\t\tif (this.mc.player != null && !propertyLayer.getProperties().isEmpty()) {\n\t\t\t// send update to server, when there are changed properties\n\t\t\tMainProxy.sendPacketToServer(ModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(module));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton par1GuiButton) throws IOException {\n\t\tif (par1GuiButton.id == 0) {\n\t\t\tcurrentOffset -= 1;\n\t\t} else if (par1GuiButton.id == 1) {\n\t\t\tcurrentOffset += 1;\n\t\t} else {\n\t\t\tsuper.actionPerformed(par1GuiButton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tint x = i - guiLeft;\n\t\tint y = j - guiTop;\n\t\tif (0 < x && x < 175 && 0 < y && y < 208) {\n\t\t\tmouseX = x;\n\t\t\tmouseY = y;\n\t\t}\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tint pointerX = var2 - guiLeft;\n\t\tint pointerY = var3 - guiTop;\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 7, guiTop + 126);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 6, guiTop + 7);\n\n\t\tif (tmpInv.getIDStackInSlot(0) != null) {\n\t\t\tList<String> oreNames = getOreNames(tmpInv.getStackInSlot(0));\n\t\t\toreNames.stream().filter(name -> !unsunkNames.contains(name)).forEach(unsunkNames::add);\n\t\t\ttmpInv.clearInventorySlotContents(0);\n\t\t}\n\n\t\tif (currentOffset > unsunkNames.size() - 2) {\n\t\t\tcurrentOffset = unsunkNames.size() - 2;\n\t\t}\n\t\tif (currentOffset < 0) {\n\t\t\tcurrentOffset = 0;\n\t\t}\n\n\t\t//draw unsunk list and highlight bar, handle clicks\n\t\tGui.drawRect(guiLeft + 26, guiTop + 5, guiLeft + 159, guiTop + 27, Color.DARK_GREY.getValue());\n\t\tfinal ArrayList<String> oresToAdd = oreListOverlay.read(oreList -> {\n\t\t\tArrayList<String> oresToAddInner = new ArrayList<>();\n\t\t\tfor (int i = 0; i + currentOffset < unsunkNames.size() && i < 2; i++) {\n\t\t\t\tif (27 <= pointerX && pointerX < 158 && 6 + (10 * i) <= pointerY && pointerY < 6 + (10 * (i + 1))) {\n\t\t\t\t\tGui.drawRect(guiLeft + 27, guiTop + 6 + (10 * i), guiLeft + 158, guiTop + 6 + (10 * (i + 1)), Color.LIGHT_GREY.getValue());\n\t\t\t\t}\n\t\t\t\tmc.fontRenderer.drawString(unsunkNames.get(currentOffset + i), guiLeft + 28, guiTop + 7 + (10 * i), 0x404040);\n\t\t\t\tif (27 <= mouseX && mouseX < 158 && 6 + (10 * i) <= mouseY && mouseY < 6 + (10 * (i + 1))) {\n\t\t\t\t\tmouseX = 0;\n\t\t\t\t\tmouseY = 0;\n\t\t\t\t\tif (oreList.size() < 9) {\n\t\t\t\t\t\tString oreName = unsunkNames.get(currentOffset + i);\n\t\t\t\t\t\tif (!oreList.contains(oreName)) {\n\t\t\t\t\t\t\toresToAddInner.add(oreName);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tunsunkNames.remove(oreName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn oresToAddInner;\n\t\t});\n\t\tif (!oresToAdd.isEmpty()) {\n\t\t\toreListOverlay.write(oreList -> {\n\t\t\t\tfor (String oreName : oresToAdd) {\n\t\t\t\t\tif (!oreList.contains(oreName)) {\n\t\t\t\t\t\toreList.add(oreName);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn Unit.INSTANCE;\n\t\t\t});\n\t\t}\n\n\t\t//draw main list and highlight bar, handle clicks\n\t\tGui.drawRect(guiLeft + 5, guiTop + 30, guiLeft + 169, guiTop + 122, Color.DARK_GREY.getValue());\n\t\tfinal ArrayList<String> oresToRemove = oreListOverlay.read(oreList -> {\n\t\t\tArrayList<String> oresToRemoveInner = new ArrayList<>();\n\t\t\tfor (int i = 0; i < oreList.size() && i < 9; i++) {\n\t\t\t\tif (6 <= pointerX && pointerX < 168 && 31 + (10 * i) <= pointerY && pointerY < 31 + (10 * (i + 1))) {\n\t\t\t\t\tGui.drawRect(guiLeft + 6, guiTop + 31 + (10 * i), guiLeft + 168, guiTop + 31 + (10 * (i + 1)), Color.LIGHT_GREY.getValue());\n\t\t\t\t}\n\t\t\t\tmc.fontRenderer.drawString(oreList.get(i), guiLeft + 7, guiTop + 32 + (10 * i), 0x404040);\n\t\t\t\tif (6 <= mouseX && mouseX < 168 && 31 + (10 * i) <= mouseY && mouseY < 31 + (10 * (i + 1))) {\n\t\t\t\t\tmouseX = 0;\n\t\t\t\t\tmouseY = 0;\n\t\t\t\t\tString oreName = oreList.get(i);\n\t\t\t\t\tif (!unsunkNames.contains(oreName)) {\n\t\t\t\t\t\tunsunkNames.add(oreName);\n\t\t\t\t\t}\n\t\t\t\t\toresToRemoveInner.add(oreName);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn oresToRemoveInner;\n\t\t});\n\n\t\tif (!oresToRemove.isEmpty()) {\n\t\t\toreListOverlay.write(oreList -> {\n\t\t\t\tfor (String oreName : oresToRemove) {\n\t\t\t\t\toreList.remove(oreName);\n\t\t\t\t}\n\t\t\t\treturn Unit.INSTANCE;\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate List<String> getOreNames(@Nonnull ItemStack stack) {\n\t\tint[] oreids = OreDictionary.getOreIDs(stack);\n\t\tList<String> oreNames = new ArrayList<>(oreids.length);\n\t\tfor (int oreid : oreids) {\n\t\t\tString oreName = OreDictionary.getOreName(oreid);\n\t\t\tif (oreName != null && !oreName.equals(\"Unknown\") && !oreNames.contains(oreName)) {\n\t\t\t\toreNames.add(oreName);\n\t\t\t}\n\t\t}\n\t\treturn oreNames;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/GuiSimpleFilter.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui.modules;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.module.SimpleFilter;\n\npublic class GuiSimpleFilter extends ModuleBaseGui {\n\n\tprivate final SimpleFilter filter;\n\n\tpublic GuiSimpleFilter(IInventory playerInventory, LogisticsModule filterModule) {\n\t\tsuper(null, filterModule);\n\t\tif (!(filterModule instanceof SimpleFilter)) throw new IllegalArgumentException(\"Module is not a filter module\");\n\t\tfilter = (SimpleFilter) filterModule;\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, filter.getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\n\t\tinventorySlots = dummy;\n\t\txSize = 175;\n\t\tySize = 142;\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tmc.fontRenderer.drawString(filter.getFilterInventory().getName(), 8, 6, 0x404040);\n\t\tmc.fontRenderer.drawString(\"Inventory\", 8, ySize - 92, 0x404040);\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/itemsink.png\");\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiSimpleFilter.TEXTURE);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/GuiSneakyConfigurator.java",
    "content": "/*\n * Copyright (c) Krapht, 2012\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui.modules;\n\nimport java.io.IOException;\nimport java.util.Locale;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.modules.SneakyModuleDirectionUpdate;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.module.SneakyDirection;\n\npublic class GuiSneakyConfigurator extends ModuleBaseGui {\n\n\tprivate final SneakyDirection directionReceiver;\n\n\tpublic GuiSneakyConfigurator(IInventory playerInventory, LogisticsModule module) {\n\t\tsuper(new DummyContainer(playerInventory, null), module);\n\t\tif (!(module instanceof SneakyDirection)) throw new IllegalArgumentException(\"Module is not sneaky\");\n\t\tdirectionReceiver = (SneakyDirection) module;\n\t\txSize = 160;\n\t\tySize = 200;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\n\t\tint left = width / 2 - xSize / 2;\n\t\tint top = height / 2 - ySize / 2;\n\n\t\tbuttonList.add(new GuiButton(0, left + 110, top + 103, 40, 20, \"\")); //DOWN\n\t\tbuttonList.add(new GuiButton(1, left + 110, top + 43, 40, 20, \"\")); //UP\n\t\tbuttonList.add(new GuiButton(2, left + 50, top + 53, 50, 20, \"\")); //NORTH\n\t\tbuttonList.add(new GuiButton(3, left + 50, top + 93, 50, 20, \"\")); //SOUTH\n\t\tbuttonList.add(new GuiButton(4, left + 10, top + 73, 40, 20, \"\")); //WEST\n\t\tbuttonList.add(new GuiButton(5, left + 100, top + 73, 40, 20, \"\")); //EAST\n\t\tbuttonList.add(new GuiButton(6, left + 10, top + 23, 60, 20, \"\")); //DEFAULT\n\n\t\trefreshButtons();\n\t}\n\n\tprivate void refreshButtons() {\n\t\tfor (Object p : buttonList) {\n\t\t\tGuiButton button = (GuiButton) p;\n\t\t\tbutton.displayString = getButtonOrientationString(button.id == 6 ? null : EnumFacing.byIndex(button.id));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tdirectionReceiver.setSneakyDirection(guibutton.id == 6 ? null : EnumFacing.byIndex(guibutton.id));\n\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SneakyModuleDirectionUpdate.class).setDirection(directionReceiver.getSneakyDirection()).setModulePos(module));\n\n\t\trefreshButtons();\n\t\tsuper.actionPerformed(guibutton);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\n\t\trefreshButtons();\n\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\n\t\tmc.fontRenderer.drawString(\"Sneaky orientation\", xSize / 2 - mc.fontRenderer.getStringWidth(\"Sneaky orientation\") / 2, 10, 0x404040);\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/sneaky.png\");\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int x, int y) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiSneakyConfigurator.TEXTURE);\n\t\tint j = guiLeft;\n\t\tint k = guiTop;\n\t\t//drawRect(width/2 - xSize / 2, height / 2 - ySize /2, width/2 + xSize / 2, height / 2 + ySize /2, 0xFF404040);\n\t\tdrawTexturedModalRect(j, k, 0, 0, xSize, ySize);\n\t}\n\n\tprivate String getButtonOrientationString(EnumFacing orientation) {\n\t\tString s = (orientation == null ? \"DEFAULT\" : orientation.name());\n\t\tif (orientation == directionReceiver.getSneakyDirection()) {\n\t\t\treturn \"\\u00a7a>\" + s + \"<\";\n\t\t}\n\t\treturn s.toLowerCase(Locale.US);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/GuiStringBasedItemSink.java",
    "content": "package logisticspipes.gui.modules;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.List;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.IInventory;\n\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SimpleGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.property.StringListProperty;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay;\n\npublic class GuiStringBasedItemSink extends ModuleBaseGui {\n\n\tprivate final ItemIdentifierInventory tmpInv;\n\tprivate final PropertyLayer propertyLayer;\n\tprivate final IStringBasedModule stringBasedModule;\n\tprivate final PropertyOverlay<List<String>, StringListProperty> stringListOverlay;\n\tprivate String name = \"\";\n\tprivate int mouseX = 0;\n\tprivate int mouseY = 0;\n\n\tpublic GuiStringBasedItemSink(IInventory playerInventory, LogisticsModule module) {\n\t\tsuper(null, module);\n\t\tif (!(module instanceof IStringBasedModule)) throw new IllegalArgumentException(\"Module must be string based\");\n\t\tstringBasedModule = (IStringBasedModule) module;\n\t\tpropertyLayer = new PropertyLayer(Collections.singletonList(stringBasedModule.stringListProperty()));\n\t\tstringListOverlay = propertyLayer.overlay(stringBasedModule.stringListProperty());\n\n\t\ttmpInv = new ItemIdentifierInventory(1, \"Analyse Slot\", 1);\n\n\t\tDummyContainer dummy = new DummyContainer(playerInventory, tmpInv);\n\t\tdummy.addDummySlot(0, 7, 8);\n\n\t\tdummy.addNormalSlotsForPlayerInventory(7, 126);\n\n\t\tinventorySlots = dummy;\n\t\txSize = 175;\n\t\tySize = 208;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, guiLeft + 38, guiTop + 18, 50, 10, \"Add\"));\n\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 107, guiTop + 18, 50, 10, \"Remove\"));\n\t\tbuttonList.get(0).enabled = false;\n\t\tbuttonList.get(1).enabled = false;\n\t}\n\n\t@Override\n\tpublic void onGuiClosed() {\n\t\tsuper.onGuiClosed();\n\t\tpropertyLayer.unregister();\n\t\tif (this.mc.player != null && !propertyLayer.getProperties().isEmpty()) {\n\t\t\t// send update to server, when there are changed properties\n\t\t\tMainProxy.sendPacketToServer(ModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(module));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton par1GuiButton) throws IOException {\n\t\tif (par1GuiButton.id == 0) {\n\t\t\tfinal ItemIdentifierStack analyseStack = tmpInv.getIDStackInSlot(0);\n\t\t\tif (analyseStack == null) return;\n\t\t\tstringListOverlay.write(strings -> {\n\t\t\t\tif (!strings.contains(stringBasedModule.getStringForItem(analyseStack.getItem()))) {\n\t\t\t\t\tstrings.add(stringBasedModule.getStringForItem(analyseStack.getItem()));\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t} else if (par1GuiButton.id == 1) {\n\t\t\tfinal ItemIdentifierStack analyseStack = tmpInv.getIDStackInSlot(0);\n\t\t\tstringListOverlay.write(strings -> {\n\t\t\t\tif (analyseStack != null\n\t\t\t\t\t\t&& strings.contains(stringBasedModule.getStringForItem(analyseStack.getItem()))) {\n\t\t\t\t\tstrings.remove(stringBasedModule.getStringForItem(analyseStack.getItem()));\n\t\t\t\t} else if (!name.isEmpty() && strings.contains(name)) {\n\t\t\t\t\tstrings.remove(name);\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t} else {\n\t\t\tsuper.actionPerformed(par1GuiButton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tint x = i - guiLeft;\n\t\tint y = j - guiTop;\n\t\tif (0 < x && x < 175 && 0 < y && y < 208) {\n\t\t\tmouseX = x;\n\t\t\tmouseY = y;\n\t\t}\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 7, guiTop + 126);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 6, guiTop + 7);\n\t\tSimpleGraphics.drawRectNoBlend(guiLeft + 26, guiTop + 5, guiLeft + 169, guiTop + 17, Color.DARK_GREY, 0.0);\n\t\tstringListOverlay.read(strings -> {\n\t\t\tfinal ItemIdentifierStack analyseStack = tmpInv.getIDStackInSlot(0);\n\t\t\tif (analyseStack != null) {\n\t\t\t\tname = \"\";\n\t\t\t\tmc.fontRenderer\n\t\t\t\t\t\t.drawString(stringBasedModule.getStringForItem(analyseStack.getItem()), guiLeft + 28,\n\t\t\t\t\t\t\t\tguiTop + 7,\n\t\t\t\t\t\t\t\t0x404040);\n\t\t\t\tif (strings.contains(stringBasedModule.getStringForItem(analyseStack.getItem()))) {\n\t\t\t\t\tbuttonList.get(0).enabled = false;\n\t\t\t\t\tbuttonList.get(1).enabled = true;\n\t\t\t\t} else if (strings.size() < 9) {\n\t\t\t\t\tbuttonList.get(0).enabled = true;\n\t\t\t\t\tbuttonList.get(1).enabled = false;\n\t\t\t\t} else {\n\t\t\t\t\tbuttonList.get(0).enabled = false;\n\t\t\t\t\tbuttonList.get(1).enabled = false;\n\t\t\t\t}\n\t\t\t} else if (name.isEmpty()) {\n\t\t\t\tbuttonList.get(0).enabled = false;\n\t\t\t\tbuttonList.get(1).enabled = false;\n\t\t\t} else {\n\t\t\t\tif (strings.contains(name)) {\n\t\t\t\t\tmc.fontRenderer.drawString(name, guiLeft + 28, guiTop + 7, 0x404040);\n\t\t\t\t\tbuttonList.get(0).enabled = false;\n\t\t\t\t\tbuttonList.get(1).enabled = true;\n\t\t\t\t} else {\n\t\t\t\t\tname = \"\";\n\t\t\t\t\tbuttonList.get(0).enabled = false;\n\t\t\t\t\tbuttonList.get(1).enabled = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tGui.drawRect(guiLeft + 5, guiTop + 30, guiLeft + 169, guiTop + 122, Color.DARK_GREY.getValue());\n\t\t\tfor (int i = 0; i < strings.size() && i < 9; i++) {\n\t\t\t\tint pointerX = var2 - guiLeft;\n\t\t\t\tint pointerY = var3 - guiTop;\n\t\t\t\tif (6 <= pointerX && pointerX < 168 && 31 + (10 * i) <= pointerY && pointerY < 31 + (10 * (i + 1))) {\n\t\t\t\t\tGui.drawRect(guiLeft + 6, guiTop + 31 + (10 * i), guiLeft + 168, guiTop + 31 + (10 * (i + 1)),\n\t\t\t\t\t\t\tColor.LIGHT_GREY.getValue());\n\t\t\t\t}\n\t\t\t\tmc.fontRenderer.drawString(strings.get(i), guiLeft + 7, guiTop + 32 + (10 * i), 0x404040);\n\t\t\t\tif (6 <= mouseX && mouseX < 168 && 31 + (10 * i) <= mouseY && mouseY < 31 + (10 * (i + 1))) {\n\t\t\t\t\tname = strings.get(i);\n\t\t\t\t\tmouseX = 0;\n\t\t\t\t\tmouseY = 0;\n\t\t\t\t\ttmpInv.clearInventorySlotContents(0);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/modules/ModuleBaseGui.java",
    "content": "package logisticspipes.gui.modules;\n\nimport java.io.IOException;\n\nimport net.minecraft.inventory.Container;\n\nimport lombok.Getter;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.GuiOpenChassis;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic abstract class ModuleBaseGui extends LogisticsBaseGuiScreen {\n\n\t@Getter\n\tprotected LogisticsModule module;\n\n\tpublic ModuleBaseGui(Container par1Container, LogisticsModule module) {\n\t\tsuper(par1Container);\n\t\tthis.module = module;\n\t}\n\n\t@Override\n\tprotected void keyTyped(char typedChar, int keyCode) throws IOException {\n\t\tif (module == null) {\n\t\t\tsuper.keyTyped(typedChar, keyCode);\n\t\t\treturn;\n\t\t}\n\t\tif (keyCode == 1 || typedChar == 'e') {\n\t\t\tsuper.keyTyped(typedChar, keyCode);\n\t\t\tif (module.getSlot() == ModulePositionType.SLOT) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(GuiOpenChassis.class).setBlockPos(module.getBlockPos()));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/orderer/FluidGuiOrderer.java",
    "content": "package logisticspipes.gui.orderer;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.RequestFluidOrdererRefreshPacket;\nimport logisticspipes.network.packets.orderer.SubmitFluidRequestPacket;\nimport logisticspipes.pipes.PipeFluidRequestLogistics;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class FluidGuiOrderer extends GuiOrderer {\n\n\tpublic FluidGuiOrderer(PipeFluidRequestLogistics pipe, EntityPlayer entityPlayer) {\n\t\tsuper(pipe.getX(), pipe.getY(), pipe.getZ(), pipe.getWorld().provider.getDimension(), entityPlayer);\n\t\t_title = \"Request Fluid\";\n\t\trefreshItems();\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tboolean setItemDisplay = itemDisplay == null;\n\t\tsuper.initGui();\n\t\tbuttonList.add(new GuiButton(3, guiLeft + 10, bottom - 25, 46, 20, \"Refresh\")); // Refresh\n\t\tif (setItemDisplay) {\n\t\t\titemDisplay = new ItemDisplay(this, fontRenderer, this, this, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, xCenter, bottom - 24, 49, new int[] { 1, 1000, 16000, 100 }, false);\n\t\t}\n\t\titemDisplay.reposition(guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, xCenter, bottom - 24);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0 && itemDisplay.getSelectedItem() != null) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SubmitFluidRequestPacket.class).setStack(itemDisplay.getSelectedItem().getItem().makeStack(itemDisplay.getRequestCount())).setPosX(xCoord).setPosY(yCoord).setPosZ(zCoord).setDimension(dimension));\n\t\t\trefreshItems();\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected int getStackAmount() {\n\t\treturn 1000;\n\t}\n\n\t@Override\n\tpublic void refreshItems() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestFluidOrdererRefreshPacket.class).setInteger(dimension).setPosX(xCoord).setPosY(yCoord).setPosZ(zCoord));\n\t}\n\n\t@Override\n\tpublic void specialItemRendering(ItemIdentifier item, int x, int y) {}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/orderer/GuiOrderer.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.gui.orderer;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.enchantment.Enchantment;\nimport net.minecraft.enchantment.EnchantmentHelper;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.ChatAllowedCharacters;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.gui.popup.GuiRequestPopup;\nimport logisticspipes.interfaces.ISpecialItemRenderer;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.RequestComponentPacket;\nimport logisticspipes.network.packets.orderer.RequestSubmitPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.IItemSearch;\nimport logisticspipes.utils.gui.ISubGuiControler;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic abstract class GuiOrderer extends LogisticsBaseGuiScreen implements IItemSearch, ISpecialItemRenderer {\n\n\tpublic final EntityPlayer _entityPlayer;\n\tpublic ItemDisplay itemDisplay;\n\tprivate InputBar search;\n\n\tprotected String _title = \"Request items\";\n\n\tpublic final int xCoord;\n\tpublic final int yCoord;\n\tpublic final int zCoord;\n\tpublic int dimension;\n\n\tpublic static int dimensioncache;\n\tpublic static long cachetime;\n\n\tpublic GuiOrderer(int x, int y, int z, int dim, EntityPlayer entityPlayer) {\n\t\tsuper(220, 240, 0, 0);\n\t\txCoord = x;\n\t\tyCoord = y;\n\t\tzCoord = z;\n\t\tif (GuiOrderer.cachetime + 100 < System.currentTimeMillis()) {\n\t\t\tdimension = dim;\n\t\t} else {\n\t\t\tdimension = GuiOrderer.dimensioncache;\n\t\t}\n\t\t_entityPlayer = entityPlayer;\n\t\tinventorySlots = new DummyContainer(entityPlayer.inventory, null);\n\t}\n\n\tpublic abstract void refreshItems();\n\n\tpublic void handlePacket(Collection<ItemIdentifierStack> allItems) {\n\t\titemDisplay.setItemList(allItems.stream().filter(Objects::nonNull).collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, right - 55, bottom - 25, 50, 20, \"Request\")); // Request\n\t\tbuttonList.add(new SmallGuiButton(1, right - 15, guiTop + 5, 10, 10, \">\")); // Next page\n\t\tbuttonList.add(new SmallGuiButton(2, right - 90, guiTop + 5, 10, 10, \"<\")); // Prev page\n\t\tbuttonList.add(new SmallGuiButton(10, xCenter - 51, bottom - 15, 26, 10, \"---\")); // -64\n\t\tbuttonList.add(new SmallGuiButton(4, xCenter - 51, bottom - 26, 15, 10, \"--\")); // -10\n\t\tbuttonList.add(new SmallGuiButton(5, xCenter - 35, bottom - 26, 10, 10, \"-\")); // -1\n\t\tbuttonList.add(new SmallGuiButton(6, xCenter + 26, bottom - 26, 10, 10, \"+\")); // +1\n\t\tbuttonList.add(new SmallGuiButton(7, xCenter + 38, bottom - 26, 15, 10, \"++\")); // +10\n\t\tbuttonList.add(new SmallGuiButton(11, xCenter + 26, bottom - 15, 26, 10, \"+++\")); // +64\n\t\tbuttonList.add(new GuiCheckBox(8, guiLeft + 9, bottom - 60, 14, 14, Configs.DISPLAY_POPUP)); // Popup\n\n\t\tbuttonList.add(new SmallGuiButton(20, xCenter - 13, bottom - 41, 26, 10, \"Sort\")); // Sort\n\n\t\tif (search == null) {\n\t\t\tsearch = new InputBar(fontRenderer, this, guiLeft + 10, bottom - 78, xSize - 20, 15);\n\t\t}\n\t\tsearch.reposition(guiLeft + 10, bottom - 78, xSize - 20, 15);\n\n\t\tif (itemDisplay == null) {\n\t\t\titemDisplay = new ItemDisplay(this, fontRenderer, this, this, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, xCenter, bottom - 24, 49, new int[] { 1, 10, 64, 64 }, true);\n\t\t}\n\t\titemDisplay.reposition(guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, xCenter, bottom - 24);\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tpublic boolean doesGuiPauseGame() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void drawGuiContainerBackgroundLayer(float f, int i, int j) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\n\t\tmc.fontRenderer.drawString(_title, guiLeft + mc.fontRenderer.getStringWidth(_title) / 2, guiTop + 6, 0x404040);\n\t\titemDisplay.renderPageNumber(right - 47, guiTop + 6);\n\n\t\tif (buttonList.get(9) instanceof GuiCheckBox && ((GuiCheckBox) buttonList.get(9)).getState()) {\n\t\t\tmc.fontRenderer.drawString(\"Popup\", guiLeft + 25, bottom - 56, 0x404040);\n\t\t} else {\n\t\t\tmc.fontRenderer.drawString(\"Popup\", guiLeft + 25, bottom - 56, Color.getValue(Color.GREY));\n\t\t}\n\n\t\titemDisplay.renderAmount(getStackAmount());\n\t\t//SearchInput\n\t\tsearch.drawTextBox();\n\n\t\titemDisplay.renderSortMode(xCenter, bottom - 52);\n\t\titemDisplay.renderItemArea(zLevel);\n\t}\n\n\t@Override\n\tpublic void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tif (super.hasSubGui()) {\n\t\t\treturn;\n\t\t}\n\t\tGuiGraphics.displayItemToolTip(itemDisplay.getToolTip(), this, zLevel, guiLeft, guiTop);\n\t}\n\n\t@Override\n\tpublic boolean itemSearched(ItemIdentifier item) {\n\t\tif (search.isEmpty()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (isSearched(item.getFriendlyName().toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\treturn true;\n\t\t}\n\t\t//if(isSearched(String.valueOf(Item.getIdFromItem(item.item)), search.getContent())) return true;\n\t\t//Enchantment? Enchantment!\n\t\tMap<Enchantment, Integer> enchantIdLvlMap = EnchantmentHelper.getEnchantments(item.unsafeMakeNormalStack(1));\n\t\tfor (Entry<Enchantment, Integer> e : enchantIdLvlMap.entrySet()) {\n\t\t\tString enchantname = e.getKey().getName();\n\t\t\tif (enchantname != null) {\n\t\t\t\tif (isSearched(enchantname.toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean isSearched(String value, String search) {\n\t\tboolean flag = true;\n\t\tfor (String s : search.split(\" \")) {\n\t\t\tif (!value.contains(s)) {\n\t\t\t\tflag = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn flag;\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\titemDisplay.handleClick(i, j, k);\n\t\tsearch.handleClick(i, j, k);\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\titemDisplay.handleMouse();\n\t\tsuper.handleMouseInputSub();\n\t}\n\n\tpublic void handleRequestAnswer(Collection<IResource> items, boolean error, ISubGuiControler control, EntityPlayer player) {\n\t\twhile (control.hasSubGui()) {\n\t\t\tcontrol = control.getSubGui();\n\t\t}\n\t\tif (error) {\n\t\t\tcontrol.setSubGui(new GuiRequestPopup(_entityPlayer, \"You are missing:\", items));\n\t\t} else {\n\t\t\tcontrol.setSubGui(new GuiRequestPopup(_entityPlayer, \"Request successful!\", items));\n\t\t}\n\t}\n\n\tpublic void handleSimulateAnswer(Collection<IResource> used, Collection<IResource> missing, ISubGuiControler control, EntityPlayer player) {\n\t\twhile (control.hasSubGui()) {\n\t\t\tcontrol = control.getSubGui();\n\t\t}\n\t\tcontrol.setSubGui(new GuiRequestPopup(_entityPlayer, \"Components: \", used, \"Missing: \", missing));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0 && itemDisplay.getSelectedItem() != null) {\n\t\t\tfinal ItemIdentifierStack stack = itemDisplay.getSelectedItem().getItem().makeStack(itemDisplay.getRequestCount());\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSubmitPacket.class).setStack(stack).setPosX(xCoord).setPosY(yCoord).setPosZ(zCoord).setDimension(dimension));\n\t\t\trefreshItems();\n\t\t} else if (guibutton.id == 1) {\n\t\t\titemDisplay.nextPage();\n\t\t} else if (guibutton.id == 2) {\n\t\t\titemDisplay.prevPage();\n\t\t} else if (guibutton.id == 3) {\n\t\t\trefreshItems();\n\t\t} else if (guibutton.id == 10) {\n\t\t\titemDisplay.sub(3);\n\t\t} else if (guibutton.id == 4) {\n\t\t\titemDisplay.sub(2);\n\t\t} else if (guibutton.id == 5) {\n\t\t\titemDisplay.sub(1);\n\t\t} else if (guibutton.id == 6) {\n\t\t\titemDisplay.add(1);\n\t\t} else if (guibutton.id == 7) {\n\t\t\titemDisplay.add(2);\n\t\t} else if (guibutton.id == 11) {\n\t\t\titemDisplay.add(3);\n\t\t} else if (guibutton.id == 8) {\n\t\t\tGuiCheckBox button = (GuiCheckBox) guibutton;\n\t\t\tConfigs.DISPLAY_POPUP = button.change();\n\t\t\tConfigs.savePopupState();\n\t\t} else if (guibutton.id == 13 && itemDisplay.getSelectedItem() != null) {\n\t\t\tfinal ItemIdentifierStack stack = itemDisplay.getSelectedItem().getItem().makeStack(itemDisplay.getRequestCount());\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestComponentPacket.class).setStack(stack).setPosX(xCoord).setPosY(yCoord).setPosZ(zCoord).setDimension(dimension));\n\t\t} else if (guibutton.id == 20) {\n\t\t\titemDisplay.cycle();\n\t\t}\n\n\t\tsuper.actionPerformed(guibutton);\n\t}\n\n\tprotected int getStackAmount() {\n\t\treturn 64;\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) throws IOException {\n\t\tif (search.isFocused()) {\n\t\t\tif (!search.isEmpty() && search.handleKey(c, i))\n\t\t\t\treturn;\n\t\t} else if (GuiScreen.isAltKeyDown() && ChatAllowedCharacters.isAllowedCharacter(c)) {\n\t\t\titemDisplay.setFocused(false);\n\t\t\tsearch.setFocused(true);\n\t\t\tsearch.setText(\"\");\n\t\t\tsearch.handleKey(c, i);\n\t\t\treturn;\n\t\t}\n\t\tif (!itemDisplay.keyTyped(c, i)) {\n\t\t\t// Track everything except Escape when in search bar\n\t\t\tif (i == 1 || !search.handleKey(c, i)) {\n\t\t\t\tsuper.keyTyped(c, i);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void resetSubGui() {\n\t\tsuper.resetSubGui();\n\t\trefreshItems();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/orderer/GuiRequestTable.java",
    "content": "package logisticspipes.gui.orderer;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.enchantment.Enchantment;\nimport net.minecraft.enchantment.EnchantmentHelper;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ChatAllowedCharacters;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.config.Configs;\nimport logisticspipes.gui.popup.GuiDiskPopup;\nimport logisticspipes.gui.popup.GuiRequestPopup;\nimport logisticspipes.gui.popup.RequestMonitorPopup;\nimport logisticspipes.interfaces.IChainAddList;\nimport logisticspipes.interfaces.IDiskProvider;\nimport logisticspipes.interfaces.ISpecialItemRenderer;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.ClearCraftingGridPacket;\nimport logisticspipes.network.packets.block.CraftingCycleRecipe;\nimport logisticspipes.network.packets.orderer.DiskRequestConectPacket;\nimport logisticspipes.network.packets.orderer.OrdererRefreshRequestPacket;\nimport logisticspipes.network.packets.orderer.RequestComponentPacket;\nimport logisticspipes.network.packets.orderer.RequestSubmitListPacket;\nimport logisticspipes.network.packets.orderer.RequestSubmitPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.utils.ChainAddArrayList;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.IItemSearch;\nimport logisticspipes.utils.gui.ISubGuiControler;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.extension.GuiExtension;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.string.ChatColor;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiRequestTable extends LogisticsBaseGuiScreen implements IItemSearch, ISpecialItemRenderer, IDiskProvider {\n\n\tpublic final PipeBlockRequestTable _table;\n\tpublic final EntityPlayer _entityPlayer;\n\tprotected final String _title = \"Request items\";\n\tpublic ItemDisplay itemDisplay;\n\tpublic int dimension;\n\tprotected DisplayOptions displayOptions = DisplayOptions.Both;\n\tprivate SmallGuiButton macroButton;\n\tprivate InputBar search;\n\tprivate boolean showRequest = true;\n\tprivate int startLeft;\n\tprivate int startXSize;\n\tprivate BitSet handledExtension = new BitSet();\n\tprivate int orderIdForButton;\n\tprivate GuiButton[] cycleButtons = new GuiButton[2];\n\tprivate IChainAddList<GuiButton> moveWhileSmall = new ChainAddArrayList<>();\n\tprivate IChainAddList<GuiButton> hideWhileSmall = new ChainAddArrayList<>();\n\tprivate GuiButton hideShowButton;\n\n\tpublic GuiRequestTable(EntityPlayer entityPlayer, PipeBlockRequestTable table) {\n\t\tsuper(410, 240, 0, 0);\n\t\t_table = table;\n\t\t_entityPlayer = entityPlayer;\n\t\tif (GuiOrderer.cachetime + 100 < System.currentTimeMillis()) {\n\t\t\tdimension = _table.getWorld().provider.getDimension();\n\t\t} else {\n\t\t\tdimension = GuiOrderer.dimensioncache;\n\t\t}\n\t\tDummyContainer dummy = new DummyContainer(entityPlayer.inventory, _table.matrix);\n\t\tdummy.guiHolderForJEI = this;\n\n\t\tint i = 0;\n\t\tfor (int y = 0; y < 3; y++) {\n\t\t\tfor (int x = 0; x < 9; x++) {\n\t\t\t\tdummy.addNormalSlot(i++, _table.inv, guiLeft + (x * 18) + 20, guiTop + (y * 18) + 80);\n\t\t\t}\n\t\t}\n\t\ti = 0;\n\t\tfor (int y = 0; y < 3; y++) {\n\t\t\tfor (int x = 0; x < 3; x++) {\n\t\t\t\tdummy.addDummySlot(i++, guiLeft + (x * 18) + 20, guiTop + (y * 18) + 15);\n\t\t\t}\n\t\t}\n\t\tdummy.addCallableSlotHandler(0, _table.resultInv, guiLeft + 101, guiTop + 33, _table::getResultForClick);\n\t\tdummy.addNormalSlot(0, _table.toSortInv, guiLeft + 164, guiTop + 51);\n\t\tdummy.addNormalSlot(0, _table.diskInv, guiLeft + 164, guiTop + 25);\n\t\tdummy.addNormalSlotsForPlayerInventory(20, 150);\n\t\tinventorySlots = dummy;\n\t\trefreshItems();\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tboolean reHide = false;\n\t\tif (!showRequest) {\n\t\t\tguiLeft = startLeft;\n\t\t\txSize = startXSize;\n\t\t\tshowRequest = true;\n\t\t\treHide = true;\n\t\t}\n\t\tsuper.initGui();\n\n\t\tbuttonList.clear();\n\t\tbuttonList.add(hideWhileSmall.addChain(new GuiButton(0, right - 55, bottom - 25, 50, 20, \"Request\"))); // Request\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(1, right - 15, guiTop + 5, 10, 10, \">\"))); // Next page\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(2, right - 90, guiTop + 5, 10, 10, \"<\"))); // Prev page\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(10, right - 148, bottom - 15, 26, 10, \"---\"))); // -64\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(4, right - 148, bottom - 26, 15, 10, \"--\"))); // -10\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(5, right - 132, bottom - 26, 10, 10, \"-\"))); // -1\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(6, right - 86, bottom - 26, 10, 10, \"+\"))); // +1\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(7, right - 74, bottom - 26, 15, 10, \"++\"))); // +10\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(11, right - 86, bottom - 15, 26, 10, \"+++\"))); // +64\n\t\tbuttonList.add(hideWhileSmall.addChain(new GuiCheckBox(8, guiLeft + 209, bottom - 60, 14, 14, Configs.DISPLAY_POPUP))); // Popup\n\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(3, guiLeft + 210, bottom - 15, 46, 10, \"Refresh\"))); // Refresh\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(13, guiLeft + 210, bottom - 28, 46, 10, \"Content\"))); // Component\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(9, guiLeft + 210, bottom - 41, 46, 10, \"Both\")));\n\t\tbuttonList.add(hideWhileSmall.addChain(new SmallGuiButton(20, right - 116, bottom - 41, 26, 10, \"Sort\"))); // Sort\n\n\t\tbuttonList.add(moveWhileSmall.addChain(new SmallGuiButton(14, guiLeft + 96, guiTop + 53, 10, 10, \"+\"))); // +1\n\t\tbuttonList.add(moveWhileSmall.addChain(new SmallGuiButton(15, guiLeft + 108, guiTop + 53, 15, 10, \"++\"))); // +10\n\t\tbuttonList.add(moveWhileSmall.addChain(new SmallGuiButton(16, guiLeft + 96, guiTop + 64, 26, 10, \"+++\"))); // +64\n\n\t\tbuttonList.add(moveWhileSmall.addChain(new SmallGuiButton(30, guiLeft + 96 + 2, guiTop + 18, 10, 10, \"X\"))); // x\n\t\tbuttonList.add(moveWhileSmall.addChain(new SmallGuiButton(31, guiLeft + 108 + 2, guiTop + 18, 10, 10, \"~\", 3))); // ~\n\n\t\tbuttonList.add(hideShowButton = new SmallGuiButton(17, guiLeft + 173, guiTop + 5, 36, 10, \"Hide\")); // Hide\n\t\tbuttonList.add(macroButton = new SmallGuiButton(18, right - 55, bottom - 60, 50, 10, \"Disk\"));\n\t\tmacroButton.enabled = false;\n\n\t\t(cycleButtons[0] = addButton(new SmallGuiButton(21, guiLeft + 124, guiTop + 30, 15, 10, \"/\\\\\"))).visible = false;\n\t\t(cycleButtons[1] = addButton(new SmallGuiButton(22, guiLeft + 124, guiTop + 42, 15, 10, \"\\\\/\"))).visible = false;\n\n\t\tif (search == null) {\n\t\t\tsearch = new InputBar(fontRenderer, this, guiLeft + 205, bottom - 78, 200, 15);\n\t\t}\n\t\tsearch.reposition(guiLeft + 205, bottom - 78, 200, 15);\n\n\t\tif (itemDisplay == null) {\n\t\t\titemDisplay = new ItemDisplay(this, fontRenderer, this, this, guiLeft + 205, guiTop + 18, 200, ySize - 100, right - 104, bottom - 24, 36, new int[] { 1, 10, 64, 64 }, true);\n\t\t}\n\t\titemDisplay.reposition(guiLeft + 205, guiTop + 18, 200, ySize - 100, right - 104, bottom - 24);\n\n\t\tstartLeft = guiLeft;\n\t\tstartXSize = xSize;\n\t\tif (reHide) {\n\t\t\tshowRequest = false;\n\t\t\txSize = startXSize - 210;\n\t\t\tguiLeft = startLeft + 105;\n\t\t\tfor (GuiButton button : moveWhileSmall) {\n\t\t\t\tbutton.x += 105;\n\t\t\t}\n\t\t\thideShowButton.x += 90;\n\t\t\thideShowButton.displayString = \"Show\";\n\t\t\tfor (GuiButton button : hideWhileSmall) {\n\t\t\t\tbutton.visible = false;\n\t\t\t}\n\t\t\tmacroButton.visible = false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t}\n\n\t@Override\n\tpublic void drawGuiContainerBackgroundLayer(float f, int i, int j) {\n\t\tfor (GuiButton cycleButton : cycleButtons) {\n\t\t\tcycleButton.visible = _table.targetType != null;\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right - (showRequest ? 0 : 105), bottom, zLevel, true);\n\n\t\tdrawRect(guiLeft + 162, guiTop + 23, guiLeft + 182, guiTop + 43, Color.BLACK);\n\t\tdrawRect(guiLeft + 164, guiTop + 25, guiLeft + 180, guiTop + 41, Color.DARKER_GREY);\n\n\t\tif (showRequest) {\n\t\t\tmc.fontRenderer.drawString(_title, guiLeft + 180 + mc.fontRenderer.getStringWidth(_title) / 2, guiTop + 6, 0x404040);\n\t\t\titemDisplay.renderPageNumber(right - 47, guiTop + 6);\n\n\t\t\tif (buttonList.get(9) instanceof GuiCheckBox && ((GuiCheckBox) buttonList.get(9)).getState()) {\n\t\t\t\tmc.fontRenderer.drawString(\"Popup\", guiLeft + 225, bottom - 56, 0x404040);\n\t\t\t} else {\n\t\t\t\tmc.fontRenderer.drawString(\"Popup\", guiLeft + 225, bottom - 56, Color.getValue(Color.GREY));\n\t\t\t}\n\n\t\t\titemDisplay.renderAmount(getStackAmount());\n\t\t\t//SearchInput\n\t\t\tsearch.drawTextBox();\n\n\t\t\titemDisplay.renderSortMode(right - 103, bottom - 52);\n\t\t\titemDisplay.renderItemArea(zLevel);\n\t\t}\n\n\t\tfor (int x = 0; x < 9; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + (x * 18) + 19, guiTop + (y * 18) + 79);\n\t\t\t}\n\t\t}\n\t\tfor (int x = 0; x < 3; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + (x * 18) + 19, guiTop + (y * 18) + 14);\n\t\t\t}\n\t\t}\n\t\tmc.fontRenderer.drawString(\"Sort:\", guiLeft + 136, guiTop + 55, 0xffffff);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 100, guiTop + 32);\n\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 163, guiTop + 50);\n\t\tdrawRect(guiLeft + 75, guiTop + 38, guiLeft + 95, guiTop + 43, Color.DARKER_GREY);\n\t\tfor (int a = 0; a < 10; a++) {\n\t\t\tdrawRect(guiLeft + 97 - a, guiTop + 40 - a, guiLeft + 98 - a, guiTop + 41 + a, Color.DARKER_GREY);\n\t\t}\n\t\tfor (int a = 0; a < 15; a++) {\n\t\t\tdrawRect(guiLeft + 164 + a, guiTop + 51 + a, guiLeft + 166 + a, guiTop + 53 + a, Color.DARKER_GREY);\n\t\t\tdrawRect(guiLeft + 164 + a, guiTop + 65 - a, guiLeft + 166 + a, guiTop + 67 - a, Color.DARKER_GREY);\n\t\t}\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 20, guiTop + 150);\n\t\tfor (final Entry<Integer, Pair<IResource, LinkedLogisticsOrderList>> entry : _table.watchedRequests.entrySet()) {\n\t\t\tif (!handledExtension.get(entry.getKey())) {\n\t\t\t\thandledExtension.set(entry.getKey());\n\t\t\t\textensionControllerLeft.addExtension(new GuiExtension() {\n\n\t\t\t\t\tprivate Map<Pair<Integer, Integer>, IOrderInfoProvider> ordererPosition = new HashMap<>();\n\t\t\t\t\tprivate int height;\n\t\t\t\t\tprivate int width = 4;\n\t\t\t\t\tprivate GuiButton localControlledButton;\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void renderForeground(int left, int top) {\n\t\t\t\t\t\tif (!_table.watchedRequests.containsKey(entry.getKey())) {\n\t\t\t\t\t\t\textensionControllerLeft.removeExtension(this);\n\t\t\t\t\t\t\tif (isFullyExtended() && localControlledButton != null) {\n\t\t\t\t\t\t\t\tbuttonList.remove(localControlledButton);\n\t\t\t\t\t\t\t\tlocalControlledButton = null;\n\t\t\t\t\t\t\t\torderIdForButton = -1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tordererPosition.clear();\n\t\t\t\t\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\t\t\t\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240 / 1.0F, 240 / 1.0F);\n\t\t\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\t\t\t\tItemStack stack;\n\t\t\t\t\t\tIResource resource = entry.getValue().getValue1();\n\t\t\t\t\t\tString s;\n\t\t\t\t\t\tif (resource != null) {\n\t\t\t\t\t\t\tstack = resource.getDisplayItem().makeNormalStack();\n\t\t\t\t\t\t\titemRender.renderItemAndEffectIntoGUI(stack, left + 5, top + 5);\n\t\t\t\t\t\t\titemRender.renderItemOverlayIntoGUI(mc.fontRenderer, stack, left + 5, top + 5, \"\");\n\t\t\t\t\t\t\ts = TextUtil.getThreeDigitFormattedNumber(stack.getCount(), false);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ts = \"List\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\t\titemRender.zLevel = 0.0F;\n\n\t\t\t\t\t\t// Draw number\n\t\t\t\t\t\tmc.fontRenderer.drawStringWithShadow(s, left + 22 - mc.fontRenderer.getStringWidth(s), top + 14, 16777215);\n\t\t\t\t\t\tif (isFullyExtended()) {\n\t\t\t\t\t\t\tif (localControlledButton == null || orderIdForButton != entry.getKey()) {\n\t\t\t\t\t\t\t\tif (localControlledButton != null) {\n\t\t\t\t\t\t\t\t\tbuttonList.remove(localControlledButton);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tlocalControlledButton = new SmallGuiButton(100, guiLeft - 35, guiTop + 10, 30, 10, \"more\");\n\t\t\t\t\t\t\t\tbuttonList.add(localControlledButton);\n\t\t\t\t\t\t\t\torderIdForButton = entry.getKey();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tList<IOrderInfoProvider> list = entry.getValue().getValue2().getList();\n\t\t\t\t\t\t\tcalculateSize(left, top, list);\n\t\t\t\t\t\t\tString ident = String.format(\"ID: %d\", entry.getKey());\n\t\t\t\t\t\t\tmc.fontRenderer.drawStringWithShadow(ident, left + 25, top + 7, 16777215);\n\t\t\t\t\t\t\tint x = left + 6;\n\t\t\t\t\t\t\tint y = top + 25;\n\t\t\t\t\t\t\tfor (IOrderInfoProvider order : list) {\n\t\t\t\t\t\t\t\tstack = order.getAsDisplayItem().makeNormalStack();\n\t\t\t\t\t\t\t\tif (stack.getCount() <= 0) {\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\t\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\t\t\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\t\t\t\t\t\t\titemRender.renderItemAndEffectIntoGUI(stack, x, y);\n\t\t\t\t\t\t\t\titemRender.renderItemOverlayIntoGUI(fontRenderer, stack, x, y, \"\");\n\t\t\t\t\t\t\t\ts = TextUtil.getThreeDigitFormattedNumber(stack.getCount(), false);\n\t\t\t\t\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\t\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\t\t\t\titemRender.zLevel = 0.0F;\n\n\t\t\t\t\t\t\t\t// Draw number\n\t\t\t\t\t\t\t\tmc.fontRenderer.drawStringWithShadow(s, x + 17 - mc.fontRenderer.getStringWidth(s), y + 9, 16777215);\n\t\t\t\t\t\t\t\tordererPosition.put(new Pair<>(x, y), order);\n\t\t\t\t\t\t\t\tx += 18;\n\t\t\t\t\t\t\t\tif (x > left + getFinalWidth() - 18) {\n\t\t\t\t\t\t\t\t\tx = left + 6;\n\t\t\t\t\t\t\t\t\ty += 18;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (isExtending()) {\n\t\t\t\t\t\t\tList<IOrderInfoProvider> list = entry.getValue().getValue2().getList();\n\t\t\t\t\t\t\tcalculateSize(left, top, list);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!isFullyExtended() && localControlledButton != null) {\n\t\t\t\t\t\t\tbuttonList.remove(localControlledButton);\n\t\t\t\t\t\t\tlocalControlledButton = null;\n\t\t\t\t\t\t\torderIdForButton = -1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tRenderHelper.disableStandardItemLighting();\n\t\t\t\t\t}\n\n\t\t\t\t\tprivate void calculateSize(int left, int top, List<IOrderInfoProvider> list) {\n\t\t\t\t\t\tint x = left + 6;\n\t\t\t\t\t\tint y = 50;\n\t\t\t\t\t\tint line = 1;\n\t\t\t\t\t\twidth = 4;\n\t\t\t\t\t\tfor (IOrderInfoProvider order : list) {\n\t\t\t\t\t\t\tItemStack stack = order.getAsDisplayItem().makeNormalStack();\n\t\t\t\t\t\t\tif (stack.getCount() <= 0) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (line++ % (4 * 4) == 0) {\n\t\t\t\t\t\t\t\twidth++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (IOrderInfoProvider order : list) {\n\t\t\t\t\t\t\tItemStack stack = order.getAsDisplayItem().makeNormalStack();\n\t\t\t\t\t\t\tif (stack.getCount() <= 0) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tx += 18;\n\t\t\t\t\t\t\tif (x > left + getFinalWidth() - 18) {\n\t\t\t\t\t\t\t\tx = left + 6;\n\t\t\t\t\t\t\t\ty += 18;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\theight = y;\n\t\t\t\t\t\tif (x == left + 6) {\n\t\t\t\t\t\t\theight -= 18;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic int getFinalWidth() {\n\t\t\t\t\t\treturn Math.max(85, width * 18 + 8);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic int getFinalHeight() {\n\t\t\t\t\t\treturn Math.max(50, height);\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void handleMouseOverAt(int xPos, int yPos) {\n\t\t\t\t\t\tif (isFullyExtended()) {\n\t\t\t\t\t\t\tordererPosition.keySet().stream()\n\t\t\t\t\t\t\t\t\t.filter(key -> xPos >= key.getValue1() && xPos < key.getValue1() + 18 && yPos >= key\n\t\t\t\t\t\t\t\t\t\t\t.getValue2() && yPos < key.getValue2() + 18).forEach(key -> {\n\t\t\t\t\t\t\t\tIOrderInfoProvider order = ordererPosition.get(key);\n\t\t\t\t\t\t\t\tList<String> list = new ArrayList<>();\n\t\t\t\t\t\t\t\tlist.add(ChatColor.BLUE + \"Request Type: \" + ChatColor.YELLOW + order.getType().name());\n\t\t\t\t\t\t\t\tlist.add(ChatColor.BLUE + \"Send to Router ID: \" + ChatColor.YELLOW + order\n\t\t\t\t\t\t\t\t\t\t.getRouterId());\n\t\t\t\t\t\t\t\tGuiGraphics.displayItemToolTip(new Object[] { xPos - 10, yPos, order\n\t\t\t\t\t\t\t\t\t\t.getAsDisplayItem().makeNormalStack(), true, list }, zLevel, guiLeft, guiTop, false);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (entry.getValue() != null && entry.getValue().getValue1() != null && entry.getValue().getValue1().getDisplayItem() != null) {\n\t\t\t\t\t\t\tList<String> list = new ArrayList<>();\n\t\t\t\t\t\t\tlist.add(ChatColor.BLUE + \"Request ID: \" + ChatColor.YELLOW + entry.getKey());\n\t\t\t\t\t\t\tGuiGraphics.displayItemToolTip(new Object[] { xPos - 10, yPos, entry.getValue().getValue1().getDisplayItem().makeNormalStack(), true, list }, zLevel, guiLeft, guiTop, false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tsuper.renderExtensions();\n\t}\n\n\tpublic void refreshItems() {\n\t\tint integer;\n\t\tswitch (displayOptions) {\n\t\t\tcase Both:\n\t\t\t\tinteger = 0;\n\t\t\t\tbreak;\n\t\t\tcase SupplyOnly:\n\t\t\t\tinteger = 1;\n\t\t\t\tbreak;\n\t\t\tcase CraftOnly:\n\t\t\t\tinteger = 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tinteger = 3;\n\t\t}\n\t\tinteger += (dimension * 10);\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OrdererRefreshRequestPacket.class).setInteger(integer).setTilePos(_table.container));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) {\n\t\tif (guibutton.id == 0 && itemDisplay.getSelectedItem() != null) {\n\t\t\tfinal ItemIdentifierStack stack = itemDisplay.getSelectedItem().getItem().makeStack(itemDisplay.getRequestCount());\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSubmitPacket.class).setStack(stack).setTilePos(_table.container).setDimension(dimension));\n\t\t\trefreshItems();\n\t\t} else if (guibutton.id == 1) {\n\t\t\titemDisplay.nextPage();\n\t\t} else if (guibutton.id == 2) {\n\t\t\titemDisplay.prevPage();\n\t\t} else if (guibutton.id == 3) {\n\t\t\trefreshItems();\n\t\t} else if (guibutton.id == 10) {\n\t\t\titemDisplay.sub(3);\n\t\t} else if (guibutton.id == 4) {\n\t\t\titemDisplay.sub(2);\n\t\t} else if (guibutton.id == 5) {\n\t\t\titemDisplay.sub(1);\n\t\t} else if (guibutton.id == 6) {\n\t\t\titemDisplay.add(1);\n\t\t} else if (guibutton.id == 7) {\n\t\t\titemDisplay.add(2);\n\t\t} else if (guibutton.id == 11) {\n\t\t\titemDisplay.add(3);\n\t\t} else if (guibutton.id == 8) {\n\t\t\tGuiCheckBox button = (GuiCheckBox) guibutton;\n\t\t\tConfigs.DISPLAY_POPUP = button.change();\n\t\t\tConfigs.savePopupState();\n\t\t} else if (guibutton.id == 13 && itemDisplay.getSelectedItem() != null) {\n\t\t\tfinal ItemIdentifierStack stack = itemDisplay.getSelectedItem().getItem().makeStack(itemDisplay.getRequestCount());\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestComponentPacket.class).setStack(stack).setTilePos(_table.container).setDimension(dimension));\n\t\t} else if (guibutton.id == 9) {\n\t\t\tString displayString = \"\";\n\t\t\tswitch (displayOptions) {\n\t\t\t\tcase Both:\n\t\t\t\t\tdisplayOptions = DisplayOptions.CraftOnly;\n\t\t\t\t\tdisplayString = \"Craft\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CraftOnly:\n\t\t\t\t\tdisplayOptions = DisplayOptions.SupplyOnly;\n\t\t\t\t\tdisplayString = \"Supply\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SupplyOnly:\n\t\t\t\t\tdisplayOptions = DisplayOptions.Both;\n\t\t\t\t\tdisplayString = \"Both\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tguibutton.displayString = displayString;\n\t\t\trefreshItems();\n\t\t} else if (guibutton.id == 14) {\n\t\t\trequestMatrix(1);\n\t\t} else if (guibutton.id == 15) {\n\t\t\trequestMatrix(10);\n\t\t} else if (guibutton.id == 16) {\n\t\t\trequestMatrix(64);\n\t\t} else if (guibutton.id == 17) {\n\t\t\t//hideShowButton\n\t\t\t// moveWhileSmall\n\t\t\tshowRequest = !showRequest;\n\t\t\tif (showRequest) {\n\t\t\t\txSize = startXSize;\n\t\t\t\tguiLeft = startLeft;\n\t\t\t\tfor (GuiButton button : moveWhileSmall) {\n\t\t\t\t\tbutton.x -= 105;\n\t\t\t\t}\n\t\t\t\thideShowButton.x -= 90;\n\t\t\t} else {\n\t\t\t\txSize = startXSize - 210;\n\t\t\t\tguiLeft = startLeft + 105;\n\t\t\t\tfor (GuiButton button : moveWhileSmall) {\n\t\t\t\t\tbutton.x += 105;\n\t\t\t\t}\n\t\t\t\thideShowButton.x += 90;\n\t\t\t}\n\t\t\thideShowButton.displayString = showRequest ? \"Hide\" : \"Show\";\n\t\t\tfor (GuiButton button : hideWhileSmall) {\n\t\t\t\tbutton.visible = showRequest;\n\t\t\t}\n\t\t\tmacroButton.visible = showRequest;\n\t\t\torderIdForButton = -1;\n\t\t} else if (guibutton.id == 100) {\n\t\t\textensionControllerLeft.retract();\n\t\t\tsetSubGui(new RequestMonitorPopup(_table, orderIdForButton));\n\t\t} else if (guibutton.id == 18) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiskRequestConectPacket.class).setPosX(_table.getX()).setPosY(_table.getY()).setPosZ(_table.getZ()));\n\t\t\tsetSubGui(new GuiDiskPopup(this));\n\t\t} else if (guibutton.id == 20) {\n\t\t\titemDisplay.cycle();\n\t\t} else if (guibutton.id == 21 || guibutton.id == 22) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(CraftingCycleRecipe.class).setDown(guibutton.id == 22).setTilePos(_table.container));\n\t\t} else if (guibutton.id == 30) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(ClearCraftingGridPacket.class).setTilePos(_table.container));\n\t\t\t_table.cacheRecipe();\n\t\t} else if (guibutton.id == 31) {\n\t\t\tArrayList<ItemIdentifierStack> list = new ArrayList<>(9);\n\t\t\tlist.addAll(_table.matrix.getItemsAndCount().entrySet().stream()\n\t\t\t\t\t.map(e -> e.getKey().makeStack(e.getValue())).collect(Collectors.toList()));\n\t\t\tfor (Pair<ItemStack, Integer> entry : _table.inv) {\n\t\t\t\tif (entry.getValue1().isEmpty()) continue;\n\t\t\t\tint size = entry.getValue1().getCount();\n\t\t\t\tItemIdentifier ident = ItemIdentifier.get(entry.getValue1());\n\t\t\t\tfor (ItemIdentifierStack stack : list) {\n\t\t\t\t\tif (!stack.getItem().equals(ident)) continue;\n\t\t\t\t\tint toUse = Math.min(size, stack.getStackSize());\n\t\t\t\t\tstack.lowerStackSize(toUse);\n\t\t\t\t\tsize -= toUse;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlist.removeIf(itemIdentifierStack -> itemIdentifierStack.getStackSize() <= 0);\n\t\t\tif (!list.isEmpty()) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSubmitListPacket.class).setIdentList(list).setTilePos(_table.container));\n\t\t\t\trefreshItems();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void requestMatrix(int multiplier) {\n\t\tArrayList<ItemIdentifierStack> list = new ArrayList<>(9);\n\t\tlist.addAll(_table.matrix.getItemsAndCount().entrySet().stream()\n\t\t\t\t.map(e -> e.getKey().makeStack(e.getValue() * multiplier)).collect(Collectors.toList()));\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSubmitListPacket.class).setIdentList(list).setTilePos(_table.container));\n\t\trefreshItems();\n\t}\n\n\tprotected int getStackAmount() {\n\t\treturn 64;\n\t}\n\n\tpublic void handlePacket(Collection<ItemIdentifierStack> allItems) {\n\t\titemDisplay.setItemList(allItems.stream().filter(Objects::nonNull).collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic void specialItemRendering(ItemIdentifier item, int x, int y) {\n\t\t//TODO Render Thaumcraft aspects\n\t}\n\n\t@Override\n\tpublic void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tif (super.hasSubGui()) {\n\t\t\treturn;\n\t\t}\n\t\tGuiGraphics.displayItemToolTip(itemDisplay.getToolTip(), this, zLevel, guiLeft, guiTop);\n\t\tmacroButton.enabled = !_table.diskInv.getStackInSlot(0).isEmpty() && _table.diskInv.getStackInSlot(0).getItem().equals(LPItems.disk);\n\t}\n\n\t@Override\n\tpublic boolean itemSearched(ItemIdentifier item) {\n\t\tif (search.isEmpty()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (isSearched(item.getFriendlyName().toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\treturn true;\n\t\t}\n\t\t//if(isSearched(String.valueOf(Item.getIdFromItem(item.item)), search.getContent())) return true;\n\t\t//Enchantment? Enchantment!\n\t\tMap<Enchantment, Integer> enchantIdLvlMap = EnchantmentHelper.getEnchantments(item.unsafeMakeNormalStack(1));\n\t\tfor (Entry<Enchantment, Integer> e : enchantIdLvlMap.entrySet()) {\n\t\t\tif (e.getKey() != null) {\n\t\t\t\tString enchantname = e.getKey().getName();\n\t\t\t\tif (enchantname != null) {\n\t\t\t\t\tif (isSearched(enchantname.toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean isSearched(String value, String search) {\n\t\tboolean flag = true;\n\t\tfor (String s : search.split(\" \")) {\n\t\t\tif (!value.contains(s)) {\n\t\t\t\tflag = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn flag;\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tif (showRequest) {\n\t\t\titemDisplay.handleClick(i, j, k);\n\t\t\tsearch.handleClick(i, j, k);\n\t\t}\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tif (showRequest) {\n\t\t\titemDisplay.handleMouse();\n\t\t}\n\t\tsuper.handleMouseInputSub();\n\t}\n\n\tpublic void handleRequestAnswer(Collection<IResource> items, boolean error, ISubGuiControler control, EntityPlayer player) {\n\t\twhile (control.hasSubGui()) {\n\t\t\tcontrol = control.getSubGui();\n\t\t}\n\t\tif (error) {\n\t\t\tcontrol.setSubGui(new GuiRequestPopup(_entityPlayer, \"You are missing:\", items));\n\t\t} else {\n\t\t\tcontrol.setSubGui(new GuiRequestPopup(_entityPlayer, \"Request successful!\", items));\n\t\t}\n\t}\n\n\tpublic void handleSimulateAnswer(Collection<IResource> used, Collection<IResource> missing, ISubGuiControler control, EntityPlayer player) {\n\t\twhile (control.hasSubGui()) {\n\t\t\tcontrol = control.getSubGui();\n\t\t}\n\t\tcontrol.setSubGui(new GuiRequestPopup(_entityPlayer, \"Components: \", used, \"Missing: \", missing));\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) throws IOException {\n\t\tif (search.isFocused()) {\n\t\t\tif (!search.isEmpty() && search.handleKey(c, i))\n\t\t\t\treturn;\n\t\t} else if (GuiScreen.isAltKeyDown() && ChatAllowedCharacters.isAllowedCharacter(c)) {\n\t\t\titemDisplay.setFocused(false);\n\t\t\tsearch.setFocused(true);\n\t\t\tsearch.setText(\"\");\n\t\t\tsearch.handleKey(c, i);\n\t\t\treturn;\n\t\t}\n\t\tif (!itemDisplay.keyTyped(c, i)) {\n\t\t\t// Track everything except Escape when in search bar\n\t\t\tif (i == 1 || !search.handleKey(c, i)) {\n\t\t\t\tsuper.keyTyped(c, i);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void resetSubGui() {\n\t\tsuper.resetSubGui();\n\t\trefreshItems();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getDisk() {\n\t\treturn _table.diskInv.getStackInSlot(0);\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn _table.getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn _table.getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn _table.getZ();\n\t}\n\n\t@Override\n\tpublic ItemDisplay getItemDisplay() {\n\t\treturn itemDisplay;\n\t}\n\n\tprivate enum DisplayOptions {\n\t\tBoth,\n\t\tSupplyOnly,\n\t\tCraftOnly,\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/orderer/NormalGuiOrderer.java",
    "content": "package logisticspipes.gui.orderer;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.OrdererRefreshRequestPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class NormalGuiOrderer extends GuiOrderer {\n\n\tprivate enum DisplayOptions {\n\t\tBoth,\n\t\tSupplyOnly,\n\t\tCraftOnly,\n\t}\n\n\tprotected DisplayOptions displayOptions = DisplayOptions.Both;\n\n\tpublic NormalGuiOrderer(int x, int y, int z, int dim, EntityPlayer entityPlayer) {\n\t\tsuper(x, y, z, dim, entityPlayer);\n\t\trefreshItems();\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.add(new SmallGuiButton(3, guiLeft + 10, bottom - 15, 46, 10, \"Refresh\")); // Refresh\n\t\tbuttonList.add(new SmallGuiButton(13, guiLeft + 10, bottom - 28, 46, 10, \"Content\")); // Component\n\t\tbuttonList.add(new SmallGuiButton(9, guiLeft + 10, bottom - 41, 46, 10, \"Both\"));\n\t}\n\n\t@Override\n\tpublic void refreshItems() {\n\t\tint integer;\n\t\tswitch (displayOptions) {\n\t\t\tcase Both:\n\t\t\t\tinteger = 0;\n\t\t\t\tbreak;\n\t\t\tcase SupplyOnly:\n\t\t\t\tinteger = 1;\n\t\t\t\tbreak;\n\t\t\tcase CraftOnly:\n\t\t\t\tinteger = 2;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tinteger = 3;\n\t\t}\n\t\tinteger += (dimension * 10);\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OrdererRefreshRequestPacket.class).setInteger(integer).setPosX(xCoord).setPosY(yCoord).setPosZ(zCoord));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tsuper.actionPerformed(guibutton);\n\t\tif (guibutton.id == 9) {\n\t\t\tString displayString = \"\";\n\t\t\tswitch (displayOptions) {\n\t\t\t\tcase Both:\n\t\t\t\t\tdisplayOptions = DisplayOptions.CraftOnly;\n\t\t\t\t\tdisplayString = \"Craft\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase CraftOnly:\n\t\t\t\t\tdisplayOptions = DisplayOptions.SupplyOnly;\n\t\t\t\t\tdisplayString = \"Supply\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase SupplyOnly:\n\t\t\t\t\tdisplayOptions = DisplayOptions.Both;\n\t\t\t\t\tdisplayString = \"Both\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tguibutton.displayString = displayString;\n\t\t\trefreshItems();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void specialItemRendering(ItemIdentifier item, int x, int y) {}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/orderer/NormalMk2GuiOrderer.java",
    "content": "package logisticspipes.gui.orderer;\n\nimport java.io.IOException;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.gui.popup.GuiDiskPopup;\nimport logisticspipes.interfaces.IDiskProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.DiskDropPacket;\nimport logisticspipes.network.packets.orderer.DiskRequestConectPacket;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class NormalMk2GuiOrderer extends NormalGuiOrderer implements IDiskProvider {\n\n\tpublic PipeItemsRequestLogisticsMk2 pipe;\n\tprivate SmallGuiButton macroButton;\n\n\tpublic NormalMk2GuiOrderer(PipeItemsRequestLogisticsMk2 RequestPipeMK2, EntityPlayer entityPlayer) {\n\t\tsuper(RequestPipeMK2.getX(), RequestPipeMK2.getY(), RequestPipeMK2.getZ(), RequestPipeMK2.getWorld().provider.getDimension(), entityPlayer);\n\t\tpipe = RequestPipeMK2;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiskRequestConectPacket.class).setPosX(pipe.getX()).setPosY(pipe.getY()).setPosZ(pipe.getZ()));\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.add(macroButton = new SmallGuiButton(12, right - 55, bottom - 60, 50, 10, \"Disk\"));\n\t\tmacroButton.enabled = false;\n\t}\n\n\t@Override\n\tpublic void drawGuiContainerBackgroundLayer(float f, int i, int j) {\n\t\tsuper.drawGuiContainerBackgroundLayer(f, i, j);\n\n\t\tdrawRect(right - 39, bottom - 47, right - 19, bottom - 27, Color.BLACK);\n\t\tdrawRect(right - 37, bottom - 45, right - 21, bottom - 29, Color.DARKER_GREY);\n\n\t\tif (pipe.getDisk() != null) {\n\t\t\titemRender.renderItemIntoGUI(pipe.getDisk(), right - 37, bottom - 45);\n\t\t\tmacroButton.enabled = true;\n\t\t} else {\n\t\t\tmacroButton.enabled = false;\n\t\t}\n\t\tGL11.glDisable(2896 /*GL_LIGHTING*/);\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int x, int y, int k) throws IOException {\n\t\tif (x >= right - 39 && x < right - 19 && y >= bottom - 47 && y < bottom - 27) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiskDropPacket.class).setPosX(pipe.getX()).setPosY(pipe.getY()).setPosZ(pipe.getZ()));\n\t\t} else {\n\t\t\tsuper.mouseClicked(x, y, k);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tsuper.actionPerformed(guibutton);\n\t\tif (guibutton.id == 12) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiskRequestConectPacket.class).setPosX(pipe.getX()).setPosY(pipe.getY()).setPosZ(pipe.getZ()));\n\t\t\tsetSubGui(new GuiDiskPopup(this));\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getDisk() {\n\t\treturn pipe.getDisk();\n\t}\n\n\t@Override\n\tpublic void specialItemRendering(ItemIdentifier item, int x, int y) {\n\t\t/*\n\t\tGL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);\n\t\tif (SimpleServiceLocator.thaumCraftProxy.isScannedObject(item.unsafeMakeNormalStack(1), mc.thePlayer.getName())) {\n\t\t\tSimpleServiceLocator.thaumCraftProxy.renderAspectsDown(item.unsafeMakeNormalStack(1), -20, 10, this);\n\t\t}\n\t\tGL11.glPopAttrib();\n\t\t*/\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn pipe.getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn pipe.getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn pipe.getZ();\n\t}\n\n\t@Override\n\tpublic ItemDisplay getItemDisplay() {\n\t\treturn itemDisplay;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/ActionChoicePopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\n\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SubGuiScreen;\n\npublic class ActionChoicePopup extends SubGuiScreen {\n\n\tprivate final String message;\n\tprivate final String leftButton;\n\tprivate final Runnable leftAction;\n\tprivate final String rightButton;\n\tprivate final Runnable rightAction;\n\tprivate final boolean buttonMin;\n\n\tpublic ActionChoicePopup(String message, String leftButton, Runnable leftAction, String rightButton, Runnable rightAction) {\n\t\tsuper(100, 100, 0, 0);\n\t\tthis.message = message;\n\t\tthis.leftButton = leftButton;\n\t\tthis.leftAction = leftAction;\n\t\tthis.rightButton = rightButton;\n\t\tthis.rightAction = rightAction;\n\t\tint sizeX = Minecraft.getMinecraft().fontRenderer.getStringWidth(message);\n\t\tint leftX = Minecraft.getMinecraft().fontRenderer.getStringWidth(leftButton);\n\t\tint rightX = Minecraft.getMinecraft().fontRenderer.getStringWidth(rightButton);\n\t\tthis.xSize = Math.max(sizeX + 20, leftX + rightX + 70);\n\t\tthis.ySize = 55;\n\t\tthis.buttonMin = xSize == leftX + rightX + 70;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\n\t\tif (buttonMin) {\n\t\t\tbuttonList.add(new GuiButton(0, guiLeft + 10, guiTop + 25, Minecraft.getMinecraft().fontRenderer.getStringWidth(leftButton) + 20, 20, leftButton));\n\t\t\tbuttonList.add(new GuiButton(1, guiLeft + Minecraft.getMinecraft().fontRenderer.getStringWidth(leftButton) + 40, guiTop + 25,\n\t\t\t\t\tMinecraft.getMinecraft().fontRenderer.getStringWidth(rightButton) + 20, 20, rightButton));\n\t\t} else {\n\t\t\tbuttonList.add(new GuiButton(0, guiLeft + (this.xSize / 4) - ((Minecraft.getMinecraft().fontRenderer.getStringWidth(leftButton) + 20) / 2),\n\t\t\t\t\tguiTop + 25, Minecraft.getMinecraft().fontRenderer.getStringWidth(leftButton) + 20, 20, leftButton));\n\t\t\tbuttonList.add(new GuiButton(1, guiLeft + (this.xSize * 3 / 4) - ((Minecraft.getMinecraft().fontRenderer.getStringWidth(rightButton) + 20) / 2),\n\t\t\t\t\tguiTop + 25, Minecraft.getMinecraft().fontRenderer.getStringWidth(rightButton) + 20, 20, rightButton));\n\t\t}\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tmc.fontRenderer.drawStringWithShadow(message, xCenter - (mc.fontRenderer.getStringWidth(message) / 2f), guiTop + 6, 0xFFFFFF);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tswitch (button.id) {\n\t\t\tcase 0:\n\t\t\t\tleftAction.run();\n\t\t\t\texitGui();\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\trightAction.run();\n\t\t\t\texitGui();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/DisconnectionConfigurationPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.awt.Rectangle;\nimport java.io.IOException;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.ScaledResolution;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.upgrade.ToogleDisconnectionUpgradeSidePacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.gui.UpgradeSlot;\nimport logisticspipes.utils.gui.sideconfig.SideConfigDisplay;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class DisconnectionConfigurationPopup extends SubGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.pipecontroller.popup.\";\n\n\tprivate SideConfigDisplay configDisplay;\n\tprivate CoreRoutedPipe pipe;\n\tprivate Rectangle bounds;\n\tprivate UpgradeSlot pos;\n\n\tpublic DisconnectionConfigurationPopup(CoreRoutedPipe pipe, UpgradeSlot pos) {\n\t\tsuper(250, 250, 0, 0);\n\t\tthis.pipe = pipe;\n\t\tthis.pos = pos;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tconfigDisplay = new SideConfigDisplay(pipe) {\n\n\t\t\t@Override\n\t\t\tpublic void handleSelection(SelectedFace selection) {\n\t\t\t\tDisconnectionConfigurationPopup.this.handleSelection(selection);\n\t\t\t}\n\t\t};\n\t\tconfigDisplay.init();\n\t\tconfigDisplay.renderNeighbours = true;\n\n\t\tbuttonList.add(new GuiButton(0, right - 106, bottom - 26, 100, 20, \"OK\"));\n\n\t\tbounds = new Rectangle(guiLeft + 5, guiTop + 20, this.xSize - 10, this.ySize - 50);\n\t}\n\n\tpublic void handleSelection(SideConfigDisplay.SelectedFace selection) {\n\t\t//ItemStack stack = pipe.getOriginalUpgradeManager().getInv().getStackInSlot(pos);\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(ToogleDisconnectionUpgradeSidePacket.class).setSide(selection.face).setSlot(pos));\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY, float partialTick) {\n\t\tdrawRect(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height, 0xff000000);\n\n\t\tMinecraft mc = Minecraft.getMinecraft();\n\t\tScaledResolution scaledresolution = new ScaledResolution(mc);\n\n\t\tint vpx = bounds.x * scaledresolution.getScaleFactor();\n\t\tint vpy = (bounds.y + 10) * scaledresolution.getScaleFactor();\n\t\tint w = bounds.width * scaledresolution.getScaleFactor();\n\t\tint h = (bounds.height - 1) * scaledresolution.getScaleFactor();\n\n\t\tmc.fontRenderer.drawString(TextUtil\n\t\t\t\t.translate(PREFIX + \"disconnectTitle\"), guiLeft + 8, guiTop + 8, logisticspipes.utils.Color\n\t\t\t\t.getValue(logisticspipes.utils.Color.DARKER_GREY), false);\n\n\t\tconfigDisplay.drawScreen(mouseX, mouseY, partialTick, new Rectangle(vpx, vpy, w, h), bounds);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tsuper.handleMouseInputSub();\n\t\tconfigDisplay.handleMouseInput();\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tswitch (button.id) {\n\t\t\tcase 0:\n\t\t\t\tthis.exitGui();\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiAddChannelPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.UUID;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.AddNewChannelPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiAddChannelPopup extends SubGuiScreen {\n\n\tprivate static String GUI_LANG_KEY = \"gui.popup.addchannel.\";\n\tprotected InputBar textInput = null;\n\tprotected final UUID responsibleSecurityID;\n\n\tpublic GuiAddChannelPopup(UUID responsibleSecurityID) {\n\t\tsuper(118, 140, 0, 0);\n\t\tthis.responsibleSecurityID = responsibleSecurityID;\n\t}\n\n\tprotected GuiAddChannelPopup(UUID responsibleSecurityID, int ySize) {\n\t\tsuper(118, ySize, 0, 0);\n\t\tthis.responsibleSecurityID = responsibleSecurityID;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiCheckBox(0, guiLeft + 94, guiTop + 66, 16, 16, true));\n\t\tbuttonList.add(new GuiCheckBox(1, guiLeft + 94, guiTop + 81, 16, 16, false));\n\t\tbuttonList.add(new GuiCheckBox(2, guiLeft + 94, guiTop + 96, 16, 16, false));\n\n\t\tbuttonList.add(new SmallGuiButton(4, guiLeft + 58, guiTop + 120, 50, 10, TextUtil.translate(GUI_LANG_KEY + \"save\")));\n\n\t\tif (this.textInput == null) {\n\t\t\tthis.textInput = new InputBar(Minecraft.getMinecraft().fontRenderer, this.getBaseScreen(), guiLeft + 30, guiTop + 32, right - guiLeft - 20, 15);\n\t\t}\n\t\tthis.textInput.reposition(guiLeft + 10, guiTop + 34, right - guiLeft - 20, 15);\n\n\t\t((GuiCheckBox) buttonList.get(1)).enabled = responsibleSecurityID != null;\n\t}\n\n\t@Override\n\tpublic void exitGui() {\n\t\tsuper.exitGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t\tgetBaseScreen().initGui();\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tdrawTitle();\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GUI_LANG_KEY + \"name\"), guiLeft + 10, guiTop + 20, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GUI_LANG_KEY + \"access\") + \":\", guiLeft + 10, guiTop + 55, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GUI_LANG_KEY + \"public\"), guiLeft + 10, guiTop + 70, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GUI_LANG_KEY + \"security\"), guiLeft + 10, guiTop + 85, responsibleSecurityID != null ? 0x404040 : 0x808080);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GUI_LANG_KEY + \"private\"), guiLeft + 10, guiTop + 100, 0x404040);\n\t}\n\n\tprotected void drawTitle() {\n\t\tmc.fontRenderer.drawStringWithShadow(\n\t\t\t\tTextUtil.translate(GUI_LANG_KEY + \"title\"), xCenter - (mc.fontRenderer.getStringWidth(TextUtil.translate(GUI_LANG_KEY + \"title\")) / 2f), guiTop + 6, 0xFFFFFF);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {\n\t\tsuper.drawGuiContainerForegroundLayer(mouseX, mouseY);\n\t\ttextInput.drawTextBox();\n\t}\n\n\t@Override\n\tprotected void keyTyped(char par1, int par2) {\n\t\tif (!this.textInput.handleKey(par1, par2)) {\n\t\t\tsuper.keyTyped(par1, par2);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {\n\t\tif (!this.textInput.handleClick(mouseX, mouseY, mouseButton)) {\n\t\t\tsuper.mouseClicked(mouseX, mouseY, mouseButton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) throws IOException {\n\t\tswitch (button.id) {\n\t\t\tcase 0:\n\t\t\t\t((GuiCheckBox) buttonList.get(0)).setState(true);\n\t\t\t\t((GuiCheckBox) buttonList.get(1)).setState(false);\n\t\t\t\t((GuiCheckBox) buttonList.get(2)).setState(false);\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\t((GuiCheckBox) buttonList.get(0)).setState(false);\n\t\t\t\t((GuiCheckBox) buttonList.get(1)).setState(true);\n\t\t\t\t((GuiCheckBox) buttonList.get(2)).setState(false);\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t((GuiCheckBox) buttonList.get(0)).setState(false);\n\t\t\t\t((GuiCheckBox) buttonList.get(1)).setState(false);\n\t\t\t\t((GuiCheckBox) buttonList.get(2)).setState(true);\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tChannelInformation.AccessRights rights = null;\n\t\t\t\tUUID security = null;\n\t\t\t\tif (((GuiCheckBox) buttonList.get(0)).getState()) {\n\t\t\t\t\trights = ChannelInformation.AccessRights.PUBLIC;\n\t\t\t\t} else if (((GuiCheckBox) buttonList.get(1)).getState()) {\n\t\t\t\t\trights = ChannelInformation.AccessRights.SECURED;\n\t\t\t\t\tsecurity = responsibleSecurityID;\n\t\t\t\t} else if (((GuiCheckBox) buttonList.get(2)).getState()) {\n\t\t\t\t\trights = ChannelInformation.AccessRights.PRIVATE;\n\t\t\t\t}\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(AddNewChannelPacket.class).setName(this.textInput.getText()).setRights(rights).setSecurityStationID(security));\n\t\t\t\texitGui();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiAddMacro.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Locale;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.interfaces.IDiskProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.DiscContent;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.IItemSearch;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\n\npublic class GuiAddMacro extends SubGuiScreen implements IItemSearch {\n\n\tprivate final IDiskProvider diskProvider;\n\tprivate int mousePosX = 0;\n\tprivate int mousePosY = 0;\n\tprivate int mouseButton = 0;\n\tprivate int pageAll = 0;\n\tprivate int maxPageAll = 0;\n\tprivate int pageMacro = 0;\n\tprivate int maxPageMacro = 0;\n\tprivate int wheelUp = 0;\n\tprivate int wheelDown = 0;\n\tprivate boolean editSearch = false;\n\tprivate boolean editName = false;\n\tprivate LinkedList<ItemIdentifierStack> macroItems = new LinkedList<>();\n\tprivate String name1;\n\tprivate String name2 = \"\";\n\tprivate String Search1 = \"\";\n\tprivate String Search2 = \"\";\n\tprivate boolean displayCursor = false;\n\tprivate long oldSystemTime = 0;\n\n\tprivate Object[] tooltip;\n\n\tprivate static final int NAME_WIDTH = 122;\n\tprivate static final int SEARCH_WIDTH = 138;\n\n\tpublic GuiAddMacro(IDiskProvider diskProvider, String macroName) {\n\t\tsuper(200, 200, 0, 0);\n\t\tthis.diskProvider = diskProvider;\n\t\tname1 = macroName;\n\t\tloadMacroItems();\n\t}\n\n\tprivate void loadMacroItems() {\n\t\tif ((name1 + name2).equals(\"\")) {\n\t\t\treturn;\n\t\t}\n\t\tNBTTagList inventar = null;\n\n\t\tNBTTagList list = diskProvider.getDisk().getTagCompound().getTagList(\"macroList\", 10);\n\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\tNBTTagCompound tag = list.getCompoundTagAt(i);\n\t\t\tString name = tag.getString(\"name\");\n\t\t\tif (name.equals(name1 + name2)) {\n\t\t\t\tinventar = tag.getTagList(\"inventar\", 10);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (inventar == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (int i = 0; i < inventar.tagCount(); i++) {\n\t\t\tNBTTagCompound itemNBT = inventar.getCompoundTagAt(i);\n\t\t\tint itemID = itemNBT.getInteger(\"id\");\n\t\t\tint itemData = itemNBT.getInteger(\"data\");\n\t\t\tNBTTagCompound tag = null;\n\t\t\tif (itemNBT.hasKey(\"nbt\")) {\n\t\t\t\ttag = itemNBT.getCompoundTag(\"nbt\");\n\t\t\t}\n\t\t\tItemIdentifier item = ItemIdentifier.get(Item.getItemById(itemID), itemData, tag);\n\t\t\tint amount = itemNBT.getInteger(\"amount\");\n\t\t\tItemIdentifierStack stack = new ItemIdentifierStack(item, amount);\n\t\t\tmacroItems.add(stack);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, right - 15, guiTop + 5, 10, 10, \">\")); // Next pageAll\n\t\tbuttonList.add(new SmallGuiButton(1, right - 90, guiTop + 5, 10, 10, \"<\")); // Prev pageAll\n\t\tbuttonList.add(new SmallGuiButton(2, right - 15, guiTop + 135, 10, 10, \">\")); // Next pageAll\n\t\tbuttonList.add(new SmallGuiButton(3, right - 90, guiTop + 135, 10, 10, \"<\")); // Prev pageAll\n\t\tbuttonList.add(new GuiButton(4, right - 39, bottom - 27, 35, 20, \"Save\")); // Prev pageAll\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tmousePosX = i;\n\t\tmousePosY = j;\n\t\tmouseButton = k;\n\t\tint x = i - guiLeft;\n\t\tint y = j - guiTop;\n\t\tif (50 < x && x < 188 && 118 < y && y < 133) {\n\t\t\teditSearch = true;\n\t\t\teditName = false;\n\t\t} else if (37 < x && x < 159 && 176 < y && y < 190) {\n\t\t\teditSearch = false;\n\t\t\teditName = true;\n\t\t} else {\n\t\t\teditSearch = false;\n\t\t\teditName = false;\n\t\t}\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tint wheel = org.lwjgl.input.Mouse.getDWheel() / 120;\n\t\tif (wheel == 0) {\n\t\t\tsuper.handleMouseInputSub();\n\t\t}\n\t\tif (wheel < 0) {\n\t\t\twheelDown = wheel * -1;\n\t\t} else {\n\t\t\twheelUp = wheel;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void renderToolTips(int mouseX, int mouseY, float par3) {\n\t\tif (!hasSubGui()) {\n\t\t\tGuiGraphics.displayItemToolTip(tooltip, zLevel, guiLeft, guiTop, false);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {\n\t\tint panelXSize = 20;\n\t\tint panelYSize = 20;\n\n\t\tint ppi = 0;\n\t\tint column = 0;\n\t\tint row = 0;\n\n\t\tint wheel = org.lwjgl.input.Mouse.getDWheel();\n\t\tif (wheel != 0) {\n\t\t\tif (wheel < 0) {\n\t\t\t\tmouseButton = 0;\n\t\t\t} else {\n\t\t\t\tmouseButton = 1;\n\t\t\t}\n\t\t\tmousePosX = mouseX;\n\t\t\tmousePosY = mouseY;\n\t\t}\n\n\t\ttooltip = null;\n\n\t\tfor (ItemIdentifierStack itemIdStack : diskProvider.getItemDisplay()._allItems) {\n\t\t\tItemIdentifier item = itemIdStack.getItem();\n\t\t\tif (!itemSearched(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tppi++;\n\n\t\t\tif (ppi <= 45 * pageAll) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ppi > 45 * (pageAll + 1)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack st = itemIdStack.unsafeMakeNormalStack();\n\t\t\tint x = guiLeft + 10 + panelXSize * column;\n\t\t\tint y = guiTop + 18 + panelYSize * row;\n\n\t\t\tif (!super.hasSubGui()) {\n\t\t\t\tif (mouseX >= x && mouseX < x + panelXSize && mouseY >= y && mouseY < y + panelYSize) {\n\t\t\t\t\tGui.drawRect(x - 3, y - 1, x + panelXSize - 3, y + panelYSize - 3, Color.getValue(Color.BLACK));\n\t\t\t\t\tGui.drawRect(x - 2, y - 0, x + panelXSize - 4, y + panelYSize - 4, Color.getValue(Color.DARKER_GREY));\n\t\t\t\t\ttooltip = new Object[] { mouseX + guiLeft, mouseY + guiTop, st, false };\n\t\t\t\t}\n\n\t\t\t\tif (mousePosX != 0 && mousePosY != 0) {\n\t\t\t\t\tif ((mousePosX >= x && mousePosX < x + panelXSize && mousePosY >= y && mousePosY < y + panelYSize) || (mouseX >= x && mouseX < x + panelXSize && mouseY >= y && mouseY < y + panelYSize && (wheelDown != 0 || wheelUp != 0))) {\n\t\t\t\t\t\tboolean handled = false;\n\t\t\t\t\t\tfor (ItemIdentifierStack stack : macroItems) {\n\t\t\t\t\t\t\tif (stack.getItem().equals(item)) {\n\t\t\t\t\t\t\t\tif (mouseButton == 0 || wheelUp != 0) {\n\t\t\t\t\t\t\t\t\tstack.setStackSize(stack.getStackSize() + (1 + (wheelUp != 0 ? wheelUp - 1 : 0)));\n\t\t\t\t\t\t\t\t} else if (mouseButton == 1 || wheelDown != 0) {\n\t\t\t\t\t\t\t\t\tstack.setStackSize(stack.getStackSize() - (1 + (wheelDown != 0 ? wheelDown - 1 : 0)));\n\t\t\t\t\t\t\t\t\tif (stack.getStackSize() <= 0) {\n\t\t\t\t\t\t\t\t\t\tmacroItems.remove(stack);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\thandled = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!handled) {\n\t\t\t\t\t\t\tint i = 0;\n\t\t\t\t\t\t\tfor (ItemIdentifierStack stack : macroItems) {\n\t\t\t\t\t\t\t\tif (item.equals(stack.getItem()) && item.itemDamage < stack.getItem().itemDamage) {\n\t\t\t\t\t\t\t\t\tif (mouseButton == 0 || wheelUp != 0) {\n\t\t\t\t\t\t\t\t\t\tmacroItems.add(i, item.makeStack(1 + (wheelUp != 0 ? wheelUp - 1 : 0)));\n\t\t\t\t\t\t\t\t\t} else if (mouseButton == 2) {\n\t\t\t\t\t\t\t\t\t\tmacroItems.add(i, item.makeStack(64));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\thandled = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (Item.getIdFromItem(item.item) < Item.getIdFromItem(stack.getItem().item)) {\n\t\t\t\t\t\t\t\t\tif (mouseButton == 0 || wheelUp != 0) {\n\t\t\t\t\t\t\t\t\t\tmacroItems.add(i, item.makeStack(1 + (wheelUp != 0 ? wheelUp - 1 : 0)));\n\t\t\t\t\t\t\t\t\t} else if (mouseButton == 2) {\n\t\t\t\t\t\t\t\t\t\tmacroItems.add(i, item.makeStack(64));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\thandled = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!handled) {\n\t\t\t\t\t\t\t\tif (mouseButton == 0 || wheelUp != 0) {\n\t\t\t\t\t\t\t\t\tmacroItems.addLast(item.makeStack(1 + (wheelUp != 0 ? wheelUp - 1 : 0)));\n\t\t\t\t\t\t\t\t} else if (mouseButton == 2) {\n\t\t\t\t\t\t\t\t\tmacroItems.addLast(item.makeStack(64));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmousePosX = 0;\n\t\t\t\t\t\tmousePosY = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcolumn++;\n\t\t\tif (column == 9) {\n\t\t\t\trow++;\n\t\t\t\tcolumn = 0;\n\t\t\t}\n\t\t}\n\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(diskProvider.getItemDisplay()._allItems, this, pageAll, guiLeft + 9, guiTop + 17, 9, 45, panelXSize, panelYSize, 100.0F, DisplayAmount.NEVER);\n\n\t\tppi = 0;\n\t\tcolumn = 0;\n\t\trow = 0;\n\n\t\tfor (ItemIdentifierStack itemStack : macroItems) {\n\t\t\tItemIdentifier item = itemStack.getItem();\n\t\t\tif (!itemSearched(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tppi++;\n\n\t\t\tif (ppi <= 9 * pageMacro) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ppi > 9 * (pageMacro + 1)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack st = itemStack.unsafeMakeNormalStack();\n\t\t\tint x = guiLeft + 10 + panelXSize * column;\n\t\t\tint y = guiTop + 150 + panelYSize * row;\n\n\t\t\tif (!super.hasSubGui()) {\n\t\t\t\tif (mouseX >= x && mouseX < x + panelXSize && mouseY >= y && mouseY < y + panelYSize) {\n\t\t\t\t\ttooltip = new Object[] { mouseX + guiLeft, mouseY + guiTop, st };\n\t\t\t\t}\n\t\t\t}\n\t\t\tcolumn++;\n\t\t\tif (column == 9) {\n\t\t\t\trow++;\n\t\t\t\tcolumn = 0;\n\t\t\t}\n\t\t}\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(macroItems, this, pageMacro, guiLeft + 10, guiTop + 150, 9, 9, panelXSize, panelYSize, 100.0F, DisplayAmount.ALWAYS);\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, false);\n\t\tmc.fontRenderer.drawString(\"Add Macro\", guiLeft + mc.fontRenderer.getStringWidth(\"Add Macro\") / 2, guiTop + 6, 0x404040);\n\n\t\tmaxPageAll = (int) Math.floor((getSearchedItemNumber(diskProvider.getItemDisplay()._allItems) - 1) / 45F);\n\t\tif (maxPageAll == -1) {\n\t\t\tmaxPageAll = 0;\n\t\t}\n\t\tif (pageAll > maxPageAll) {\n\t\t\tpageAll = maxPageAll;\n\t\t}\n\n\t\tString pageString1 = \"Page \" + (pageAll + 1) + \" / \" + (maxPageAll + 1);\n\t\tmc.fontRenderer.drawString(pageString1, right - 47 - mc.fontRenderer.getStringWidth(pageString1) / 2, guiTop + 6, 0x404040);\n\n\t\tmc.fontRenderer.drawString(\"Macro Items\", guiLeft + mc.fontRenderer.getStringWidth(\"Add Macro\") / 2, guiTop + 136, 0x404040);\n\n\t\tmaxPageMacro = (int) Math.floor((getSearchedItemNumber(macroItems) - 1) / 9F);\n\t\tif (maxPageMacro == -1) {\n\t\t\tmaxPageMacro = 0;\n\t\t}\n\t\tif (pageMacro > maxPageMacro) {\n\t\t\tpageMacro = maxPageMacro;\n\t\t}\n\n\t\tString pageString2 = \"Page \" + (pageMacro + 1) + \" / \" + (maxPageMacro + 1);\n\t\tmc.fontRenderer.drawString(pageString2, right - 47 - mc.fontRenderer.getStringWidth(pageString2) / 2, guiTop + 136, 0x404040);\n\n\t\tmc.fontRenderer.drawString(\"Search:\", guiLeft + 8, guiTop + 122, 0x404040);\n\n\t\tif (editSearch) {\n\t\t\tGui.drawRect(guiLeft + 50, bottom - 66, right - 10, bottom - 83, Color.getValue(Color.BLACK));\n\t\t\tGui.drawRect(guiLeft + 51, bottom - 67, right - 11, bottom - 82, Color.getValue(Color.WHITE));\n\t\t} else {\n\t\t\tGui.drawRect(guiLeft + 51, bottom - 67, right - 11, bottom - 82, Color.getValue(Color.BLACK));\n\t\t}\n\t\tGui.drawRect(guiLeft + 52, bottom - 68, right - 12, bottom - 81, Color.getValue(Color.DARKER_GREY));\n\n\t\tmc.fontRenderer.drawString(Search1 + Search2, guiLeft + 55, guiTop + 122, 0xFFFFFF);\n\n\t\tif (editSearch) {\n\t\t\tint lineX = guiLeft + 55 + mc.fontRenderer.getStringWidth(Search1);\n\t\t\tif (System.currentTimeMillis() - oldSystemTime > 500) {\n\t\t\t\tdisplayCursor = !displayCursor;\n\t\t\t\toldSystemTime = System.currentTimeMillis();\n\t\t\t}\n\t\t\tif (displayCursor) {\n\t\t\t\tGui.drawRect(lineX, guiTop + 120, lineX + 1, guiTop + 131, Color.getValue(Color.WHITE));\n\t\t\t}\n\t\t}\n\n\t\tmc.fontRenderer.drawString(\"Name:\", guiLeft + 8, bottom - 20, 0x404040);\n\n\t\tif (editName) {\n\t\t\tGui.drawRect(guiLeft + 36, bottom - 8, right - 40, bottom - 25, Color.getValue(Color.BLACK));\n\t\t\tGui.drawRect(guiLeft + 37, bottom - 9, right - 41, bottom - 24, Color.getValue(Color.WHITE));\n\t\t} else {\n\t\t\tGui.drawRect(guiLeft + 37, bottom - 9, right - 41, bottom - 24, Color.getValue(Color.BLACK));\n\t\t}\n\t\tGui.drawRect(guiLeft + 38, bottom - 10, right - 42, bottom - 23, Color.getValue(Color.DARKER_GREY));\n\n\t\tmc.fontRenderer.drawString(name1 + name2, guiLeft + 41, bottom - 20, 0xFFFFFF);\n\n\t\tif (editName) {\n\t\t\tint lineX = guiLeft + 41 + mc.fontRenderer.getStringWidth(name1);\n\t\t\tif (System.currentTimeMillis() - oldSystemTime > 500) {\n\t\t\t\tdisplayCursor = !displayCursor;\n\t\t\t\toldSystemTime = System.currentTimeMillis();\n\t\t\t}\n\t\t\tif (displayCursor) {\n\t\t\t\tGui.drawRect(lineX, bottom - 11, lineX + 1, bottom - 22, Color.getValue(Color.WHITE));\n\t\t\t}\n\t\t}\n\n\t\tGui.drawRect(guiLeft + 6, guiTop + 16, right - 12, bottom - 84, Color.getValue(Color.GREY));\n\t\tGui.drawRect(guiLeft + 6, bottom - 52, right - 12, bottom - 32, Color.getValue(Color.DARKER_GREY));\n\t}\n\n\tprivate int getSearchedItemNumber(List<ItemIdentifierStack> list) {\n\t\tint count = 0;\n\t\tfor (ItemIdentifierStack item : list) {\n\t\t\tif (itemSearched(item.getItem())) {\n\t\t\t\tcount++;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\t@Override\n\tpublic boolean itemSearched(ItemIdentifier item) {\n\t\tif (Search1.isEmpty() && Search2.isEmpty()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (isSearched(item.getFriendlyName().toLowerCase(Locale.US), (Search1 + Search2).toLowerCase(Locale.US))) {\n\t\t\treturn true;\n\t\t}\n\t\treturn isSearched(String.valueOf(Item.getIdFromItem(item.item)), (Search1 + Search2));\n\t}\n\n\tprivate boolean isSearched(String value, String search) {\n\t\tboolean flag = true;\n\t\tfor (String s : search.split(\" \")) {\n\t\t\tif (!value.contains(s)) {\n\t\t\t\tflag = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn flag;\n\t}\n\n\tprivate void nextPageAll() {\n\t\tif (pageAll < maxPageAll) {\n\t\t\tpageAll++;\n\t\t} else {\n\t\t\tpageAll = 0;\n\t\t}\n\t}\n\n\tprivate void prevPageAll() {\n\t\tif (pageAll > 0) {\n\t\t\tpageAll--;\n\t\t} else {\n\t\t\tpageAll = maxPageAll;\n\t\t}\n\t}\n\n\tprivate void nextPageMacro() {\n\t\tif (pageMacro < maxPageMacro) {\n\t\t\tpageMacro++;\n\t\t} else {\n\t\t\tpageMacro = 0;\n\t\t}\n\t}\n\n\tprivate void prevPageMacro() {\n\t\tif (pageMacro > 0) {\n\t\t\tpageMacro--;\n\t\t} else {\n\t\t\tpageMacro = maxPageMacro;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) {\n\t\t\tnextPageAll();\n\t\t} else if (guibutton.id == 1) {\n\t\t\tprevPageAll();\n\t\t} else if (guibutton.id == 2) {\n\t\t\tnextPageMacro();\n\t\t} else if (guibutton.id == 3) {\n\t\t\tprevPageMacro();\n\t\t} else if (guibutton.id == 4) {\n\t\t\tif (!(name1 + name2).equals(\"\") && macroItems.size() != 0) {\n\t\t\t\tNBTTagList inventar = new NBTTagList();\n\t\t\t\tfor (ItemIdentifierStack stack : macroItems) {\n\t\t\t\t\tNBTTagCompound itemNBT = new NBTTagCompound();\n\t\t\t\t\titemNBT.setInteger(\"id\", Item.getIdFromItem(stack.getItem().item));\n\t\t\t\t\titemNBT.setInteger(\"data\", stack.getItem().itemDamage);\n\t\t\t\t\tif (stack.getItem().tag != null) {\n\t\t\t\t\t\titemNBT.setTag(\"nbt\", stack.getItem().tag);\n\t\t\t\t\t}\n\t\t\t\t\titemNBT.setInteger(\"amount\", stack.getStackSize());\n\t\t\t\t\tinventar.appendTag(itemNBT);\n\t\t\t\t}\n\n\t\t\t\tboolean flag = false;\n\t\t\t\tNBTTagList list = diskProvider.getDisk().getTagCompound().getTagList(\"macroList\", 10);\n\n\t\t\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\t\t\tNBTTagCompound tag = list.getCompoundTagAt(i);\n\t\t\t\t\tString name = tag.getString(\"name\");\n\t\t\t\t\tif (name.equals(name1 + name2)) {\n\t\t\t\t\t\tflag = true;\n\t\t\t\t\t\ttag.setTag(\"inventar\", inventar);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!flag) {\n\t\t\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\t\t\tnbt.setString(\"name\", name1 + name2);\n\t\t\t\t\tnbt.setTag(\"inventar\", inventar);\n\t\t\t\t\tlist.appendTag(nbt);\n\t\t\t\t}\n\t\t\t\tdiskProvider.getDisk().getTagCompound().setTag(\"macroList\", list);\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiscContent.class).setStack(diskProvider.getDisk()).setPosX(diskProvider.getX()).setPosY(diskProvider.getY()).setPosZ(diskProvider.getZ()));\n\t\t\t\texitGui();\n\t\t\t} else if (macroItems.size() != 0) {\n\t\t\t\tsetSubGui(new GuiMessagePopup(\"Please enter a name\"));\n\t\t\t} else {\n\t\t\t\tsetSubGui(new GuiMessagePopup(\"Select some items\"));\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) {\n\t\tif (editName) {\n\t\t\tif (c == 13) {\n\t\t\t\teditName = false;\n\t\t\t\treturn;\n\t\t\t} else if (i == 47 && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {\n\t\t\t\tname1 = name1 + GuiScreen.getClipboardString();\n\t\t\t} else if (c == 8) {\n\t\t\t\tif (name1.length() > 0) {\n\t\t\t\t\tname1 = name1.substring(0, name1.length() - 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (Character.isLetterOrDigit(c) || c == ' ') {\n\t\t\t\tif (mc.fontRenderer.getStringWidth(name1 + c + name2) <= NAME_WIDTH) {\n\t\t\t\t\tname1 += c;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (i == 203) { //Left\n\t\t\t\tif (name1.length() > 0) {\n\t\t\t\t\tname2 = name1.substring(name1.length() - 1) + name2;\n\t\t\t\t\tname1 = name1.substring(0, name1.length() - 1);\n\t\t\t\t}\n\t\t\t} else if (i == 205) { //Right\n\t\t\t\tif (name2.length() > 0) {\n\t\t\t\t\tname1 += name2.substring(0, 1);\n\t\t\t\t\tname2 = name2.substring(1);\n\t\t\t\t}\n\t\t\t} else if (i == 1) { //ESC\n\t\t\t\teditName = false;\n\t\t\t} else if (i == 28) { //Enter\n\t\t\t\teditName = false;\n\t\t\t} else if (i == 199) { //Pos\n\t\t\t\tname2 = name1 + name2;\n\t\t\t\tname1 = \"\";\n\t\t\t} else if (i == 207) { //Ende\n\t\t\t\tname1 = name1 + name2;\n\t\t\t\tname2 = \"\";\n\t\t\t} else if (i == 211) { //Entf\n\t\t\t\tif (name2.length() > 0) {\n\t\t\t\t\tname2 = name2.substring(1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (editSearch) {\n\t\t\tif (c == 13) {\n\t\t\t\teditSearch = false;\n\t\t\t\treturn;\n\t\t\t} else if (i == 47 && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {\n\t\t\t\tSearch1 = Search1 + GuiScreen.getClipboardString();\n\t\t\t} else if (c == 8) {\n\t\t\t\tif (Search1.length() > 0) {\n\t\t\t\t\tSearch1 = Search1.substring(0, Search1.length() - 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (Character.isLetterOrDigit(c) || c == ' ') {\n\t\t\t\tif (mc.fontRenderer.getStringWidth(Search1 + c + Search2) <= SEARCH_WIDTH) {\n\t\t\t\t\tSearch1 += c;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (i == 203) { //Left\n\t\t\t\tif (Search1.length() > 0) {\n\t\t\t\t\tSearch2 = Search1.substring(Search1.length() - 1) + Search2;\n\t\t\t\t\tSearch1 = Search1.substring(0, Search1.length() - 1);\n\t\t\t\t}\n\t\t\t} else if (i == 205) { //Right\n\t\t\t\tif (Search2.length() > 0) {\n\t\t\t\t\tSearch1 += Search2.substring(0, 1);\n\t\t\t\t\tSearch2 = Search2.substring(1);\n\t\t\t\t}\n\t\t\t} else if (i == 1) { //ESC\n\t\t\t\teditSearch = false;\n\t\t\t} else if (i == 28) { //Enter\n\t\t\t\teditSearch = false;\n\t\t\t} else if (i == 199) { //Pos\n\t\t\t\tSearch2 = Search1 + Search2;\n\t\t\t\tSearch1 = \"\";\n\t\t\t} else if (i == 207) { //Ende\n\t\t\t\tSearch1 = Search1 + Search2;\n\t\t\t\tSearch2 = \"\";\n\t\t\t} else if (i == 211) { //Entf\n\t\t\t\tif (Search2.length() > 0) {\n\t\t\t\t\tSearch2 = Search2.substring(1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.keyTyped(c, i);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiAddTracking.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.enchantment.Enchantment;\nimport net.minecraft.enchantment.EnchantmentHelper;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.blocks.stats.TrackingTask;\nimport logisticspipes.config.Configs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.AddItemToTrackPacket;\nimport logisticspipes.network.packets.block.RequestAmountTaskSubGui;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.IItemSearch;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiAddTracking extends SubGuiScreen implements IItemSearch {\n\n\tprivate static final String PREFIX = \"gui.networkstatistics.add.\";\n\n\tItemDisplay itemDisplay;\n\tInputBar search;\n\tprivate final LogisticsStatisticsTileEntity tile;\n\n\tpublic GuiAddTracking(LogisticsStatisticsTileEntity tile) {\n\t\tsuper(160, 200, 0, 0);\n\t\tthis.tile = tile;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\n\t\tsuper.initGui();\n\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(3, guiLeft + 4, bottom - 25, 50, 20, \"Refresh\")); // Refresh\n\t\tbuttonList.add(new GuiButton(0, right - 55, bottom - 25, 50, 20, \"Add\"));\n\t\tbuttonList.add(new SmallGuiButton(1, right - 15, guiTop + 5, 10, 10, \">\")); // Next page\n\t\tbuttonList.add(new SmallGuiButton(2, right - 90, guiTop + 5, 10, 10, \"<\")); // Prev page\n\n\t\tbuttonList.add(new SmallGuiButton(20, xCenter - 13, bottom - 21, 26, 10, \"Sort\")); // Sort\n\n\t\tif (search == null) {\n\t\t\tsearch = new InputBar(fontRenderer, getBaseScreen(), guiLeft + 30, bottom - 78, right - guiLeft - 58, 15);\n\t\t}\n\t\tsearch.reposition(guiLeft + 10, bottom - 58, right - guiLeft - 20, 15);\n\n\t\tif (itemDisplay == null) {\n\t\t\titemDisplay = new ItemDisplay(this, fontRenderer, getBaseScreen(), null, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, 0, 0, 0, new int[] { 1, 10, 64, 64 }, true);\n\t\t}\n\t\titemDisplay.reposition(guiLeft + 10, guiTop + 18, xSize - 20, ySize - 80, 0, 0);\n\t}\n\n\t@Override\n\tpublic void exitGui() {\n\t\tsuper.exitGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t\tgetBaseScreen().initGui();\n\t}\n\n\t@Override\n\tprotected void renderToolTips(int mouseX, int mouseY, float par3) {\n\t\tif (!super.hasSubGui()) {\n\t\t\tGuiGraphics.displayItemToolTip(itemDisplay.getToolTip(), this, zLevel, 0, 0);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {\n\t\titemDisplay.renderItemArea(zLevel);\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\t//mc.fontRenderer.drawString(StringUtil.translate(PREFIX + \"title\"), guiLeft + 5, guiTop + 6, 0x404040);\n\t\titemDisplay.renderPageNumber(right - 47, guiTop + 6);\n\n\t\tsearch.drawTextBox();\n\n\t\titemDisplay.renderSortMode(xCenter, bottom - 32);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0 && itemDisplay.getSelectedItem() != null) {\n\t\t\tboolean found = false;\n\t\t\tfor (TrackingTask task : tile.tasks) {\n\t\t\t\tif (task.item.equals(itemDisplay.getSelectedItem().getItem())) {\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (found) {\n\t\t\t\tsetSubGui(new GuiMessagePopup(TextUtil.translate(PREFIX + \"alreadytracked\")));\n\t\t\t} else {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(AddItemToTrackPacket.class).setItem(itemDisplay.getSelectedItem().getItem()).setTilePos(tile));\n\t\t\t\tTrackingTask task = new TrackingTask();\n\t\t\t\ttask.item = itemDisplay.getSelectedItem().getItem();\n\t\t\t\ttile.tasks.add(task);\n\t\t\t\texitGui();\n\t\t\t}\n\t\t} else if (guibutton.id == 1) {\n\t\t\titemDisplay.nextPage();\n\t\t} else if (guibutton.id == 2) {\n\t\t\titemDisplay.prevPage();\n\t\t} else if (guibutton.id == 3) {\n\t\t\trefreshItems();\n\t\t} else if (guibutton.id == 8) {\n\t\t\tGuiCheckBox button = (GuiCheckBox) guibutton;\n\t\t\tConfigs.DISPLAY_POPUP = button.change();\n\t\t\tConfigs.savePopupState();\n\t\t} else if (guibutton.id == 20) {\n\t\t\titemDisplay.cycle();\n\t\t}\n\n\t\tsuper.actionPerformed(guibutton);\n\t}\n\n\tprivate void refreshItems() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestAmountTaskSubGui.class).setTilePos(tile));\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\titemDisplay.handleClick(i, j, k);\n\t\tsearch.handleClick(i, j, k);\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) {\n\t\tif (i == 201) { //PgUp\n\t\t\titemDisplay.prevPage();\n\t\t} else if (i == 209) { //PgDn\n\t\t\titemDisplay.nextPage();\n\t\t} else {\n\t\t\t// Track everything except Escape when in search bar\n\t\t\tif (i == 1 || !search.handleKey(c, i)) {\n\t\t\t\tsuper.keyTyped(c, i);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void handlePacket(List<ItemIdentifierStack> identList) {\n\t\tif (itemDisplay == null) {\n\t\t\titemDisplay = new ItemDisplay(this, fontRenderer, getBaseScreen(), null, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 100, 0, 0, 0, new int[] { 1, 10, 64, 64 }, true);\n\t\t}\n\t\titemDisplay.setItemList(identList);\n\t}\n\n\t@Override\n\tpublic boolean itemSearched(ItemIdentifier item) {\n\t\tif (search.isEmpty()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (isSearched(item.getFriendlyName().toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\treturn true;\n\t\t}\n\t\t//if(isSearched(String.valueOf(Item.getIdFromItem(item.item)), search.getContent())) return true;\n\t\t//Enchantment? Enchantment!\n\t\tMap<Enchantment, Integer> enchantIdLvlMap = EnchantmentHelper.getEnchantments(item.unsafeMakeNormalStack(1));\n\t\tfor (Entry<Enchantment, Integer> e : enchantIdLvlMap.entrySet()) {\n\t\t\tString enchantName = e.getKey().getName();\n\t\t\tif (enchantName != null) {\n\t\t\t\tif (isSearched(enchantName.toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean isSearched(String value, String search) {\n\t\tboolean flag = true;\n\t\tfor (String s : search.split(\" \")) {\n\t\t\tif (!value.contains(s)) {\n\t\t\t\tflag = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn flag;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiDiskPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.interfaces.IDiskProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.DiscContent;\nimport logisticspipes.network.packets.orderer.DiskMacroRequestPacket;\nimport logisticspipes.network.packets.orderer.DiskSetNamePacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.gui.TextListDisplay;\n\npublic class GuiDiskPopup extends SubGuiScreen {\n\n\tprivate boolean editName = false;\n\tprivate boolean displayCursor = false;\n\tprivate long oldSystemTime = 0;\n\tprivate String name1;\n\tprivate String name2;\n\tprivate final IDiskProvider diskProvider;\n\tprivate final TextListDisplay textList;\n\n\tprivate static final int SEARCH_WIDTH = 120;\n\n\tpublic GuiDiskPopup(IDiskProvider diskProvider) {\n\t\tsuper(150, 200, 0, 0);\n\t\tthis.diskProvider = diskProvider;\n\t\tname2 = \"\";\n\t\tif (diskProvider.getDisk().hasTagCompound()) {\n\t\t\tname1 = diskProvider.getDisk().getTagCompound().getString(\"name\");\n\t\t} else {\n\t\t\tname1 = \"Disk\";\n\t\t}\n\t\ttextList = new TextListDisplay(this, 6, 46, 6, 30, 12, new TextListDisplay.List() {\n\n\t\t\t@Override\n\t\t\tpublic int getSize() {\n\t\t\t\tNBTTagCompound nbt = diskProvider.getDisk().getTagCompound();\n\t\t\t\tif (nbt == null) {\n\t\t\t\t\tdiskProvider.getDisk().setTagCompound(new NBTTagCompound());\n\t\t\t\t\tnbt = diskProvider.getDisk().getTagCompound();\n\t\t\t\t}\n\n\t\t\t\tif (!nbt.hasKey(\"macroList\")) {\n\t\t\t\t\tNBTTagList list = new NBTTagList();\n\t\t\t\t\tnbt.setTag(\"macroList\", list);\n\t\t\t\t}\n\t\t\t\tNBTTagList list = nbt.getTagList(\"macroList\", 10);\n\t\t\t\treturn list.tagCount();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String getTextAt(int index) {\n\t\t\t\tNBTTagCompound nbt = diskProvider.getDisk().getTagCompound();\n\t\t\t\tif (nbt == null) {\n\t\t\t\t\tdiskProvider.getDisk().setTagCompound(new NBTTagCompound());\n\t\t\t\t\tnbt = diskProvider.getDisk().getTagCompound();\n\t\t\t\t}\n\n\t\t\t\tif (!nbt.hasKey(\"macroList\")) {\n\t\t\t\t\tNBTTagList list = new NBTTagList();\n\t\t\t\t\tnbt.setTag(\"macroList\", list);\n\t\t\t\t}\n\t\t\t\tNBTTagList list = nbt.getTagList(\"macroList\", 10);\n\t\t\t\treturn list.getCompoundTagAt(index).getString(\"name\");\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getTextColor(int index) {\n\t\t\t\treturn 0xFFFFFF;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tint x = i - guiLeft;\n\t\tint y = j - guiTop;\n\t\ttextList.mouseClicked(i, j, k);\n\t\tif (k == 0) {\n\t\t\tif (10 < x && x < 138 && 29 < y && y < 44) {\n\t\t\t\teditName = true;\n\t\t\t} else if (editName) {\n\t\t\t\twriteDiskName();\n\t\t\t} else {\n\t\t\t\tsuper.mouseClicked(i, j, k);\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.mouseClicked(i, j, k);\n\t\t}\n\t}\n\n\tprivate void writeDiskName() {\n\t\teditName = false;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiskSetNamePacket.class).setString(name1 + name2).setPosX(diskProvider.getX()).setPosY(diskProvider.getY()).setPosZ(diskProvider.getZ()));\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\tif (diskProvider.getDisk().hasTagCompound()) {\n\t\t\tnbt = diskProvider.getDisk().getTagCompound();\n\t\t}\n\t\tnbt.setString(\"name\", name1 + name2);\n\t\tdiskProvider.getDisk().setTagCompound(nbt);\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiscContent.class).setStack(diskProvider.getDisk()).setPosX(diskProvider.getX()).setPosY(diskProvider.getY()).setPosZ(diskProvider.getZ()));\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, xCenter + 16, bottom - 27, 50, 10, \"Request\"));\n\t\tbuttonList.add(new SmallGuiButton(1, xCenter + 16, bottom - 15, 50, 10, \"Exit\"));\n\t\tbuttonList.add(new SmallGuiButton(2, xCenter - 66, bottom - 27, 50, 10, \"Add/Edit\"));\n\t\tbuttonList.add(new SmallGuiButton(3, xCenter - 66, bottom - 15, 50, 10, \"Delete\"));\n\t\tbuttonList.add(new SmallGuiButton(4, xCenter - 12, bottom - 27, 25, 10, \"/\\\\\"));\n\t\tbuttonList.add(new SmallGuiButton(5, xCenter - 12, bottom - 15, 25, 10, \"\\\\/\"));\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tmc.fontRenderer.drawStringWithShadow(\"Disk\", xCenter - (mc.fontRenderer.getStringWidth(\"Disk\") / 2), guiTop + 10, 0xFFFFFF);\n\n\t\t//NameInput\n\t\tif (editName) {\n\t\t\tGui.drawRect(guiLeft + 10, guiTop + 28, right - 10, guiTop + 45, Color.getValue(Color.BLACK));\n\t\t\tGui.drawRect(guiLeft + 11, guiTop + 29, right - 11, guiTop + 44, Color.getValue(Color.WHITE));\n\t\t} else {\n\t\t\tGui.drawRect(guiLeft + 11, guiTop + 29, right - 11, guiTop + 44, Color.getValue(Color.BLACK));\n\t\t}\n\t\tGui.drawRect(guiLeft + 12, guiTop + 30, right - 12, guiTop + 43, Color.getValue(Color.DARKER_GREY));\n\n\t\tmc.fontRenderer.drawString(name1 + name2, guiLeft + 15, guiTop + 33, 0xFFFFFF);\n\n\t\t//Gui.drawRect(guiLeft + 6, guiTop + 46, right - 6, bottom - 30, Color.getValue(Color.GREY));\n\n\t\ttextList.renderGuiBackground(mouseX, mouseY);\n\n\t\tif (editName) {\n\t\t\tint lineX = guiLeft + 15 + mc.fontRenderer.getStringWidth(name1);\n\t\t\tif (System.currentTimeMillis() - oldSystemTime > 500) {\n\t\t\t\tdisplayCursor = !displayCursor;\n\t\t\t\toldSystemTime = System.currentTimeMillis();\n\t\t\t}\n\t\t\tif (displayCursor) {\n\t\t\t\tGui.drawRect(lineX, guiTop + 31, lineX + 1, guiTop + 42, Color.getValue(Color.WHITE));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tint wheel = org.lwjgl.input.Mouse.getDWheel() / 120;\n\t\tif (wheel == 0) {\n\t\t\tsuper.handleMouseInputSub();\n\t\t}\n\t\tif (wheel < 0) {\n\t\t\ttextList.scrollUp();\n\t\t} else if (wheel > 0) {\n\t\t\ttextList.scrollDown();\n\t\t}\n\t}\n\n\tprivate void handleRequest() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiskMacroRequestPacket.class).setInteger(textList.getSelected()).setPosX(diskProvider.getX()).setPosY(diskProvider.getY()).setPosZ(diskProvider.getZ()));\n\t}\n\n\tprivate void handleDelete() {\n\t\tNBTTagCompound nbt = diskProvider.getDisk().getTagCompound();\n\t\tif (nbt == null) {\n\t\t\tdiskProvider.getDisk().setTagCompound(new NBTTagCompound());\n\t\t\tnbt = diskProvider.getDisk().getTagCompound();\n\t\t}\n\n\t\tif (!nbt.hasKey(\"macroList\")) {\n\t\t\tNBTTagList list = new NBTTagList();\n\t\t\tnbt.setTag(\"macroList\", list);\n\t\t}\n\n\t\tNBTTagList list = nbt.getTagList(\"macroList\", 10);\n\t\tNBTTagList newList = new NBTTagList();\n\n\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\tif (i != textList.getSelected()) {\n\t\t\t\tnewList.appendTag(list.getCompoundTagAt(i));\n\t\t\t}\n\t\t}\n\t\ttextList.setSelected(-1);\n\t\tnbt.setTag(\"macroList\", newList);\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DiscContent.class).setStack(diskProvider.getDisk()).setPosX(diskProvider.getX()).setPosY(diskProvider.getY()).setPosZ(diskProvider.getZ()));\n\t}\n\n\tprivate void handleAddEdit() {\n\t\tString macroName = \"\";\n\t\tNBTTagCompound nbt = diskProvider.getDisk().getTagCompound();\n\t\tif (nbt != null) {\n\t\t\tif (nbt.hasKey(\"macroList\")) {\n\t\t\t\tNBTTagList list = nbt.getTagList(\"macroList\", 10);\n\t\t\t\tif (textList.getSelected() != -1 && textList.getSelected() < list.tagCount()) {\n\t\t\t\t\tNBTTagCompound entry = list.getCompoundTagAt(textList.getSelected());\n\t\t\t\t\tmacroName = entry.getString(\"name\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsetSubGui(new GuiAddMacro(diskProvider, macroName));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) {\n\t\t\thandleRequest();\n\t\t} else if (guibutton.id == 1) {\n\t\t\texitGui();\n\t\t} else if (guibutton.id == 2) {\n\t\t\thandleAddEdit();\n\t\t} else if (guibutton.id == 3) {\n\t\t\thandleDelete();\n\t\t} else if (guibutton.id == 4) {\n\t\t\ttextList.scrollDown();\n\t\t} else if (guibutton.id == 5) {\n\t\t\ttextList.scrollUp();\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) {\n\t\tif (editName) {\n\t\t\tif (c == 13) {\n\t\t\t\twriteDiskName();\n\t\t\t\treturn;\n\t\t\t} else if (i == 47 && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {\n\t\t\t\tname1 = name1 + GuiScreen.getClipboardString();\n\t\t\t} else if (c == 8) {\n\t\t\t\tif (name1.length() > 0) {\n\t\t\t\t\tname1 = name1.substring(0, name1.length() - 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (Character.isLetterOrDigit(c) || c == ' ') {\n\t\t\t\tif (mc.fontRenderer.getStringWidth(name1 + c + name2) <= SEARCH_WIDTH) {\n\t\t\t\t\tname1 += c;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (i == 203) { //Left\n\t\t\t\tif (name1.length() > 0) {\n\t\t\t\t\tname2 = name1.substring(name1.length() - 1) + name2;\n\t\t\t\t\tname1 = name1.substring(0, name1.length() - 1);\n\t\t\t\t}\n\t\t\t} else if (i == 205) { //Right\n\t\t\t\tif (name2.length() > 0) {\n\t\t\t\t\tname1 += name2.substring(0, 1);\n\t\t\t\t\tname2 = name2.substring(1);\n\t\t\t\t}\n\t\t\t} else if (i == 1) { //ESC\n\t\t\t\twriteDiskName();\n\t\t\t} else if (i == 28) { //Enter\n\t\t\t\twriteDiskName();\n\t\t\t} else if (i == 199) { //Pos\n\t\t\t\tname2 = name1 + name2;\n\t\t\t\tname1 = \"\";\n\t\t\t} else if (i == 207) { //Ende\n\t\t\t\tname1 = name1 + name2;\n\t\t\t\tname2 = \"\";\n\t\t\t} else if (i == 211) { //Entf\n\t\t\t\tif (name2.length() > 0) {\n\t\t\t\t\tname2 = name2.substring(1);\n\t\t\t\t}\n\t\t\t}\n\t\t\t//\t\t} else if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)){\n\t\t\t//\t\t\tsuper.keyTyped(c, i);\n\t\t\t//\t\t} else if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)){\n\t\t\t//\t\t\tsuper.keyTyped(c, i);\n\t\t} else {\n\t\t\tsuper.keyTyped(c, i);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiEditCCAccessTable.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.Collections;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.GuiScreen;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.SecurityAddCCIdPacket;\nimport logisticspipes.network.packets.block.SecurityRemoveCCIdPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiEditCCAccessTable extends SubGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.securitystation.popup.ccAccess.\";\n\n\tprivate final LogisticsSecurityTileEntity _tile;\n\n\tprivate String searchInput1 = \"0\";\n\tprivate String searchInput2 = \"\";\n\tprivate boolean editSearch = false;\n\tprivate boolean editSearchB = false;\n\tprivate boolean displayCursor = true;\n\tprivate long oldSystemTime = 0;\n\tprivate static int searchWidth = 55;\n\tprivate int lastClickedX = 0;\n\tprivate int lastClickedY = 0;\n\tprivate int lastClickedK = 0;\n\tprivate boolean clickWasButton = false;\n\tprivate int page = 0;\n\n\tpublic GuiEditCCAccessTable(LogisticsSecurityTileEntity tile) {\n\t\tsuper(150, 150, 0, 0);\n\t\t_tile = tile;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, guiLeft + 10, guiTop + 119, 30, 20, \"-\"));\n\t\tbuttonList.add(new GuiButton(1, guiLeft + 110, guiTop + 119, 30, 20, \"+\"));\n\t\tbuttonList.add(new SmallGuiButton(2, guiLeft + 30, guiTop + 107, 40, 10, TextUtil.translate(GuiEditCCAccessTable.PREFIX + \"Remove\")));\n\t\tbuttonList.add(new SmallGuiButton(3, guiLeft + 80, guiTop + 107, 40, 10, TextUtil.translate(GuiEditCCAccessTable.PREFIX + \"Add\")));\n\t\tbuttonList.add(new SmallGuiButton(4, guiLeft + 87, guiTop + 4, 10, 10, \"<\"));\n\t\tbuttonList.add(new SmallGuiButton(5, guiLeft + 130, guiTop + 4, 10, 10, \">\"));\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tmc.fontRenderer.drawString(\"(\" + (page + 1) + \"/\" + ((int) ((_tile.excludedCC.size() / 9D) + 1 - (_tile.excludedCC.size() % 9 == 0 && _tile.excludedCC.size() != 0 ? 1 : 0))) + \")\", guiLeft + 100, guiTop + 5, 0x4F4F4F);\n\n\t\tboolean dark = true;\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tdrawRect(guiLeft + 10, guiTop + 15 + (i * 10), right - 10, guiTop + 25 + (i * 10), dark ? Color.DARKER_GREY : Color.LIGHTER_GREY);\n\t\t\tdark = !dark;\n\t\t}\n\t\tdark = true;\n\t\tfor (int i = 0; i < 9 && i + (page * 9) < _tile.excludedCC.size(); i++) {\n\t\t\tInteger id = _tile.excludedCC.get(i + (page * 9));\n\t\t\tmc.fontRenderer.drawString(Integer.toString(id), guiLeft + 75 - (mc.fontRenderer.getStringWidth(Integer.toString(id)) / 2), guiTop + 16 + (i * 10), dark ? 0xFFFFFF : 0x000000);\n\t\t\tdark = !dark;\n\t\t\tif (lastClickedX >= guiLeft + 10 && lastClickedX < right - 10 && lastClickedY >= guiTop + 15 + (i * 10) && lastClickedY < guiTop + 25 + (i * 10)) {\n\t\t\t\tlastClickedX = -10000000;\n\t\t\t\tlastClickedY = -10000000;\n\t\t\t\tsearchInput1 = Integer.toString(id);\n\t\t\t\tsearchInput2 = \"\";\n\t\t\t}\n\t\t}\n\n\t\t//SearchInput\n\t\tif (editSearch) {\n\t\t\tdrawRect(guiLeft + 40, bottom - 30, right - 40, bottom - 13, Color.BLACK);\n\t\t\tdrawRect(guiLeft + 41, bottom - 29, right - 41, bottom - 14, Color.WHITE);\n\t\t} else {\n\t\t\tdrawRect(guiLeft + 41, bottom - 29, right - 41, bottom - 14, Color.BLACK);\n\t\t}\n\t\tdrawRect(guiLeft + 42, bottom - 28, right - 42, bottom - 15, Color.DARKER_GREY);\n\n\t\tmc.fontRenderer.drawString(searchInput1 + searchInput2, guiLeft + 75 - (mc.fontRenderer.getStringWidth(searchInput1 + searchInput2) / 2), bottom - 25, 0xFFFFFF);\n\t\tif (editSearch) {\n\t\t\tint lineX = guiLeft + 75 + mc.fontRenderer.getStringWidth(searchInput1) - (mc.fontRenderer.getStringWidth(searchInput1 + searchInput2) / 2);\n\t\t\tif (System.currentTimeMillis() - oldSystemTime > 500) {\n\t\t\t\tdisplayCursor = !displayCursor;\n\t\t\t\toldSystemTime = System.currentTimeMillis();\n\t\t\t}\n\t\t\tif (displayCursor) {\n\t\t\t\tdrawRect(lineX, bottom - 27, lineX + 1, bottom - 16, Color.WHITE);\n\t\t\t}\n\t\t}\n\n\t\t//Click into search\n\t\tif (lastClickedX != -10000000 && lastClickedY != -10000000) {\n\t\t\tif (lastClickedX >= guiLeft + 42 && lastClickedX < right - 42 && lastClickedY >= bottom - 30 && lastClickedY < bottom - 13) {\n\t\t\t\teditSearch = true;\n\t\t\t\tif (searchInput1.equals(\"0\") && searchInput2.length() == 0) {\n\t\t\t\t\tsearchInput1 = \"\";\n\t\t\t\t}\n\t\t\t\tlastClickedX = -10000000;\n\t\t\t\tlastClickedY = -10000000;\n\t\t\t\tif (lastClickedK == 1) {\n\t\t\t\t\tsearchInput1 = \"0\";\n\t\t\t\t\tsearchInput2 = \"\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\teditSearch = false;\n\t\t\t\tif (searchInput1.length() == 0 && searchInput2.length() == 0) {\n\t\t\t\t\tsearchInput1 = \"0\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\tclickWasButton = false;\n\t\teditSearchB = true;\n\t\tsuper.mouseClicked(i, j, k);\n\t\tif ((!clickWasButton && i >= guiLeft + 10 && i < right - 10 && j >= guiTop + 18 && j < bottom - 10) || editSearch) {\n\t\t\tif (!editSearchB) {\n\t\t\t\teditSearch = false;\n\t\t\t}\n\t\t\tlastClickedX = i;\n\t\t\tlastClickedY = j;\n\t\t\tlastClickedK = k;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) {\n\t\tif (editSearch) {\n\t\t\teditSearchB = false;\n\t\t}\n\t\tclickWasButton = true;\n\t\tswitch (guibutton.id) {\n\t\t\tcase 0:\n\t\t\t\tif ((searchInput1 + searchInput2).equals(\"\")) {\n\t\t\t\t\tsearchInput1 = \"0\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tint number = Integer.valueOf(searchInput1 + searchInput2);\n\t\t\t\t\tnumber--;\n\t\t\t\t\tif (number < 0) {\n\t\t\t\t\t\tnumber = 0;\n\t\t\t\t\t}\n\t\t\t\t\tsearchInput1 = Integer.toString(number);\n\t\t\t\t\tsearchInput2 = \"\";\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t\tsearchInput1 = \"0\";\n\t\t\t\t\tsearchInput2 = \"\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif ((searchInput1 + searchInput2).equals(\"\")) {\n\t\t\t\t\tsearchInput1 = \"1\";\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tint number = Integer.valueOf(searchInput1 + searchInput2);\n\t\t\t\t\tnumber++;\n\t\t\t\t\tif (mc.fontRenderer.getStringWidth(Integer.toString(number)) <= GuiEditCCAccessTable.searchWidth) {\n\t\t\t\t\t\tsearchInput1 = Integer.toString(number);\n\t\t\t\t\t\tsearchInput2 = \"\";\n\t\t\t\t\t}\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t\tsearchInput1 = \"0\";\n\t\t\t\t\tsearchInput2 = \"\";\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2: {\n\t\t\t\tInteger id = Integer.valueOf(searchInput1 + searchInput2);\n\t\t\t\t_tile.excludedCC.remove(id);\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityRemoveCCIdPacket.class).setInteger(id).setBlockPos(_tile.getPos()));\n\t\t\t}\n\t\t\tbreak;\n\t\t\tcase 3: {\n\t\t\t\tInteger id = Integer.valueOf(searchInput1 + searchInput2);\n\t\t\t\tif (!_tile.excludedCC.contains(id)) {\n\t\t\t\t\t_tile.excludedCC.add(id);\n\t\t\t\t\tCollections.sort(_tile.excludedCC);\n\t\t\t\t}\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SecurityAddCCIdPacket.class).setInteger(id).setBlockPos(_tile.getPos()));\n\t\t\t}\n\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tpage--;\n\t\t\t\tif (page < 0) {\n\t\t\t\t\tpage = 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tpage++;\n\t\t\t\tif (page > (_tile.excludedCC.size() / 9) - (_tile.excludedCC.size() % 9 == 0 && _tile.excludedCC.size() != 0 ? 1 : 0)) {\n\t\t\t\t\tpage = (_tile.excludedCC.size() / 9) - (_tile.excludedCC.size() % 9 == 0 && _tile.excludedCC.size() != 0 ? 1 : 0);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tprotected void keyTyped(char c, int i) {\n\t\tif (editSearch) {\n\t\t\tif (c == 13) {\n\t\t\t\teditSearch = false;\n\t\t\t\treturn;\n\t\t\t} else if (i == 47 && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {\n\t\t\t\ttry {\n\t\t\t\t\tInteger.valueOf(GuiScreen.getClipboardString());\n\t\t\t\t\tsearchInput1 = searchInput1 + GuiScreen.getClipboardString();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tsetSubGui(new GuiMessagePopup(\"Clipboard doesn't\", \"contain a number.\"));\n\t\t\t\t}\n\t\t\t} else if (c == 8) {\n\t\t\t\tif (searchInput1.length() > 0) {\n\t\t\t\t\tsearchInput1 = searchInput1.substring(0, searchInput1.length() - 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (Character.isDigit(c)) {\n\t\t\t\tif (mc.fontRenderer.getStringWidth(searchInput1 + c + searchInput2) <= GuiEditCCAccessTable.searchWidth) {\n\t\t\t\t\tsearchInput1 += c;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else if (i == 203) { //Left\n\t\t\t\tif (searchInput1.length() > 0) {\n\t\t\t\t\tsearchInput2 = searchInput1.substring(searchInput1.length() - 1) + searchInput2;\n\t\t\t\t\tsearchInput1 = searchInput1.substring(0, searchInput1.length() - 1);\n\t\t\t\t}\n\t\t\t} else if (i == 205) { //Right\n\t\t\t\tif (searchInput2.length() > 0) {\n\t\t\t\t\tsearchInput1 += searchInput2.substring(0, 1);\n\t\t\t\t\tsearchInput2 = searchInput2.substring(1);\n\t\t\t\t}\n\t\t\t} else if (i == 1) { //ESC\n\t\t\t\teditSearch = false;\n\t\t\t} else if (i == 28) { //Enter\n\t\t\t\teditSearch = false;\n\t\t\t} else if (i == 199) { //Pos\n\t\t\t\tsearchInput2 = searchInput1 + searchInput2;\n\t\t\t\tsearchInput1 = \"\";\n\t\t\t} else if (i == 207) { //Ende\n\t\t\t\tsearchInput1 = searchInput1 + searchInput2;\n\t\t\t\tsearchInput2 = \"\";\n\t\t\t} else if (i == 211) { //Entf\n\t\t\t\tif (searchInput2.length() > 0) {\n\t\t\t\t\tsearchInput2 = searchInput2.substring(1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.keyTyped(c, i);\n\t\t}\n\t}\n\n\tpublic void drawRect(int x1, int y1, int x2, int y2, Color color) {\n\t\tGui.drawRect(x1, y1, x2, y2, Color.getValue(color));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiEditChannelPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.UUID;\n\nimport net.minecraft.client.gui.GuiButton;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.EditChannelPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiEditChannelPopup extends GuiAddChannelPopup {\n\n\tprivate static String GUI_LANG_KEY = \"gui.popup.editchannel.\";\n\tprivate final UUID channelIdentifier;\n\tprivate ChannelInformation toInit;\n\n\tpublic GuiEditChannelPopup(UUID correspondingSecurityStationID, ChannelInformation toEdit) {\n\t\tsuper(correspondingSecurityStationID, 160);\n\t\tthis.channelIdentifier = toEdit.getChannelIdentifier();\n\t\ttoInit = toEdit;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.remove(buttonList.size() - 1);\n\t\tbuttonList.add(new SmallGuiButton(5, guiLeft + 58, guiTop + 140, 50, 10, TextUtil.translate(GUI_LANG_KEY + \"save\")));\n\t\tif (toInit != null) {\n\t\t\tthis.textInput.setText(toInit.getName());\n\t\t\t((GuiCheckBox) buttonList.get(0)).setState(toInit.getRights() == ChannelInformation.AccessRights.PUBLIC);\n\t\t\t((GuiCheckBox) buttonList.get(1)).setState(toInit.getRights() == ChannelInformation.AccessRights.SECURED);\n\t\t\t((GuiCheckBox) buttonList.get(2)).setState(toInit.getRights() == ChannelInformation.AccessRights.PRIVATE);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tsuper.renderGuiBackground(mouseX, mouseY);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GUI_LANG_KEY + \"owner\") + \": \", guiLeft + 10, guiTop + 115, 0x404040);\n\t\tmc.fontRenderer.drawString(toInit.getOwner().getUsername(), guiLeft + 10, guiTop + 127, 0x404040);\n\t}\n\n\t@Override\n\tprotected void drawTitle() {\n\t\tmc.fontRenderer.drawStringWithShadow(TextUtil.translate(GUI_LANG_KEY + \"title\"), xCenter - (mc.fontRenderer.getStringWidth(TextUtil.translate(GUI_LANG_KEY + \"title\")) / 2f), guiTop + 6, 0xFFFFFF);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) throws IOException {\n\t\tsuper.actionPerformed(button);\n\t\tswitch (button.id) {\n\t\t\tcase 5:\n\t\t\t\tChannelInformation.AccessRights rights = null;\n\t\t\t\tUUID security = null;\n\t\t\t\tif (((GuiCheckBox) buttonList.get(0)).getState()) {\n\t\t\t\t\trights = ChannelInformation.AccessRights.PUBLIC;\n\t\t\t\t} else if (((GuiCheckBox) buttonList.get(1)).getState()) {\n\t\t\t\t\trights = ChannelInformation.AccessRights.SECURED;\n\t\t\t\t\tsecurity = responsibleSecurityID;\n\t\t\t\t} else if (((GuiCheckBox) buttonList.get(2)).getState()) {\n\t\t\t\t\trights = ChannelInformation.AccessRights.PRIVATE;\n\t\t\t\t}\n\t\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\t\tPacketHandler.getPacket(EditChannelPacket.class).setChannelIdentifier(channelIdentifier).setName(this.textInput.getText()).setRights(rights).setSecurityStationID(security));\n\t\t\t\texitGui();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiManageChannelPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.List;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.interfaces.IGUIChannelInformationReceiver;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.DeleteChannelPacket;\nimport logisticspipes.network.packets.gui.OpenAddChannelGUIPacket;\nimport logisticspipes.network.packets.gui.OpenEditChannelGUIPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.gui.TextListDisplay;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiManageChannelPopup extends SubGuiScreen implements IGUIChannelInformationReceiver {\n\n\tprivate static String GUI_LANG_KEY = \"gui.popup.managechannel.\";\n\n\tprotected final List<ChannelInformation> channelList;\n\tprotected final TextListDisplay textList;\n\tprivate BlockPos position;\n\n\tpublic GuiManageChannelPopup(List<ChannelInformation> channelList, BlockPos pos) {\n\t\tsuper(150, 170, 0, 0);\n\t\tthis.channelList = channelList;\n\t\tthis.position = pos;\n\t\tthis.textList = new TextListDisplay(this, 6, 16, 6, 30, 12, new TextListDisplay.List() {\n\n\t\t\t@Override\n\t\t\tpublic int getSize() {\n\t\t\t\treturn channelList.size();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String getTextAt(int index) {\n\t\t\t\treturn channelList.get(index).getName();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getTextColor(int index) {\n\t\t\t\treturn 0xFFFFFF;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(10, xCenter + 16, bottom - 27, 50, 10, \"Delete\"));\n\t\tbuttonList.add(new SmallGuiButton(1, xCenter + 16, bottom - 15, 50, 10, \"Exit\"));\n\t\tbuttonList.add(new SmallGuiButton(2, xCenter - 66, bottom - 27, 50, 10, \"Add\"));\n\t\tbuttonList.add(new SmallGuiButton(3, xCenter - 66, bottom - 15, 50, 10, \"Edit\"));\n\t\tbuttonList.add(new SmallGuiButton(4, xCenter - 12, bottom - 27, 25, 10, \"/\\\\\"));\n\t\tbuttonList.add(new SmallGuiButton(5, xCenter - 12, bottom - 15, 25, 10, \"\\\\/\"));\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tdrawTitle();\n\n\t\ttextList.renderGuiBackground(mouseX, mouseY);\n\t}\n\n\tprotected void drawTitle() {\n\t\tmc.fontRenderer.drawStringWithShadow(\n\t\t\t\tTextUtil.translate(GUI_LANG_KEY + \"title\"), xCenter - (mc.fontRenderer.getStringWidth(TextUtil.translate(GUI_LANG_KEY + \"title\")) / 2f), guiTop + 6, 0xFFFFFF);\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\ttextList.mouseClicked(i, j, k);\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tint wheel = org.lwjgl.input.Mouse.getDWheel() / 120;\n\t\tif (wheel == 0) {\n\t\t\tsuper.handleMouseInputSub();\n\t\t}\n\t\tif (wheel < 0) {\n\t\t\ttextList.scrollUp();\n\t\t} else if (wheel > 0) {\n\t\t\ttextList.scrollDown();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 1) { // Exit\n\t\t\texitGui();\n\t\t} else if (guibutton.id == 2) { // Add\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OpenAddChannelGUIPacket.class).setBlockPos(position));\n\t\t} else if (guibutton.id == 3) { // Edit\n\t\t\tint selected = textList.getSelected();\n\t\t\tif (selected >= 0) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OpenEditChannelGUIPacket.class).setIdentifier(channelList.get(selected).getChannelIdentifier().toString()).setBlockPos(position));\n\t\t\t}\n\t\t} else if (guibutton.id == 4) {\n\t\t\ttextList.scrollDown();\n\t\t} else if (guibutton.id == 5) {\n\t\t\ttextList.scrollUp();\n\t\t} else if (guibutton.id == 10) {\n\t\t\tint selected = textList.getSelected();\n\t\t\tif (selected >= 0) {\n\t\t\t\tthis.setSubGui(new ActionChoicePopup(TextUtil.translate(GUI_LANG_KEY + \"deletedialog.title\"), TextUtil.translate(GUI_LANG_KEY + \"deletedialog.yes\"), () ->\n\t\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DeleteChannelPacket.class).setChannelIdentifier(channelList.get(selected).getChannelIdentifier())),\n\t\t\t\t\t\tTextUtil.translate(GUI_LANG_KEY + \"deletedialog.no\"), () -> {}));\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleChannelInformation(ChannelInformation channel, boolean flag) {\n\t\tif (!flag) {\n\t\t\tif (channel.getName() == null) {\n\t\t\t\tchannelList.removeIf(chan -> chan.getChannelIdentifier().equals(channel.getChannelIdentifier()));\n\t\t\t} else {\n\t\t\t\tif (channelList.stream().anyMatch(chan -> chan.getChannelIdentifier().equals(channel.getChannelIdentifier()))) {\n\t\t\t\t\tchannelList.stream().filter(chan -> chan.getChannelIdentifier().equals(channel.getChannelIdentifier())).forEach(chan -> {\n\t\t\t\t\t\tchan.setName(channel.getName());\n\t\t\t\t\t\tchan.setRights(channel.getRights());\n\t\t\t\t\t\tchan.setResponsibleSecurityID(channel.getResponsibleSecurityID());\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tchannelList.add(channel);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiMessagePopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport net.minecraft.client.gui.GuiButton;\n\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiMessagePopup extends SubGuiScreen {\n\n\tprivate String[] text;\n\tprivate int mWidth = 0;\n\n\tpublic GuiMessagePopup(Object... message) {\n\t\tsuper(200, (message.length * 10) + 40, 0, 0);\n\t\ttext = new String[message.length];\n\t\tint i = 0;\n\t\tfor (Object o : message) {\n\t\t\tif (o instanceof Object[]) {\n\t\t\t\tfor (Object oZwei : (Object[]) o) {\n\t\t\t\t\ttext[i++] = oZwei.toString();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttext[i++] = o.toString();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, xCenter - 25, bottom - 25, 50, 20, \"OK\"));\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tif (mWidth == 0) {\n\t\t\tint lWidth = 0;\n\t\t\tfor (String msg : text) {\n\t\t\t\tint tWidth = mc.fontRenderer.getStringWidth(msg);\n\t\t\t\tif (tWidth > lWidth) {\n\t\t\t\t\tlWidth = tWidth;\n\t\t\t\t}\n\t\t\t}\n\t\t\txSize = mWidth = Math.max(Math.min(lWidth + 20, 400), 120);\n\t\t\tsuper.initGui();\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tfor (int i = 0; i < 9 && i < text.length; i++) {\n\t\t\tif (text[i] == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tString msg = TextUtil.getTrimmedString(text[i], mWidth - 10, fontRenderer, \"\");\n\t\t\tint stringWidth = mc.fontRenderer.getStringWidth(msg);\n\t\t\tmc.fontRenderer.drawString(msg, xCenter - (stringWidth / 2), guiTop + 10 + (i * 10), 0x404040);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) {\n\t\tswitch (guibutton.id) {\n\t\t\tcase 0:\n\t\t\t\tsuper.exitGui();\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiRecipeImport.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.TreeSet;\n\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.NonNullList;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.NEISetCraftingRecipe;\nimport logisticspipes.network.packets.pipe.FindMostLikelyRecipeComponents;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SimpleGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiRecipeImport extends SubGuiScreen {\n\n\tpublic static class Candidates {\n\n\t\tpublic Candidates(Set<ItemIdentifierStack> set) {\n\t\t\tthis.set = set;\n\t\t}\n\n\t\tSet<ItemIdentifierStack> set;\n\t\tpublic List<ItemIdentifierStack> order;\n\t\tint pos = 0;\n\t}\n\n\tprivate final TileEntity tile;\n\tprivate final Candidates[] grid = new Candidates[9];\n\tprivate final List<Candidates> list;\n\tprivate Object[] tooltip = null;\n\n\tpublic GuiRecipeImport(TileEntity tile, ItemStack[][] stacks) {\n\t\tsuper(150, 200, 0, 0);\n\t\tthis.tile = tile;\n\t\tlist = new ArrayList<>();\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tif (stacks[i] == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tSet<ItemIdentifierStack> part = new TreeSet<>();\n\t\t\tList<ItemIdentifierStack> order = new ArrayList<>();\n\t\t\tfor (ItemStack stack : stacks[i]) {\n\t\t\t\tItemIdentifierStack iStack = ItemIdentifierStack.getFromStack(stack);\n\t\t\t\tpart.add(iStack);\n\t\t\t\torder.add(iStack);\n\t\t\t}\n\t\t\tCandidates candidate = new Candidates(part);\n\t\t\tboolean found = false;\n\t\t\tfor (Candidates test : list) {\n\t\t\t\tif (test.set.equals(part)) {\n\t\t\t\t\tcandidate = test;\n\t\t\t\t\tfound = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!found) {\n\t\t\t\tcandidate.order = order;\n\t\t\t\tif (order.size() > 1) {\n\t\t\t\t\tlist.add(candidate);\n\t\t\t\t}\n\t\t\t}\n\t\t\tgrid[i] = candidate;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, guiLeft + 100, guiTop + 180, 40, 10, \"Done\"));\n\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 10, guiTop + 180, 60, 10, \"Most likely\"));\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tfor (Candidates candidate : list) {\n\t\t\tbuttonList.add(new SmallGuiButton(10 + x + y * 3, guiLeft + 38 + x * 40, guiTop + 88 + y * 40, 15, 10, \"/\\\\\"));\n\t\t\tbuttonList.add(new SmallGuiButton(20 + x + y * 3, guiLeft + 38 + x * 40, guiTop + 98 + y * 40, 15, 10, \"\\\\/\"));\n\t\t\tx++;\n\t\t\tif (x > 2) {\n\t\t\t\tx = 0;\n\t\t\t\ty++;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void renderToolTips(int mouseX, int mouseY, float par3) {\n\t\tGuiGraphics.displayItemToolTip(tooltip, this, zLevel, guiLeft, guiTop);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {\n\t\tfontRenderer.drawString(TextUtil.translate(\"misc.selectOreDict\"), guiLeft + 10, guiTop + 6, 0x404040, false);\n\t\ttooltip = null;\n\t\tfor (int x = 0; x < 3; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tif (grid[x + y * 3] == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tItemIdentifierStack stack = grid[x + y * 3].order.get(grid[x + y * 3].pos);\n\t\t\t\tItemStack itemStack = stack.makeNormalStack();\n\n\t\t\t\tFontRenderer font = itemStack.getItem().getFontRenderer(itemStack);\n\t\t\t\tif (font == null) {\n\t\t\t\t\tfont = fontRenderer;\n\t\t\t\t}\n\n\t\t\t\titemRender.renderItemAndEffectIntoGUI(itemStack, guiLeft + 45 + x * 18, guiTop + 20 + y * 18);\n\t\t\t\t// With empty string, because damage value indicator struggles with the depth\n\t\t\t\titemRender.renderItemOverlayIntoGUI(font, itemStack, guiLeft + 45 + x * 18, guiTop + 20 + y * 18, null);\n\n\t\t\t\tif (guiLeft + 45 + x * 18 < mouseX && mouseX < guiLeft + 45 + x * 18 + 16 && guiTop + 20 + y * 18 < mouseY && mouseY < guiTop + 20 + y * 18 + 16 && !hasSubGui()) {\n\t\t\t\t\tSimpleGraphics.drawGradientRect(guiLeft + 45 + x * 18, guiTop + 20 + y * 18, guiLeft + 45 + x * 18 + 16, guiTop + 20 + y * 18 + 16, Color.WHITE_50, Color.WHITE_50, 0.0);\n\t\t\t\t\ttooltip = new Object[] { guiLeft + mouseX, guiTop + mouseY, itemStack };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tfor (Candidates candidate : list) {\n\t\t\tItemIdentifierStack stack = candidate.order.get(candidate.pos);\n\t\t\tItemStack itemStack = stack.makeNormalStack();\n\t\t\tFontRenderer font = itemStack.getItem().getFontRenderer(itemStack);\n\t\t\tif (font == null) {\n\t\t\t\tfont = fontRenderer;\n\t\t\t}\n\n\t\t\titemRender.renderItemAndEffectIntoGUI(itemStack, guiLeft + 20 + x * 40, guiTop + 90 + y * 40);\n\t\t\t// With empty string, because damage value indicator struggles with the depth\n\t\t\titemRender.renderItemOverlayIntoGUI(font, itemStack, guiLeft + 20 + x * 40, guiTop + 90 + y * 40, \"\");\n\n\t\t\tif (guiLeft + 20 + x * 40 < mouseX && mouseX < guiLeft + 20 + x * 40 + 16 && guiTop + 90 + y * 40 < mouseY && mouseY < guiTop + 90 + y * 40 + 16 && !hasSubGui()) {\n\t\t\t\tSimpleGraphics.drawGradientRect(guiLeft + 20 + x * 40, guiTop + 90 + y * 40, guiLeft + 20 + x * 40 + 16, guiTop + 90 + y * 40 + 16, Color.WHITE_50, Color.WHITE_50, 0.0);\n\t\t\t\ttooltip = new Object[] { guiLeft + mouseX, guiTop + mouseY, itemStack };\n\t\t\t}\n\n\t\t\tx++;\n\t\t\tif (x > 2) {\n\t\t\t\tx = 0;\n\t\t\t\ty++;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tfontRenderer.drawString(TextUtil.translate(\"misc.selectOreDict\"), guiLeft + 10, guiTop + 6, 0x404040, false);\n\t\tfor (int x = 0; x < 3; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 44 + x * 18, guiTop + 19 + y * 18);\n\t\t\t}\n\t\t}\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tfor (Candidates candidate : list) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, guiLeft + 19 + x * 40, guiTop + 89 + y * 40);\n\t\t\tx++;\n\t\t\tif (x > 2) {\n\t\t\t\tx = 0;\n\t\t\t\ty++;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tint id = button.id;\n\t\tif (id == 0) {\n\t\t\tNEISetCraftingRecipe packet = PacketHandler.getPacket(NEISetCraftingRecipe.class);\n\t\t\tNonNullList<ItemStack> stackList = packet.getStackList();\n\t\t\tint i = 0;\n\t\t\tfor (Candidates candidate : grid) {\n\t\t\t\tif (candidate == null) {\n\t\t\t\t\ti++;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tstackList.set(i++, candidate.order.get(candidate.pos).makeNormalStack());\n\t\t\t}\n\t\t\tMainProxy.sendPacketToServer(packet.setBlockPos(tile.getPos()));\n\t\t\texitGui();\n\t\t} else if (id == 1) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FindMostLikelyRecipeComponents.class).setContent(list).setTilePos(tile));\n\t\t} else if (id >= 10 && id < 30) {\n\t\t\tint slot = id % 10;\n\t\t\tboolean up = id < 20;\n\t\t\tCandidates candidate = list.get(slot);\n\t\t\tif (up) {\n\t\t\t\tcandidate.pos++;\n\t\t\t\tif (candidate.pos >= candidate.order.size()) {\n\t\t\t\t\tcandidate.pos = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcandidate.pos--;\n\t\t\t\tif (candidate.pos < 0) {\n\t\t\t\t\tcandidate.pos = candidate.order.size() - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void handleProposePacket(List<Integer> response) {\n\t\tif (list.size() != response.size()) return;\n\t\tfor (int slot = 0; slot < list.size(); slot++) {\n\t\t\tCandidates candidate = list.get(slot);\n\t\t\tint newPos = response.get(slot);\n\t\t\tif (newPos != -1) {\n\t\t\t\tcandidate.pos = newPos;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int mouseX, int mouseY, int button) throws IOException {\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tfor (final Candidates candidate : list) {\n\n\t\t\tif (guiLeft + 20 + x * 40 < mouseX && mouseX < guiLeft + 20 + x * 40 + 16 && guiTop + 90 + y * 40 < mouseY && mouseY < guiTop + 90 + y * 40 + 16) {\n\t\t\t\tsetSubGui(new SelectItemOutOfList(candidate.order, slot -> candidate.pos = slot));\n\t\t\t}\n\n\t\t\tx++;\n\t\t\tif (x > 2) {\n\t\t\t\tx = 0;\n\t\t\t\ty++;\n\t\t\t}\n\t\t}\n\t\tsuper.mouseClicked(mouseX, mouseY, button);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiRequestPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.IResource.ColorCode;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiRequestPopup extends SubGuiScreen {\n\n\tprivate String[] text;\n\tprivate int mWidth = 0;\n\tprivate EntityPlayer player;\n\n\tpublic GuiRequestPopup(EntityPlayer player, Object... message) {\n\t\tsuper(200, (message.length * 10) + 40, 0, 0);\n\t\tList<String> textArray = new ArrayList<>();\n\t\tfor (Object o : message) {\n\t\t\tif (o instanceof String) {\n\t\t\t\ttextArray.add((String) o);\n\t\t\t} else if (o instanceof Collection<?>) {\n\t\t\t\tfor (Object oTwo : (Collection<?>) o) {\n\t\t\t\t\tif (oTwo instanceof ItemIdentifierStack) {\n\t\t\t\t\t\ttextArray.add(((ItemIdentifierStack) oTwo).getFriendlyName());\n\t\t\t\t\t}\n\t\t\t\t\tif (oTwo instanceof IResource) {\n\t\t\t\t\t\ttextArray.add(((IResource) oTwo).getDisplayText(ColorCode.NONE));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttextArray.add(o.toString());\n\t\t\t}\n\t\t}\n\t\ttext = textArray.toArray(new String[] {});\n\t\tySize = (text.length * 10) + 40;\n\t\tthis.player = player;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, xCenter - 55, bottom - 25, 50, 20, \"OK\"));\n\t\tbuttonList.add(new GuiButton(1, xCenter + 5, bottom - 25, 50, 20, \"Log\"));\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tif (mWidth == 0) {\n\t\t\tint lWidth = 0;\n\t\t\tfor (String msg : text) {\n\t\t\t\tint tWidth = mc.fontRenderer.getStringWidth(msg);\n\t\t\t\tif (tWidth > lWidth) {\n\t\t\t\t\tlWidth = tWidth;\n\t\t\t\t}\n\t\t\t}\n\t\t\txSize = mWidth = Math.max(Math.min(lWidth + 20, 400), 120);\n\t\t\tsuper.initGui();\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tfor (int i = 0; i < text.length; i++) {\n\t\t\tif (text[i] == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tString msg = TextUtil.getTrimmedString(text[i], mWidth - 10, fontRenderer, \"...\");\n\t\t\tint stringWidth = mc.fontRenderer.getStringWidth(msg);\n\t\t\tmc.fontRenderer.drawString(msg, xCenter - (stringWidth / 2), guiTop + 10 + (i * 10), 0x404040);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) {\n\t\tswitch (guibutton.id) {\n\t\t\tcase 0:\n\t\t\t\tsuper.exitGui();\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfor (String msg : text) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(msg));\n\t\t\t\t}\n\t\t\t\tbuttonList.get(1).enabled = false;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiSecurityStationPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.SaveSecurityPlayerPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.utils.gui.GuiCheckBox;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiSecurityStationPopup extends SubGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.securitystation.popup.player.\";\n\n\tprivate final LogisticsSecurityTileEntity _tile;\n\tprivate final SecuritySettings activeSetting;\n\n\tpublic GuiSecurityStationPopup(SecuritySettings setting, LogisticsSecurityTileEntity tile) {\n\t\tsuper(160, 135, 0, 0);\n\t\tactiveSetting = setting;\n\t\t_tile = tile;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiCheckBox(0, guiLeft + 138, guiTop + 26, 16, 16, false));\n\t\tbuttonList.add(new GuiCheckBox(1, guiLeft + 138, guiTop + 41, 16, 16, false));\n\t\tbuttonList.add(new GuiCheckBox(2, guiLeft + 138, guiTop + 56, 16, 16, false));\n\t\tbuttonList.add(new GuiCheckBox(3, guiLeft + 138, guiTop + 71, 16, 16, false));\n\t\tbuttonList.add(new GuiCheckBox(4, guiLeft + 138, guiTop + 86, 16, 16, false));\n\t\tbuttonList.add(new GuiCheckBox(5, guiLeft + 138, guiTop + 101, 16, 16, false));\n\t\tbuttonList.add(new SmallGuiButton(6, guiLeft + 123, guiTop + 118, 30, 10, TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"Close\")));\n\t\trefreshCheckBoxes();\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"Player\") + \": \" + activeSetting.name, guiLeft + 10, guiTop + 10, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"ConfigureSettings\") + \": \", guiLeft + 10, guiTop + 30, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"ActiveRequesting\") + \": \", guiLeft + 10, guiTop + 45, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"UpgradePipes\") + \": \", guiLeft + 10, guiTop + 60, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"CheckNetwork\") + \": \", guiLeft + 10, guiTop + 75, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"RemovePipes\") + \": \", guiLeft + 10, guiTop + 90, 0x404040);\n\t\tmc.fontRenderer.drawString(TextUtil.translate(GuiSecurityStationPopup.PREFIX + \"AccessRoutingChannels\") + \": \", guiLeft + 10, guiTop + 105, 0x404040);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) throws IOException {\n\t\tif (button.id == 0) {\n\t\t\tactiveSetting.openGui = !activeSetting.openGui;\n\t\t\trefreshCheckBoxes();\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tactiveSetting.writeToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SaveSecurityPlayerPacket.class).setTag(nbt).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 1) {\n\t\t\tactiveSetting.openRequest = !activeSetting.openRequest;\n\t\t\trefreshCheckBoxes();\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tactiveSetting.writeToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SaveSecurityPlayerPacket.class).setTag(nbt).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 2) {\n\t\t\tactiveSetting.openUpgrades = !activeSetting.openUpgrades;\n\t\t\trefreshCheckBoxes();\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tactiveSetting.writeToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SaveSecurityPlayerPacket.class).setTag(nbt).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 3) {\n\t\t\tactiveSetting.openNetworkMonitor = !activeSetting.openNetworkMonitor;\n\t\t\trefreshCheckBoxes();\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tactiveSetting.writeToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SaveSecurityPlayerPacket.class).setTag(nbt).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 4) {\n\t\t\tactiveSetting.removePipes = !activeSetting.removePipes;\n\t\t\trefreshCheckBoxes();\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tactiveSetting.writeToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SaveSecurityPlayerPacket.class).setTag(nbt).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 5) {\n\t\t\tactiveSetting.accessRoutingChannels = !activeSetting.accessRoutingChannels;\n\t\t\trefreshCheckBoxes();\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tactiveSetting.writeToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SaveSecurityPlayerPacket.class).setTag(nbt).setBlockPos(_tile.getPos()));\n\t\t} else if (button.id == 6) {\n\t\t\texitGui();\n\t\t} else {\n\t\t\tsuper.actionPerformed(button);\n\t\t}\n\t}\n\n\tpublic void refreshCheckBoxes() {\n\t\t((GuiCheckBox) buttonList.get(0)).setState(activeSetting.openGui);\n\t\t((GuiCheckBox) buttonList.get(1)).setState(activeSetting.openRequest);\n\t\t((GuiCheckBox) buttonList.get(2)).setState(activeSetting.openUpgrades);\n\t\t((GuiCheckBox) buttonList.get(3)).setState(activeSetting.openNetworkMonitor);\n\t\t((GuiCheckBox) buttonList.get(4)).setState(activeSetting.removePipes);\n\t\t((GuiCheckBox) buttonList.get(5)).setState(activeSetting.accessRoutingChannels);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiSelectChannelPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.function.Consumer;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiSelectChannelPopup extends GuiManageChannelPopup {\n\n\tprivate static final String GUI_LANG_KEY = \"gui.popup.selectchannel.\";\n\n\tprivate final Consumer<ChannelInformation> handleResult;\n\n\tpublic GuiSelectChannelPopup(List<ChannelInformation> channelList, BlockPos pos, Consumer<ChannelInformation> handleResult) {\n\t\tsuper(channelList, pos);\n\t\tthis.handleResult = handleResult;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.remove(0);\n\t\tbuttonList.add(new SmallGuiButton(0, xCenter + 16, bottom - 27, 50, 10, \"Select\"));\n\t}\n\n\tprotected void drawTitle() {\n\t\tmc.fontRenderer.drawStringWithShadow(\n\t\t\t\tTextUtil.translate(GUI_LANG_KEY + \"title\"), xCenter - (mc.fontRenderer.getStringWidth(TextUtil.translate(GUI_LANG_KEY + \"title\")) / 2f), guiTop + 6, 0xFFFFFF);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) { // Select\n\t\t\tint selected = textList.getSelected();\n\t\t\tif (selected >= 0) {\n\t\t\t\tChannelInformation info = channelList.get(selected);\n\t\t\t\tif (info != null) {\n\t\t\t\t\thandleResult.accept(info);\n\t\t\t\t}\n\t\t\t\texitGui();\n\t\t\t}\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/GuiSelectSatellitePopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.function.Consumer;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.RequestSatellitePipeListPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.gui.TextListDisplay;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class GuiSelectSatellitePopup extends SubGuiScreen {\n\n\tString GUI_LANG_KEY = \"gui.popup.selectsatellite.\";\n\n\tprivate final Consumer<UUID> handleResult;\n\tprivate List<Pair<String, UUID>> pipeList = Collections.EMPTY_LIST;\n\tprivate final TextListDisplay textList;\n\n\tpublic GuiSelectSatellitePopup(BlockPos pos, boolean fluidSatellites, Consumer<UUID> handleResult) {\n\t\tsuper(150, 170, 0, 0);\n\t\tthis.handleResult = handleResult;\n\t\tthis.textList = new TextListDisplay(this, 6, 16, 6, 30, 12, new TextListDisplay.List() {\n\n\t\t\t@Override\n\t\t\tpublic int getSize() {\n\t\t\t\treturn pipeList.size();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic String getTextAt(int index) {\n\t\t\t\treturn pipeList.get(index).getValue1();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getTextColor(int index) {\n\t\t\t\treturn 0xFFFFFF;\n\t\t\t}\n\t\t});\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSatellitePipeListPacket.class).setFlag(fluidSatellites).setBlockPos(pos));\n\t}\n\n\tprotected void drawTitle() {\n\t\tmc.fontRenderer.drawStringWithShadow(TextUtil.translate(GUI_LANG_KEY + \"title\"), xCenter - (mc.fontRenderer.getStringWidth(TextUtil.translate(GUI_LANG_KEY + \"title\")) / 2f), guiTop + 6, 0xFFFFFF);\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, xCenter + 16, bottom - 27, 50, 10, TextUtil.translate(GUI_LANG_KEY + \"select\")));\n\t\tbuttonList.add(new SmallGuiButton(1, xCenter + 16, bottom - 15, 50, 10, TextUtil.translate(GUI_LANG_KEY + \"exit\")));\n\t\tbuttonList.add(new SmallGuiButton(2, xCenter - 66, bottom - 27, 50, 10, TextUtil.translate(GUI_LANG_KEY + \"unset\")));\n\t\tbuttonList.add(new SmallGuiButton(4, xCenter - 12, bottom - 27, 25, 10, \"/\\\\\"));\n\t\tbuttonList.add(new SmallGuiButton(5, xCenter - 12, bottom - 15, 25, 10, \"\\\\/\"));\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tdrawTitle();\n\n\t\ttextList.renderGuiBackground(mouseX, mouseY);\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int i, int j, int k) throws IOException {\n\t\ttextList.mouseClicked(i, j, k);\n\t\tsuper.mouseClicked(i, j, k);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tint wheel = org.lwjgl.input.Mouse.getDWheel() / 120;\n\t\tif (wheel == 0) {\n\t\t\tsuper.handleMouseInputSub();\n\t\t}\n\t\tif (wheel < 0) {\n\t\t\ttextList.scrollUp();\n\t\t} else if (wheel > 0) {\n\t\t\ttextList.scrollDown();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton guibutton) throws IOException {\n\t\tif (guibutton.id == 0) { // Select\n\t\t\tint selected = textList.getSelected();\n\t\t\tif (selected >= 0) {\n\t\t\t\thandleResult.accept(pipeList.get(selected).getValue2());\n\t\t\t\texitGui();\n\t\t\t}\n\t\t} else if (guibutton.id == 1) { // Exit\n\t\t\texitGui();\n\t\t} else if (guibutton.id == 2) { // UnSet\n\t\t\thandleResult.accept(null);\n\t\t\texitGui();\n\t\t} else if (guibutton.id == 4) {\n\t\t\ttextList.scrollDown();\n\t\t} else if (guibutton.id == 5) {\n\t\t\ttextList.scrollUp();\n\t\t} else {\n\t\t\tsuper.actionPerformed(guibutton);\n\t\t}\n\t}\n\n\tpublic void handleSatelliteList(List<Pair<String, UUID>> list) {\n\t\tpipeList = list;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/RequestMonitorPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.awt.image.BufferedImage;\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.IntBuffer;\nimport java.text.DateFormat;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport javax.imageio.ImageIO;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.BufferUtils;\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SimpleGraphics;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class RequestMonitorPopup extends SubGuiScreen {\n\n\tprivate enum ZOOM_LEVEL {\n\t\tNORMAL(1, 165, 224, 1, 0, 0, 0),\n\t\tLEVEL_1(0.5F, 330, 465, 1, 50, -200, 100),\n\t\tLEVEL_2(0.25F, 660, 950, 2, 100, -400, -100);\n\n\t\tZOOM_LEVEL(float zoom, int bottom, int right, int line, int moveY, int maxX, int maxY) {\n\t\t\tthis.zoom = zoom;\n\t\t\tbottomRenderBorder = bottom;\n\t\t\trightRenderBorder = right;\n\t\t\tthis.line = line;\n\t\t\tthis.moveY = moveY;\n\t\t\tthis.maxX = maxX;\n\t\t\tthis.maxY = maxY;\n\t\t}\n\n\t\tfinal float zoom;\n\t\tfinal int bottomRenderBorder;\n\t\tfinal int rightRenderBorder;\n\t\tfinal int line;\n\t\tfinal int moveY;\n\t\tfinal int maxX;\n\t\tfinal int maxY;\n\n\t\tZOOM_LEVEL next() {\n\t\t\tint id = ordinal();\n\t\t\tif (id + 1 >= ZOOM_LEVEL.values().length) {\n\t\t\t\treturn this;\n\t\t\t} else {\n\t\t\t\treturn ZOOM_LEVEL.values()[id + 1];\n\t\t\t}\n\t\t}\n\n\t\tZOOM_LEVEL prev() {\n\t\t\tint id = ordinal();\n\t\t\tif (id - 1 < 0) {\n\t\t\t\treturn this;\n\t\t\t} else {\n\t\t\t\treturn ZOOM_LEVEL.values()[id - 1];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static final ResourceLocation achievementTextures = new ResourceLocation(\"logisticspipes\", \"textures/gui/gui_border.png\");\n\tprivate final PipeBlockRequestTable _table;\n\tprivate final int orderId;\n\n\tprivate int isMouseButtonDown;\n\tprivate int mouseX;\n\tprivate int mouseY;\n\tprivate double guiMapX;\n\tprivate double guiMapY;\n\tprivate int minY = -230;\n\tprivate int maxY = 0;\n\tprivate int minX = -800;\n\tprivate int maxX = 800;\n\tprivate ZOOM_LEVEL zoom = ZOOM_LEVEL.NORMAL;\n\tprivate Object[] tooltip = null;\n\n\tpublic RequestMonitorPopup(PipeBlockRequestTable table, int orderId) {\n\t\tsuper(256, 202, 0, 0);\n\t\t_table = table;\n\t\tthis.orderId = orderId;\n\t\tguiMapY = -200;\n\t\tMouse.getDWheel(); // Reset DWheel on GUI open\n\t}\n\n\tprivate static void mirror(int[] par0ArrayOfInteger, int width, int height) {\n\t\tint[] aInt1 = new int[width];\n\t\tint k = height / 2;\n\n\t\tfor (int l = 0; l < k; ++l) {\n\t\t\tSystem.arraycopy(par0ArrayOfInteger, l * width, aInt1, 0, width);\n\t\t\tSystem.arraycopy(par0ArrayOfInteger, (height - 1 - l) * width, par0ArrayOfInteger, l * width, width);\n\t\t\tSystem.arraycopy(aInt1, 0, par0ArrayOfInteger, (height - 1 - l) * width, width);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new GuiButton(0, width / 2 - 90, height / 2 + 74, 80, 20, \"Close\"));\n\t\tbuttonList.add(new GuiButton(1, width / 2 + 10, height / 2 + 74, 80, 20, \"Save as Image\"));\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tif (button.id == 0) {\n\t\t\texitGui();\n\t\t} else if (button.id == 1) {\n\t\t\tsaveTreeToImage();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void renderToolTips(int mouseX, int mouseY, float par3) {\n\t\tif (tooltip != null) {\n\t\t\tGuiGraphics.displayItemToolTip(tooltip, zLevel, guiLeft, guiTop, true);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tif (!_table.watchedRequests.containsKey(orderId)) {\n\t\t\texitGui();\n\t\t\treturn;\n\t\t}\n\t\tif (Mouse.isButtonDown(0)) {\n\t\t\tint k = (width - xSize) / 2;\n\t\t\tint l = (height - ySize) / 2;\n\t\t\tint i1 = k + 8;\n\t\t\tint j1 = l + 17;\n\n\t\t\tif ((isMouseButtonDown == 0 || isMouseButtonDown == 1) && mouseX >= i1 && mouseX < i1 + 224 && mouseY >= j1 && mouseY < j1 + 155) {\n\t\t\t\tif (isMouseButtonDown == 0) {\n\t\t\t\t\tisMouseButtonDown = 1;\n\t\t\t\t} else {\n\t\t\t\t\tguiMapX -= (double) (mouseX - this.mouseX) / zoom.zoom;\n\t\t\t\t\tguiMapY -= (double) (mouseY - this.mouseY) / zoom.zoom;\n\t\t\t\t}\n\n\t\t\t\tthis.mouseX = mouseX;\n\t\t\t\tthis.mouseY = mouseY;\n\t\t\t}\n\n\t\t} else {\n\t\t\tisMouseButtonDown = 0;\n\t\t}\n\n\t\tif (guiMapY < minY) {\n\t\t\tguiMapY = minY;\n\t\t}\n\t\tif (guiMapY > maxY) {\n\t\t\tguiMapY = maxY;\n\t\t}\n\t\tif (guiMapX > maxX) {\n\t\t\tguiMapX = maxX;\n\t\t}\n\t\tif (guiMapX < minX) {\n\t\t\tguiMapX = minX;\n\t\t}\n\n\t\tint dWheel = Mouse.getDWheel();\n\t\tif (dWheel < 0) {\n\t\t\tzoom = zoom.next();\n\t\t} else if (dWheel > 0) {\n\t\t\tzoom = zoom.prev();\n\t\t}\n\t\tcreateBoundary();\n\t\tdrawTransparentBack();\n\t\tdrawMap(mouseX, mouseY);\n\t}\n\n\tprivate void createBoundary() {\n\t\tint size = _table.watchedRequests.get(orderId).getValue2().getTreeRootSize();\n\t\tminX = -size * (40 / 2) + (int) (75 * (zoom.zoom));\n\t\tmaxX = -minX + zoom.maxX;\n\t\tmaxY = -100;\n\t\tfindLowest(_table.watchedRequests.get(orderId).getValue2(), -200);\n\t}\n\n\tprivate void drawTransparentBack() {\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tSimpleGraphics.drawGradientRect(0, 0, width, height, Color.BLANK, Color.BLANK, 0.0);\n\t}\n\n\tprivate void findLowest(LinkedLogisticsOrderList list, int lowerLimit) {\n\t\tlowerLimit += 48;\n\t\tfor (LinkedLogisticsOrderList sub : list.getSubOrders()) {\n\t\t\tfindLowest(sub, lowerLimit);\n\t\t}\n\t\tif (maxY < (lowerLimit + 10) * zoom.zoom) {\n\t\t\tmaxY = (int) ((lowerLimit + 10) * zoom.zoom) + zoom.maxY;\n\t\t}\n\t}\n\n\tprivate void saveTreeToImage() {\n\t\tint useWidth = mc.displayWidth;\n\t\tint useHeight = mc.displayHeight;\n\t\tint left = minX - (width / 2);\n\t\tint top = minY;\n\t\tint right = maxX - (width / 2);\n\t\tint bottom = maxY;\n\n\t\tint k = useWidth * useHeight;\n\t\tIntBuffer pixels = BufferUtils.createIntBuffer(k);\n\t\tint[] intArray = new int[k];\n\n\t\tint imgPosX = 0;\n\t\tint imgPosY = 0;\n\t\tfor (int x = left; x < right + width; x += width) {\n\t\t\timgPosY = 0;\n\t\t\tfor (int y = top; y < bottom + height; y += height) {\n\t\t\t\timgPosY += useHeight;\n\t\t\t}\n\t\t\timgPosX += useWidth;\n\t\t}\n\t\tBufferedImage bufferedimage = new BufferedImage(imgPosX, imgPosY, 1);\n\n\t\timgPosX = 0;\n\n\t\t//Clear everything\n\t\tGL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);\n\t\tGL11.glLoadIdentity();\n\t\tmc.entityRenderer.setupOverlayRendering();\n\t\tdrawForScreenShot(0, 0);\n\n\t\t//Start Creating the Image\n\t\tfor (int x = left; x < right + width; x += width) {\n\t\t\timgPosY = 0;\n\t\t\tfor (int y = top; y < bottom + height; y += height) {\n\t\t\t\tGL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\t\tmc.entityRenderer.setupOverlayRendering();\n\t\t\t\tdrawForScreenShot(y, x);\n\t\t\t\tpixels.clear();\n\t\t\t\tGL11.glReadPixels(0, 0, useWidth, useHeight, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixels);\n\t\t\t\tpixels.get(intArray);\n\t\t\t\tRequestMonitorPopup.mirror(intArray, useWidth, useHeight);\n\t\t\t\tbufferedimage.setRGB(imgPosX, imgPosY, Math.min(useWidth, bufferedimage.getWidth() - imgPosX), Math.min(useHeight, bufferedimage.getHeight() - imgPosY), intArray, 0, useWidth);\n\t\t\t\timgPosY += useHeight;\n\t\t\t}\n\t\t\timgPosX += useWidth;\n\t\t}\n\t\tsaveImage(bufferedimage);\n\t}\n\n\tprivate void saveImage(BufferedImage bufferedimage) {\n\t\tFile screenShotsFolder = new File(Minecraft.getMinecraft().gameDir, \"screenshots\");\n\t\tDateFormat dateFormat = new SimpleDateFormat(\"yyyy-MM-dd_HH.mm.ss\");\n\t\tString s = dateFormat.format(new Date());\n\t\tint i = 1;\n\t\twhile (true) {\n\t\t\tFile candidate = new File(screenShotsFolder, s + (i == 1 ? \"\" : \"_\" + i) + \".png\");\n\t\t\tif (!candidate.exists()) {\n\t\t\t\ttry {\n\t\t\t\t\tImageIO.write(bufferedimage, \"png\", candidate);\n\t\t\t\t\tMinecraft.getMinecraft().player.sendChatMessage(\"Saved tree view as \" + candidate.getName());\n\t\t\t\t} catch (IOException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t++i;\n\t\t}\n\t}\n\n\tprivate void drawForScreenShot(int top, int left) {\n\t\tleft *= -1;\n\t\ttop *= -1;\n\t\tGL11.glPushMatrix();\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glTranslated(0, 0, 100);\n\t\tGui.drawRect(0, 0, 10000, 10000, 0xff000000);\n\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\tfor (int yVar = 0; yVar * 16 < height; yVar++) {\n\t\t\tfor (int xVar = 0; xVar * 16 < width; xVar++) {\n\t\t\t\tTextureAtlasSprite icon = getTexture(Blocks.STONE);\n\t\t\t\tmc.getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\t\t\tdrawTexturedModalRect(xVar * 16, yVar * 16, icon, 16, 16);\n\t\t\t}\n\t\t}\n\t\tGL11.glTranslated(0, 0, 600);\n\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\tGL11.glEnable(GL11.GL_COLOR_MATERIAL);\n\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glDisable(GL11.GL_TEXTURE_2D);\n\t\tLinkedLogisticsOrderList list = _table.watchedRequests.get(orderId).getValue2();\n\t\tif (!list.isEmpty()) {\n\t\t\tSimpleGraphics.drawVerticalLine(left + 8, top + 0, top + 17, Color.GREEN, zoom.line);\n\t\t}\n\t\trenderLinkedOrderListLines(list, left, top + 17);\n\t\tfor (Float progress : list.getProgresses()) {\n\t\t\tint pos = (int) (29.0F * progress);\n\t\t\tdrawProgressPoint(left + 8, top + pos, 0xff00ff00);\n\t\t}\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\n\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\tGL11.glEnable(GL11.GL_COLOR_MATERIAL);\n\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\tmc.getTextureManager().bindTexture(RequestMonitorPopup.achievementTextures);\n\t\tString s = Integer.toString(orderId);\n\t\tif (!list.isEmpty()) {\n\t\t\tdrawTexturedModalRect(left - 5, top - 40 + 17, 0, 202, 26, 26);\n\t\t\tmc.fontRenderer.drawStringWithShadow(s, left + 9 - mc.fontRenderer.getStringWidth(s) / 2, top - 30 + 17, 16777215);\n\t\t} else {\n\t\t\tdrawTexturedModalRect(left - 5, top - 18 + 17, 0, 202, 26, 26);\n\t\t\tmc.fontRenderer.drawStringWithShadow(s, left + 9 - mc.fontRenderer.getStringWidth(s) / 2, top - 18 + 10 + 17, 16777215);\n\t\t}\n\t\trenderLinkedOrderListItems(list, left, top + 17, 0, 0);\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\tGL11.glPopMatrix();\n\t\tzLevel = 0.0F;\n\t\tGL11.glDepthFunc(GL11.GL_LEQUAL);\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\tRenderHelper.disableStandardItemLighting();\n\t}\n\n\tprivate void drawMap(int par1, int par2) {\n\t\ttooltip = null;\n\t\tint mapX = (int) Math.floor(guiMapX);\n\t\tint mapY = (int) Math.floor(guiMapY - zoom.moveY);\n\t\tint leftSide = ((width - xSize) / 2);\n\t\tint topSide = ((height - ySize) / 2);\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, 100.0F);\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.getTextureManager().bindTexture(RequestMonitorPopup.achievementTextures);\n\t\tdrawTexturedModalRect(leftSide, topSide, 0, 0, xSize, ySize);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -100.0F);\n\n\t\tguiTop *= 1 / zoom.zoom;\n\t\tguiLeft *= 1 / zoom.zoom;\n\t\txSize *= 1 / zoom.zoom;\n\t\tySize *= 1 / zoom.zoom;\n\t\tleftSide *= 1 / zoom.zoom;\n\t\ttopSide *= 1 / zoom.zoom;\n\t\tpar1 *= 1 / zoom.zoom;\n\t\tpar2 *= 1 / zoom.zoom;\n\n\t\tint innerLeftSide = leftSide + 16;\n\t\tint innerTopSide = topSide + 17;\n\t\tzLevel = 0.0F;\n\n\t\tGL11.glDepthFunc(GL11.GL_GEQUAL);\n\t\tGL11.glPushMatrix();\n\t\tGL11.glScalef(zoom.zoom, zoom.zoom, 1);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -100.0F);\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\tGL11.glEnable(GL11.GL_COLOR_MATERIAL);\n\n\t\tint moveBackgroundX = (mapX - minX) % 16;\n\t\tint moveBackgroundY = (mapY - minY) % 16;\n\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\tfor (int yVar = 0; yVar * 16 - moveBackgroundY < zoom.bottomRenderBorder; yVar++) {\n\t\t\tfor (int xVar = 0; xVar * 16 - moveBackgroundX < zoom.rightRenderBorder; xVar++) {\n\t\t\t\tTextureAtlasSprite icon = getTexture(Blocks.STONE);\n\t\t\t\tmc.getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\t\t\tdrawTexturedModalRect(innerLeftSide + xVar * 16 - moveBackgroundX, innerTopSide + yVar * 16 - moveBackgroundY, icon, 16, 16);\n\t\t\t}\n\t\t}\n\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glDepthFunc(GL11.GL_LEQUAL);\n\t\tGL11.glDisable(GL11.GL_TEXTURE_2D);\n\t\tLinkedLogisticsOrderList list = _table.watchedRequests.get(orderId).getValue2();\n\t\tif (!list.isEmpty()) {\n\t\t\tSimpleGraphics.drawVerticalLine(innerLeftSide - mapX + 110, innerTopSide - mapY - 197, innerTopSide - mapY - 180, Color.GREEN, zoom.line);\n\t\t}\n\t\trenderLinkedOrderListLines(list, innerLeftSide - mapX + 102, innerTopSide - mapY - 180);\n\t\tfor (Float progress : list.getProgresses()) {\n\t\t\tint pos = (int) (29.0F * progress);\n\t\t\tdrawProgressPoint(innerLeftSide - mapX + 110, innerTopSide - mapY - 197 + pos, 0xff00ff00);\n\t\t}\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\n\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\tGL11.glEnable(GL11.GL_COLOR_MATERIAL);\n\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\tmc.getTextureManager().bindTexture(RequestMonitorPopup.achievementTextures);\n\t\tString s = Integer.toString(orderId);\n\t\tif (!list.isEmpty()) {\n\t\t\tdrawTexturedModalRect(innerLeftSide - mapX + 97, innerTopSide - mapY - 220, 0, 202, 26, 26);\n\t\t\tmc.fontRenderer.drawStringWithShadow(s, innerLeftSide - mapX + 111 - mc.fontRenderer.getStringWidth(s) / 2, innerTopSide - mapY - 210, 16777215);\n\t\t} else {\n\t\t\tdrawTexturedModalRect(innerLeftSide - mapX + 97, innerTopSide - mapY - 162, 0, 202, 26, 26);\n\t\t\tmc.fontRenderer.drawStringWithShadow(s, innerLeftSide - mapX + 111 - mc.fontRenderer.getStringWidth(s) / 2, innerTopSide - mapY - 152, 16777215);\n\t\t}\n\t\trenderLinkedOrderListItems(list, innerLeftSide - mapX + 102, innerTopSide - mapY - 180, par1, par2);\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\tguiTop *= zoom.zoom;\n\t\tguiLeft *= zoom.zoom;\n\t\txSize *= zoom.zoom;\n\t\tySize *= zoom.zoom;\n\t\tleftSide *= zoom.zoom;\n\t\ttopSide *= zoom.zoom;\n\n\t\tGL11.glScalef(1 / zoom.zoom, 1 / zoom.zoom, 1);\n\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.getTextureManager().bindTexture(RequestMonitorPopup.achievementTextures);\n\t\tdrawTexturedModalRect(leftSide, topSide, 0, 0, xSize, ySize);\n\t\tGL11.glPopMatrix();\n\t\tzLevel = 0.0F;\n\t\tGL11.glDepthFunc(GL11.GL_LEQUAL);\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\tRenderHelper.disableStandardItemLighting();\n\t}\n\n\tprivate void renderLinkedOrderListItems(LinkedLogisticsOrderList list, int xPos, int yPos, int par1, int par2) {\n\t\tint size = list.size();\n\t\tint startLeft = -(size - 1) * (30 / 2) + xPos;\n\t\tyPos += 13;\n\t\tfor (IOrderInfoProvider aList : list) {\n\t\t\tif (aList.isInProgress()) {\n\t\t\t\tGL11.glColor4f(0.1F, 0.9F, 0.1F, 1.0F);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\t\t}\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\tmc.getTextureManager().bindTexture(RequestMonitorPopup.achievementTextures);\n\t\t\tdrawTexturedModalRect(startLeft - 5, yPos - 5, 0, 202, 26, 26);\n\t\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\t\trenderItemAt(aList.getAsDisplayItem(), startLeft, yPos);\n\t\t\tif (aList.isInProgress() && aList.getMachineProgress() != 0) {\n\t\t\t\tGui.drawRect(startLeft - 4, yPos + 20, startLeft + 20, yPos + 24, 0xff000000);\n\t\t\t\tGui.drawRect(startLeft - 3, yPos + 21, startLeft + 19, yPos + 23, 0xffffffff);\n\t\t\t\tGui.drawRect(startLeft - 3, yPos + 21, startLeft - 3 + (22 * aList\n\t\t\t\t\t\t.getMachineProgress() / 100), yPos + 23, 0xffff0000);\n\t\t\t}\n\t\t\tif (startLeft - 10 < par1 && par1 < startLeft + 20 && yPos - 6 < par2 && par2 < yPos + 20) {\n\t\t\t\tif (guiLeft < par1 && par1 < guiLeft + xSize - 16 && guiTop < par2 && par2 < guiTop + ySize - 16) {\n\t\t\t\t\tIOrderInfoProvider order = aList;\n\t\t\t\t\tList<String> tooltipList = new ArrayList<>();\n\t\t\t\t\ttooltipList.add(ChatColor.BLUE + \"Request Type: \" + ChatColor.YELLOW + order.getType().name());\n\t\t\t\t\ttooltipList.add(ChatColor.BLUE + \"Send to Router ID: \" + ChatColor.YELLOW + order.getRouterId());\n\t\t\t\t\ttooltip = new Object[] { (int) (par1 * zoom.zoom - 10), (int) (par2 * zoom.zoom), order\n\t\t\t\t\t\t\t.getAsDisplayItem().makeNormalStack(), true, tooltipList };\n\t\t\t\t}\n\t\t\t}\n\t\t\tstartLeft += 30;\n\t\t}\n\t\tstartLeft = xPos + 20 - list.getSubTreeRootSize() * (40 / 2);\n\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\tfor (int i = 0; i < list.getSubOrders().size(); i++) {\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t\trenderLinkedOrderListItems(list.getSubOrders().get(i), startLeft - 20, yPos + 48, par1, par2);\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void renderLinkedOrderListLines(LinkedLogisticsOrderList list, int xPos, int yPos) {\n\t\tint size = list.size();\n\t\tif (list.isEmpty()) {\n\t\t\tsize = 1;\n\t\t}\n\t\tint startLeft = -(size - 1) * (30 / 2) + xPos;\n\t\tyPos += 13;\n\t\tint left = startLeft;\n\t\tfor (int i = 0; i < list.size(); i++) {\n\t\t\tSimpleGraphics.drawVerticalLine(startLeft + 8, yPos - 13, yPos - 3, Color.GREEN, zoom.line);\n\t\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\t\tSimpleGraphics.drawVerticalLine(startLeft + 8, yPos + 18, yPos + 28, Color.GREEN, zoom.line);\n\t\t\t}\n\t\t\tstartLeft += 30;\n\t\t}\n\t\tif (!list.isEmpty()) {\n\t\t\tSimpleGraphics.drawHorizontalLine(left + 8, startLeft - 22, yPos - 13, Color.GREEN, zoom.line);\n\t\t}\n\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\tif (!list.isEmpty()) {\n\t\t\t\tSimpleGraphics.drawHorizontalLine(left + 8, startLeft - 22, yPos + 28, Color.GREEN, zoom.line);\n\t\t\t\tstartLeft -= 30;\n\t\t\t}\n\t\t\tSimpleGraphics.drawVerticalLine(left + ((startLeft - left) / 2) + 8, yPos + 28, yPos + 38, Color.GREEN, zoom.line);\n\t\t\tstartLeft = xPos + 20 - list.getSubTreeRootSize() * (40 / 2);\n\t\t\tleft = startLeft;\n\t\t\tfor (int i = 0; i < list.getSubOrders().size(); i++) {\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t\tSimpleGraphics.drawVerticalLine(startLeft - 12, yPos + 38, yPos + 48, Color.GREEN, zoom.line);\n\t\t\t\tdrawPointFor(list, xPos, yPos, i, startLeft);\n\t\t\t\trenderLinkedOrderListLines(list.getSubOrders().get(i), startLeft - 20, yPos + 48);\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t}\n\t\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\t\tleft += list.getSubOrders().get(0).getTreeRootSize() * (40 / 2);\n\t\t\t\tstartLeft -= list.getSubOrders().get(list.getSubOrders().size() - 1).getTreeRootSize() * (40 / 2);\n\t\t\t}\n\t\t\tSimpleGraphics.drawHorizontalLine(left - 12, startLeft - 12, yPos + 38, Color.GREEN, zoom.line);\n\t\t}\n\t}\n\n\tprivate void drawPointFor(LinkedLogisticsOrderList list, int xPos, int yPos, int i, int startLeft) {\n\t\tfloat totalLine = 10 + 1 + 10 + 1 + Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10;\n\t\tfor (Float point : list.getSubOrders().get(i).getProgresses()) {\n\t\t\tint pos = (int) (totalLine * (1.0F - point));\n\t\t\tif (pos < 13) {\n\t\t\t\tint newSize = list.getSubOrders().get(i).size();\n\t\t\t\tint newStartLeft = -(newSize - 1) * (30 / 2) + startLeft - 20;\n\t\t\t\tfor (int j = 0; j < newSize; j++) {\n\t\t\t\t\tdrawProgressPoint(newStartLeft + 8, yPos + 48 + 12 - pos, 0xff00ff00);\n\t\t\t\t\tnewStartLeft += 30;\n\t\t\t\t}\n\t\t\t} else if (pos < 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10;\n\t\t\t\tdrawProgressPoint(startLeft - 20 + 8, yPos + 38 + 12 - pos, 0xff00ff00);\n\t\t\t} else if (pos < Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10 + 1 + 10 + 1;\n\t\t\t\tif (startLeft < xPos + 20) {\n\t\t\t\t\tpos *= -1;\n\t\t\t\t}\n\t\t\t\tdrawProgressPoint(startLeft - 12 - pos, yPos + 38, 0xff00ff00);\n\t\t\t} else if (pos < Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10 + 1 + 10 + 1 + Math.abs(startLeft - (xPos + 20)) + 10 + 1;\n\t\t\t\tdrawProgressPoint(xPos + 8, yPos + 27 - pos, 0xff00ff00);\n\t\t\t} else if (pos < Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1 + 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10 + 1 + 10 + 1 + Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1;\n\t\t\t\tint newSize = list.size();\n\t\t\t\tint newStartLeft = -(newSize - 1) * (30 / 2) + xPos;\n\t\t\t\tfor (int j = 0; j < newSize; j++) {\n\t\t\t\t\tdrawProgressPoint(newStartLeft + 8, yPos + 16 - pos, 0xff00ff00);\n\t\t\t\t\tnewStartLeft += 30;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void renderItemAt(ItemIdentifierStack item, int x, int y) {\n\t\tif (guiLeft < x && x < guiLeft + xSize - 16 && guiTop < y && y < guiTop + ySize - 16) {\n\t\t\titemRender.renderItemAndEffectIntoGUI(item.getItem().makeNormalStack(1), x, y);\n\t\t\titemRender.renderItemOverlayIntoGUI(fontRenderer, item.getItem().makeNormalStack(1), x, y, \"\");\n\t\t\tString s = TextUtil.getThreeDigitFormattedNumber(item.getStackSize(), false);\n\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\titemRender.zLevel = 0.0F;\n\t\t\t// Draw number\n\t\t\tmc.fontRenderer.drawStringWithShadow(s, x + 17 - mc.fontRenderer.getStringWidth(s), y + 9, 16777215);\n\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t}\n\t}\n\n\tprotected void drawProgressPoint(int x, int y, int color) {\n\t\tint line = zoom.line + 1;\n\t\tGui.drawRect(x - line + 1, y - line + 1, x + line, y + line, color);\n\t}\n\n\tprivate TextureAtlasSprite getTexture(Block blockIn) {\n\t\treturn Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getTexture(blockIn.getDefaultState());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/SelectItemOutOfList.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Map;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.enchantment.Enchantment;\nimport net.minecraft.enchantment.EnchantmentHelper;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.IItemSearch;\nimport logisticspipes.utils.gui.InputBar;\nimport logisticspipes.utils.gui.ItemDisplay;\nimport logisticspipes.utils.gui.SmallGuiButton;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class SelectItemOutOfList extends SubGuiScreen implements IItemSearch {\n\n\tpublic interface IHandleItemChoice {\n\n\t\tvoid handleItemChoice(int slot);\n\t}\n\n\tprivate final List<ItemIdentifierStack> candidate;\n\tprivate final IHandleItemChoice handler;\n\tprivate ItemDisplay itemDisplay = null;\n\tprivate InputBar search;\n\n\tpublic SelectItemOutOfList(List<ItemIdentifierStack> candidate, IHandleItemChoice handler) {\n\t\tsuper(156, 188, 0, 0);\n\t\tthis.candidate = candidate;\n\t\tthis.handler = handler;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tKeyboard.enableRepeatEvents(true);\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tbuttonList.add(new SmallGuiButton(0, guiLeft + 70, guiTop + 5, 10, 10, \"<\"));\n\t\tbuttonList.add(new SmallGuiButton(1, guiLeft + 138, guiTop + 5, 10, 10, \">\"));\n\t\tbuttonList.add(new GuiButton(2, guiLeft + 100, bottom - 26, 50, 20, \"Select\"));\n\n\t\tif (search == null) {\n\t\t\tsearch = new InputBar(fontRenderer, this.getBaseScreen(), guiLeft + 7, bottom - 23, right - guiLeft - 64, 15, false);\n\t\t}\n\t\tsearch.reposition(guiLeft + 7, bottom - 23, right - guiLeft - 64, 15);\n\n\t\tif (itemDisplay == null) {\n\t\t\titemDisplay = new ItemDisplay(this, fontRenderer, this.getBaseScreen(), null, guiLeft + 10, guiTop + 18, xSize - 20, ySize - 48, 0, 0, 0, new int[] { 1, 10, 64, 64 }, true);\n\t\t\titemDisplay.setItemList(candidate);\n\t\t}\n\t\titemDisplay.reposition(guiLeft + 8, guiTop + 18, xSize - 16, ySize - 48, 0, 0);\n\t}\n\n\t@Override\n\tpublic void exitGui() {\n\t\tsuper.exitGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t\tgetBaseScreen().initGui();\n\t}\n\n\t@Override\n\tprotected void renderToolTips(int mouseX, int mouseY, float par3) {\n\t\tif (!hasSubGui()) {\n\t\t\tGuiGraphics.displayItemToolTip(itemDisplay.getToolTip(), this, zLevel, 0, 0);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t\tfontRenderer.drawString(TextUtil.translate(\"misc.selectType\"), guiLeft + 8, guiTop + 6, 0x404040, false); //TODO\n\n\t\titemDisplay.renderPageNumber(right - 47, guiTop + 6);\n\n\t\t//SearchInput\n\t\tsearch.drawTextBox();\n\n\t\t//itemDisplay.renderSortMode(xCenter, bottom - 52);\n\t\titemDisplay.renderItemArea(zLevel);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tint id = button.id;\n\t\tif (id == 1) {\n\t\t\titemDisplay.nextPage();\n\t\t} else if (id == 0) {\n\t\t\titemDisplay.prevPage();\n\t\t} else if (id == 2) {\n\t\t\tItemIdentifierStack stack = itemDisplay.getSelectedItem();\n\t\t\tint index = candidate.indexOf(stack);\n\t\t\tif (index >= 0) {\n\t\t\t\thandler.handleItemChoice(index);\n\t\t\t}\n\t\t\texitGui();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\titemDisplay.handleMouse();\n\t\tsuper.handleMouseInputSub();\n\t}\n\n\t@Override\n\tprotected void keyTyped(char par1, int par2) {\n\t\tif (!itemDisplay.keyTyped(par1, par2)) {\n\t\t\tif (par2 == 1 || !search.handleKey(par1, par2)) {\n\t\t\t\tsuper.keyTyped(par1, par2);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int mouseX, int mouseY, int button) throws IOException {\n\t\tif (itemDisplay.handleClick(mouseX, mouseY, button)) return;\n\t\tif (search.handleClick(mouseX, mouseY, button)) return;\n\t\tsuper.mouseClicked(mouseX, mouseY, button);\n\t}\n\n\t@Override\n\tpublic boolean itemSearched(ItemIdentifier item) {\n\t\tif (search.isEmpty()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (isSearched(item.getFriendlyName().toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\treturn true;\n\t\t}\n\t\t//if(isSearched(String.valueOf(Item.getIdFromItem(item.item)), search.getContent())) return true;\n\t\t//Enchantment? Enchantment!\n\t\tMap<Enchantment, Integer> enchantIdLvlMap = EnchantmentHelper.getEnchantments(item.unsafeMakeNormalStack(1));\n\t\tfor (Map.Entry<Enchantment, Integer> e : enchantIdLvlMap.entrySet()) {\n\t\t\tString enchantName = e.getKey().getName();\n\t\t\tif (enchantName != null) {\n\t\t\t\tif (isSearched(enchantName.toLowerCase(Locale.US), search.getText().toLowerCase(Locale.US))) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean isSearched(String value, String search) {\n\t\tboolean flag = true;\n\t\tfor (String s : search.split(\" \")) {\n\t\t\tif (!value.contains(s)) {\n\t\t\t\tflag = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn flag;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/gui/popup/SneakyConfigurationPopup.java",
    "content": "package logisticspipes.gui.popup;\n\nimport java.awt.Rectangle;\nimport java.io.IOException;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.ScaledResolution;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.upgrade.SneakyUpgradeSidePacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.gui.UpgradeSlot;\nimport logisticspipes.utils.gui.sideconfig.SideConfigDisplay;\nimport network.rs485.logisticspipes.util.TextUtil;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class SneakyConfigurationPopup extends SubGuiScreen {\n\n\tprivate static final String PREFIX = \"gui.pipecontroller.popup.\";\n\n\tprivate SideConfigDisplay configDisplay;\n\tprivate List<DoubleCoordinates> config;\n\tprivate Rectangle bounds;\n\tprivate UpgradeSlot pos;\n\n\tpublic SneakyConfigurationPopup(List<DoubleCoordinates> config, UpgradeSlot pos) {\n\t\tsuper(250, 250, 0, 0);\n\t\tthis.config = config;\n\t\tthis.pos = pos;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\tconfigDisplay = new SideConfigDisplay(config) {\n\n\t\t\t@Override\n\t\t\tpublic void handleSelection(SelectedFace selection) {\n\t\t\t\tSneakyConfigurationPopup.this.handleSelection(selection);\n\t\t\t}\n\t\t};\n\t\tconfigDisplay.init();\n\t\tconfigDisplay.renderNeighbours = true;\n\n\t\tbuttonList.add(new GuiButton(0, right - 106, bottom - 26, 100, 20, \"Cancel\"));\n\n\t\tbounds = new Rectangle(guiLeft + 5, guiTop + 20, this.xSize - 10, this.ySize - 50);\n\t}\n\n\tpublic void handleSelection(SideConfigDisplay.SelectedFace selection) {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SneakyUpgradeSidePacket.class).setSide(selection.face).setSlot(pos));\n\t\tthis.exitGui();\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY, float partialTick) {\n\t\tdrawRect(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height, 0xff000000);\n\n\t\tMinecraft mc = Minecraft.getMinecraft();\n\t\tScaledResolution scaledresolution = new ScaledResolution(mc);\n\n\t\tint vpx = bounds.x * scaledresolution.getScaleFactor();\n\t\tint vpy = (bounds.y + 10) * scaledresolution.getScaleFactor();\n\t\tint w = bounds.width * scaledresolution.getScaleFactor();\n\t\tint h = (bounds.height - 1) * scaledresolution.getScaleFactor();\n\n\t\tfontRenderer.drawString(TextUtil.translate(PREFIX + \"sneakyTitle\"), guiLeft + 8, guiTop + 8, Color.getValue(Color.DARKER_GREY), false);\n\n\t\tconfigDisplay.drawScreen(mouseX, mouseY, partialTick, new Rectangle(vpx, vpy, w, h), bounds);\n\t}\n\n\t@Override\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tsuper.handleMouseInputSub();\n\t\tconfigDisplay.handleMouseInput();\n\t}\n\n\t@Override\n\tprotected void renderGuiBackground(int mouseX, int mouseY) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, true);\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\tswitch (button.id) {\n\t\t\tcase 0:\n\t\t\t\tthis.exitGui();\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/hud/HUDConfig.java",
    "content": "package logisticspipes.hud;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.interfaces.IHUDConfig;\n\npublic class HUDConfig implements IHUDConfig {\n\n\tprivate NBTTagCompound configTag;\n\n\tpublic HUDConfig(@Nonnull ItemStack stack) {\n\t\tthis(stack.getTagCompound());\n\t\tstack.setTagCompound(configTag);\n\t}\n\n\tpublic HUDConfig(NBTTagCompound tag) {\n\t\tconfigTag = tag;\n\t\tif (configTag == null) {\n\t\t\tconfigTag = new NBTTagCompound();\n\t\t}\n\n\t\tif (configTag.isEmpty()) {\n\t\t\tconfigTag.setBoolean(\"HUDChassie\", true);\n\t\t\tconfigTag.setBoolean(\"HUDCrafting\", true);\n\t\t\tconfigTag.setBoolean(\"HUDInvSysCon\", true);\n\t\t\tconfigTag.setBoolean(\"HUDPowerJunction\", true);\n\t\t\tconfigTag.setBoolean(\"HUDProvider\", true);\n\t\t\tconfigTag.setBoolean(\"HUDSatellite\", true);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isChassisHUD() {\n\t\treturn configTag.getBoolean(\"HUDChassie\");\n\t}\n\n\t@Override\n\tpublic boolean isHUDCrafting() {\n\t\treturn configTag.getBoolean(\"HUDCrafting\");\n\t}\n\n\t@Override\n\tpublic boolean isHUDInvSysCon() {\n\t\treturn configTag.getBoolean(\"HUDInvSysCon\");\n\t}\n\n\t@Override\n\tpublic boolean isHUDPowerLevel() {\n\t\treturn configTag.getBoolean(\"HUDPowerJunction\");\n\t}\n\n\t@Override\n\tpublic boolean isHUDProvider() {\n\t\treturn configTag.getBoolean(\"HUDProvider\");\n\t}\n\n\t@Override\n\tpublic boolean isHUDSatellite() {\n\t\treturn configTag.getBoolean(\"HUDSatellite\");\n\t}\n\n\t@Override\n\tpublic void setChassisHUD(boolean flag) {\n\t\tconfigTag.setBoolean(\"HUDChassie\", flag);\n\t}\n\n\t@Override\n\tpublic void setHUDCrafting(boolean flag) {\n\t\tconfigTag.setBoolean(\"HUDCrafting\", flag);\n\t}\n\n\t@Override\n\tpublic void setHUDInvSysCon(boolean flag) {\n\t\tconfigTag.setBoolean(\"HUDInvSysCon\", flag);\n\t}\n\n\t@Override\n\tpublic void setHUDPowerJunction(boolean flag) {\n\t\tconfigTag.setBoolean(\"HUDPowerJunction\", flag);\n\t}\n\n\t@Override\n\tpublic void setHUDProvider(boolean flag) {\n\t\tconfigTag.setBoolean(\"HUDProvider\", flag);\n\t}\n\n\t@Override\n\tpublic void setHUDSatellite(boolean flag) {\n\t\tconfigTag.setBoolean(\"HUDSatellite\", flag);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IBlockWatchingHandler.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\npublic interface IBlockWatchingHandler {\n\n\tvoid playerStartWatching(EntityPlayer player);\n\n\tvoid playerStopWatching(EntityPlayer player);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IBufferItems.java",
    "content": "package logisticspipes.interfaces;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IBufferItems {\n\n\t/**\n\t * @param stack Item to add to buffer. Class will store a copy or other\n\t *              representation of stack.\n\t * @param info  Additional Target Information\n\t * @return amount of items NOT added to the buffer\n\t */\n\tint addToBuffer(ItemIdentifierStack stack, IAdditionalTargetInformation info);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IChainAddList.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\n\npublic interface IChainAddList<T> extends List<T> {\n\n\tT addChain(T add);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IChangeListener.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IChangeListener {\n\n\tvoid listenedChanged();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IChestContentReceiver.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.Collection;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IChestContentReceiver {\n\n\tvoid setReceivedChestContent(Collection<ItemIdentifierStack> _allItems);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IClientInformationProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\npublic interface IClientInformationProvider {\n\n\t@Nonnull\n\tList<String> getClientInformation();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IClientState.java",
    "content": "package logisticspipes.interfaces;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic interface IClientState {\n\n\tvoid writeData(LPDataOutput output);\n\n\tvoid readData(LPDataInput input);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IDebugHUDProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\n\npublic interface IDebugHUDProvider {\n\n\tList<IHeadUpDisplayRendererProvider> getHUDs();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IDiskProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.utils.gui.ItemDisplay;\n\npublic interface IDiskProvider {\n\n\t@Nonnull\n\tItemStack getDisk();\n\n\tint getX();\n\n\tint getY();\n\n\tint getZ();\n\n\tItemDisplay getItemDisplay();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IFuzzySlot.java",
    "content": "package logisticspipes.interfaces;\n\nimport network.rs485.logisticspipes.property.IBitSet;\n\npublic interface IFuzzySlot {\n\n\tIBitSet getFuzzyFlags();\n\n\tint getX();\n\n\tint getY();\n\n\tint getSlotId();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IGUIChannelInformationReceiver.java",
    "content": "package logisticspipes.interfaces;\n\nimport logisticspipes.routing.channels.ChannelInformation;\n\npublic interface IGUIChannelInformationReceiver {\n\n\tvoid handleChannelInformation(ChannelInformation channel, boolean flag);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IGuiOpenControler.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\npublic interface IGuiOpenControler {\n\n\tvoid guiOpenedByPlayer(EntityPlayer player);\n\n\tvoid guiClosedByPlayer(EntityPlayer player);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IGuiTileEntity.java",
    "content": "package logisticspipes.interfaces;\n\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\n\npublic interface IGuiTileEntity {\n\n\tCoordinatesGuiProvider getGuiProvider();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHUDButton.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IHUDButton {\n\n\tint getX();\n\n\tint getY();\n\n\tint sizeX();\n\n\tint sizeY();\n\n\tvoid setFocused();\n\n\tboolean isFocused();\n\n\tvoid clearFocused();\n\n\tvoid blockFocused();\n\n\tboolean isblockFocused();\n\n\tint focusedTime();\n\n\tvoid clicked();\n\n\tvoid renderButton(boolean hover, boolean clicked, boolean shifted);\n\n\tvoid renderAlways(boolean shifted);\n\n\tboolean shouldRenderButton();\n\n\tboolean buttonEnabled();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHUDConfig.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IHUDConfig {\n\n\tboolean isChassisHUD();\n\n\tboolean isHUDCrafting();\n\n\tboolean isHUDInvSysCon();\n\n\tboolean isHUDPowerLevel();\n\n\tboolean isHUDProvider();\n\n\tboolean isHUDSatellite();\n\n\tvoid setChassisHUD(boolean state);\n\n\tvoid setHUDCrafting(boolean state);\n\n\tvoid setHUDInvSysCon(boolean state);\n\n\tvoid setHUDPowerJunction(boolean state);\n\n\tvoid setHUDProvider(boolean state);\n\n\tvoid setHUDSatellite(boolean state);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHUDModuleHandler.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IHUDModuleHandler {\n\n\tvoid startHUDWatching();\n\n\tvoid stopHUDWatching();\n\n\tIHUDModuleRenderer getHUDRenderer();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHUDModuleRenderer.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\n\npublic interface IHUDModuleRenderer {\n\n\tvoid renderContent(boolean shifted);\n\n\tList<IHUDButton> getButtons();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHeadUpDisplayBlockRendererProvider.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IHeadUpDisplayBlockRendererProvider extends IHeadUpDisplayRendererProvider {\n\n\tboolean isHUDInvalid();\n\n\tboolean isHUDExistent();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHeadUpDisplayRenderer.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.client.Minecraft;\n\npublic interface IHeadUpDisplayRenderer {\n\n\tvoid renderHeadUpDisplay(double d, boolean day, boolean shifted, Minecraft mc, IHUDConfig config);\n\n\tboolean display(IHUDConfig config);\n\n\tboolean cursorOnWindow(int x, int y);\n\n\tvoid handleCursor(int x, int y);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IHeadUpDisplayRendererProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.world.World;\n\npublic interface IHeadUpDisplayRendererProvider {\n\n\tIHeadUpDisplayRenderer getRenderer();\n\n\tint getX();\n\n\tint getY();\n\n\tint getZ();\n\n\tWorld getWorldForHUD();\n\n\tvoid startWatching();\n\n\tvoid stopWatching();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IInventoryUtil.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.Map;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface IInventoryUtil {\n\n\tint itemCount(@Nonnull ItemIdentifier item);\n\n\t@Nonnull\n\tMap<ItemIdentifier, Integer> getItemsAndCount();\n\n\t@Deprecated\n\t@Nonnull\n\tItemStack getSingleItem(ItemIdentifier item);\n\n\t@Nonnull\n\tItemStack getMultipleItems(@Nonnull ItemIdentifier item, int count);\n\n\t/**\n\t * Checks to see if the item is inside the inventory. Used by the PolymorphicItemSink\n\t * This includes slots that are limited to one item type but don't contain any items.\n\t *\n\t * @param item The item to check\n\t * @return true if the item is inside the inventory\n\t */\n\tboolean containsUndamagedItem(@Nonnull ItemIdentifier item);\n\n\t/**\n\t * Inventory space count which terminates when space for max items are\n\t * found.\n\t *\n\t * @return spaces found. If this is less than max, then there are only\n\t * spaces for that amount.\n\t * @param stack\n\t */\n\tint roomForItem(@Nonnull ItemStack stack);\n\n\t@Nonnull\n\tSet<ItemIdentifier> getItems();\n\n\t//IInventory adapter\n\tint getSizeInventory();\n\n\t@Nonnull\n\tItemStack getStackInSlot(int slot);\n\n\t@Nonnull\n\tItemStack decrStackSize(int slot, int amount);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IItemAdvancedExistance.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\npublic interface IItemAdvancedExistance {\n\n\tboolean canExistInNormalInventory(@Nonnull ItemStack stack);\n\n\tboolean canExistInWorld(@Nonnull ItemStack stack);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ILPItemAcceptor.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\npublic interface ILPItemAcceptor {\n\n\tboolean accept(LogisticsTileGenericPipe pipe, EnumFacing from, @Nonnull ItemStack stack);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ILPPositionProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface ILPPositionProvider {\n\n\tDoubleCoordinates getLPPosition();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ILegacyActiveModule.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface ILegacyActiveModule {\n\n\tvoid onBlockRemoval();\n\n\tvoid canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filter);\n\n\tLogisticsOrder fullFill(LogisticsPromise promise, IRequestItems destination, IAdditionalTargetInformation info);\n\n\tvoid getAllItems(Map<ItemIdentifier, Integer> list, List<IFilter> filter);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ILogisticsItem.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.item.Item;\n\nimport org.apache.commons.lang3.NotImplementedException;\n\npublic interface ILogisticsItem {\n\n\tdefault String getModelPath() {\n\t\treturn getItem().getRegistryName().getPath();\n\t}\n\n\tdefault int getModelCount() {\n\t\treturn 1;\n\t}\n\n\tdefault Item getItem() {\n\t\tif (this instanceof Item) {\n\t\t\treturn (Item) this;\n\t\t} else {\n\t\t\tthrow new NotImplementedException(\"not implemented\");\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IModuleInventoryReceive.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.Collection;\nimport javax.annotation.Nonnull;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IModuleInventoryReceive {\n\n\tvoid handleInvContent(@Nonnull Collection<ItemIdentifierStack> _allItems);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IModuleWatchReciver.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\npublic interface IModuleWatchReciver {\n\n\tvoid startWatching(EntityPlayer player);\n\n\tvoid stopWatching(EntityPlayer player);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IOrderManagerContentReceiver.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.Collection;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IOrderManagerContentReceiver {\n\n\tvoid setOrderManagerContent(Collection<ItemIdentifierStack> _allItems);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IPipeServiceProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.api.IRoutedPowerProvider;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.debug.DebugLogController;\nimport logisticspipes.routing.order.LogisticsItemOrderManager;\nimport logisticspipes.utils.CacheHolder;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.connection.Adjacent;\n\n//methods needed by modules that any CRP can offer\npublic interface IPipeServiceProvider extends IRoutedPowerProvider, ISpawnParticles, ISendRoutedItem {\n\n\tboolean isNthTick(int n);\n\n\t@Nonnull\n\tDebugLogController getDebug();\n\n\tCacheHolder getCacheHolder();\n\n\t@Nonnull\n\tBlockPos getPos();\n\n\tvoid markTileDirty();\n\n\t/**\n\t * @return the available adjacent cache.\n\t */\n\t@Nonnull\n\tAdjacent getAvailableAdjacent();\n\n\t/**\n\t * Only makes sense to use this on the chassis pipe.\n\t */\n\t@Nullable\n\tEnumFacing getPointedOrientation();\n\n\t/**\n\t * to interact and send items you need to know about orders, upgrades, and have the ability to send\n\t */\n\tLogisticsItemOrderManager getItemOrderManager();\n\n\tvoid queueRoutedItem(IRoutedItem routedItem, EnumFacing from);\n\n\t@Nonnull\n\tISlotUpgradeManager getUpgradeManager(LogisticsModule.ModulePositionType slot, int positionInt);\n\n\tint countOnRoute(ItemIdentifier item);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IPipeUpgradeManager.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.util.EnumFacing;\n\npublic interface IPipeUpgradeManager {\n\n\tboolean hasPowerPassUpgrade();\n\n\tboolean hasRFPowerSupplierUpgrade();\n\n\tboolean hasBCPowerSupplierUpgrade();\n\n\tint getIC2PowerLevel();\n\n\tint getSpeedUpgradeCount();\n\n\tboolean isSideDisconnected(EnumFacing side);\n\n\tboolean hasCCRemoteControlUpgrade();\n\n\tboolean hasCraftingMonitoringUpgrade();\n\n\tboolean isOpaque();\n\n\tboolean hasUpgradeModuleUpgrade();\n\n\tboolean hasCombinedSneakyUpgrade();\n\n\tEnumFacing[] getCombinedSneakyOrientation();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IPowerLevelDisplay.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IPowerLevelDisplay {\n\n\tint getChargeState();\n\n\tint getDisplayPowerLevel();\n\n\tint getMaxStorage();\n\n\tboolean isHUDInvalid();\n\n\tString getBrand();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IQueueCCEvent.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface IQueueCCEvent {\n\n\tvoid queueEvent(String event, Object[] arguments);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IRequestWatcher.java",
    "content": "package logisticspipes.interfaces;\n\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\n\npublic interface IRequestWatcher {\n\n\tvoid handleOrderList(IResource stack, LinkedLogisticsOrderList orders);\n\n\tvoid handleClientSideListInfo(int id, IResource stack, LinkedLogisticsOrderList orders);\n\n\tvoid handleClientSideRemove(int id);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IRotationProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.util.EnumFacing;\n\npublic interface IRotationProvider {\n\n\t@Deprecated\n\tint getRotation();\n\n\tdefault EnumFacing getFacing() {\n\t\tswitch (getRotation()) {\n\t\t\tcase 0:\n\t\t\t\treturn EnumFacing.WEST;\n\t\t\tcase 1:\n\t\t\t\treturn EnumFacing.EAST;\n\t\t\tcase 2:\n\t\t\t\treturn EnumFacing.NORTH;\n\t\t\tcase 3:\n\t\t\tdefault:\n\t\t\t\treturn EnumFacing.SOUTH;\n\t\t}\n\t}\n\n\t@Deprecated\n\tvoid setRotation(int rotation);\n\n\tdefault void setFacing(EnumFacing facing) {\n\t\tswitch (facing) {\n\t\t\tcase NORTH:\n\t\t\t\tsetRotation(3);\n\t\t\t\tbreak;\n\t\t\tcase DOWN:\n\t\t\tcase UP:\n\t\t\tcase SOUTH:\n\t\t\t\tsetRotation(2);\n\t\t\t\tbreak;\n\t\t\tcase WEST:\n\t\t\t\tsetRotation(1);\n\t\t\t\tbreak;\n\t\t\tcase EAST:\n\t\t\t\tsetRotation(0);\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IRoutingDebugAdapter.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.PriorityQueue;\n\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.PipeRoutingConnectionType;\n\npublic interface IRoutingDebugAdapter {\n\n\tvoid start(PriorityQueue<ExitRoute> candidatesCost, ArrayList<EnumSet<PipeRoutingConnectionType>> closedSet, ArrayList<EnumMap<PipeRoutingConnectionType, List<List<IFilter>>>> filterList);\n\n\tvoid nextPipe(ExitRoute lowestCostNode);\n\n\tvoid handledPipe();\n\n\tvoid newCanidate(ExitRoute next);\n\n\tvoid stepOneDone();\n\n\tvoid stepTwoDone();\n\n\tvoid done();\n\n\tvoid init();\n\n\tvoid newFlagsForPipe(EnumSet<PipeRoutingConnectionType> newFlags);\n\n\tvoid filterList(EnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters);\n\n\tboolean independent();\n\n\tboolean isDebug();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISecurityProvider.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface ISecurityProvider {\n\n\tboolean getAllowCC(int id);\n\n\tboolean canAutomatedDestroy();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISecurityStationManager.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\n\npublic interface ISecurityStationManager {\n\n\tvoid add(LogisticsSecurityTileEntity tile);\n\n\t@Nullable\n\tLogisticsSecurityTileEntity getStation(UUID id);\n\n\tvoid remove(LogisticsSecurityTileEntity tile);\n\n\tvoid deauthorizeUUID(UUID id);\n\n\tvoid authorizeUUID(UUID id);\n\n\tboolean isAuthorized(UUID id);\n\n\tboolean isAuthorized(String id);\n\n\tvoid sendClientAuthorizationList();\n\n\tvoid sendClientAuthorizationList(EntityPlayer player);\n\n\tvoid setClientAuthorizationList(List<String> list);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISendQueueContentRecieiver.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.Collection;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface ISendQueueContentRecieiver {\n\n\tvoid handleSendQueueItemIdentifierList(Collection<ItemIdentifierStack> _allItems);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISendRoutedItem.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.pipes.basic.CoreRoutedPipe.ItemSendMode;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.tuples.Pair;\n\npublic interface ISendRoutedItem {\n\n\tint getSourceID();\n\n\t@Nonnull\n\tIRouter getRouter();\n\n\tIRoutedItem sendStack(@Nonnull ItemStack stack, Pair<Integer, SinkReply> reply, ItemSendMode mode, @Nonnull EnumFacing direction);\n\n\tIRoutedItem sendStack(@Nonnull ItemStack stack, int destination, ItemSendMode mode, IAdditionalTargetInformation info, @Nonnull EnumFacing direction);\n\n\tdefault IRoutedItem sendStack(@Nonnull ItemStack stack, int destRouterId, @Nonnull SinkReply sinkReply, @Nonnull ItemSendMode itemSendMode, @Nonnull EnumFacing direction) {\n\t\treturn sendStack(stack, new Pair<>(destRouterId, sinkReply), itemSendMode, direction);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISlotCheck.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\npublic interface ISlotCheck {\n\n\tboolean isStackAllowed(@Nonnull ItemStack itemStack);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISlotClick.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\npublic interface ISlotClick {\n\n\t@Nonnull\n\tItemStack getResultForClick();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISlotUpgradeManager.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface ISlotUpgradeManager {\n\n\tboolean hasPatternUpgrade();\n\n\tboolean isAdvancedSatelliteCrafter();\n\n\tboolean hasByproductExtractor();\n\n\tint getFluidCrafter();\n\n\tboolean isFuzzyUpgrade();\n\n\tint getCrafterCleanup();\n\n\tboolean hasSneakyUpgrade();\n\n\tEnumFacing getSneakyOrientation();\n\n\tboolean hasOwnSneakyUpgrade();\n\n\tIInventory getInv();\n\n\tIPipeUpgrade getUpgrade(int slot);\n\n\tDoubleCoordinates getPipePosition();\n\n\tint getActionSpeedUpgrade();\n\n\tint getItemExtractionUpgrade();\n\n\tint getItemStackExtractionUpgrade();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISpawnParticles.java",
    "content": "package logisticspipes.interfaces;\n\nimport lombok.Getter;\nimport lombok.RequiredArgsConstructor;\n\nimport logisticspipes.pipefxhandlers.Particles;\n\npublic interface ISpawnParticles {\n\n\t@RequiredArgsConstructor\n\tclass ParticleCount {\n\n\t\t@Getter\n\t\tprivate final Particles particle;\n\t\t@Getter\n\t\tprivate final int amount;\n\t}\n\n\tvoid spawnParticle(Particles particle, int amount);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISpecialInsertion.java",
    "content": "package logisticspipes.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\npublic interface ISpecialInsertion {\n\n\tint addToSlot(@Nonnull ItemStack stack, int i);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISpecialItemRenderer.java",
    "content": "package logisticspipes.interfaces;\n\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface ISpecialItemRenderer {\n\n\tvoid specialItemRendering(ItemIdentifier item, int x, int y);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISpecialTankAccessHandler.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.Map;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport logisticspipes.utils.FluidIdentifier;\n\npublic interface ISpecialTankAccessHandler extends ISpecialTankHandler {\n\n\tMap<FluidIdentifier, Long> getAvailableLiquid(TileEntity tile);\n\n\tFluidStack drainFrom(TileEntity tile, FluidIdentifier ident, Integer amount, boolean drain);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISpecialTankHandler.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\n\nimport net.minecraft.tileentity.TileEntity;\n\npublic interface ISpecialTankHandler {\n\n\tboolean init();\n\n\tboolean isType(TileEntity tile);\n\n\tList<TileEntity> getBaseTilesFor(TileEntity tile);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISpecialTankUtil.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\n\npublic interface ISpecialTankUtil extends ITankUtil {\n\n\tTileEntity getTileEntity();\n\n\tISpecialTankAccessHandler getSpecialHandler();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IStringBasedModule.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.property.StringListProperty;\n\npublic interface IStringBasedModule {\n\n\tStringListProperty stringListProperty();\n\n\tString getStringForItem(ItemIdentifier ident);\n\n\tvoid listChanged();\n\n\tvoid readFromNBT(NBTTagCompound nbt);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ISubSystemPowerProvider.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface ISubSystemPowerProvider {\n\n\tdouble getPowerLevel();\n\n\tvoid requestPower(int destination, double amount);\n\n\tboolean usePaused();\n\n\tString getBrand();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ITankUtil.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.stream.Stream;\n\nimport net.minecraftforge.fluids.capability.IFluidTankProperties;\n\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\n\npublic interface ITankUtil {\n\n\tboolean containsTanks();\n\n\tint fill(FluidIdentifierStack stack, boolean doFill);\n\n\tFluidIdentifierStack drain(FluidIdentifierStack stack, boolean doDrain);\n\n\tFluidIdentifierStack drain(int amount, boolean doDrain);\n\n\tStream<IFluidTankProperties> tanks();\n\n\t/**\n\t * Type only amount is ignored\n\t */\n\tboolean canDrain(FluidIdentifier fluid);\n\n\tint getFreeSpaceInsideTank(FluidIdentifier type);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ITileEntityPart.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface ITileEntityPart {\n\n\tvoid updateEntity();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ITubeOrientation.java",
    "content": "package logisticspipes.interfaces;\n\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.utils.IPositionRotateble;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface ITubeOrientation {\n\n\tITubeRenderOrientation getRenderOrientation();\n\n\tvoid rotatePositions(IPositionRotateble set);\n\n\tDoubleCoordinates getOffset();\n\n\tvoid setOnPipe(CoreMultiBlockPipe pipe);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/ITubeRenderOrientation.java",
    "content": "package logisticspipes.interfaces;\n\npublic interface ITubeRenderOrientation {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IWatchingHandler.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\npublic interface IWatchingHandler {\n\n\tvoid playerStartWatching(EntityPlayer player, int mode);\n\n\tvoid playerStopWatching(EntityPlayer player, int mode);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/IWorldProvider.java",
    "content": "package logisticspipes.interfaces;\n\nimport net.minecraft.world.World;\n\npublic interface IWorldProvider {\n\n\tWorld getWorld();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/PlayerListReciver.java",
    "content": "package logisticspipes.interfaces;\n\nimport java.util.List;\n\npublic interface PlayerListReciver {\n\n\tvoid receivePlayerList(List<String> list);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IAdditionalTargetInformation.java",
    "content": "package logisticspipes.interfaces.routing;\n\npublic interface IAdditionalTargetInformation {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IChannelConnectionManager.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.routing.IRouter;\n\npublic interface IChannelConnectionManager {\n\n\tboolean hasChannelConnection(IRouter router);\n\n\tboolean addChannelConnection(UUID ident, IRouter router);\n\n\tList<CoreRoutedPipe> getConnectedPipes(IRouter router);\n\n\tvoid removeChannelConnection(IRouter router);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IChannelManager.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.PlayerIdentifier;\n\npublic interface IChannelManager {\n\n\tList<ChannelInformation> getChannels();\n\n\tList<ChannelInformation> getAllowedChannels(EntityPlayer playerIdentifier);\n\n\tChannelInformation createNewChannel(String name, PlayerIdentifier owner, ChannelInformation.AccessRights rights, UUID responsibleSecurityID);\n\n\tvoid updateChannelName(UUID channelIdentifier, String newName);\n\n\tvoid updateChannelRights(UUID channelIdentifier, ChannelInformation.AccessRights rights, UUID responsibleSecurityID);\n\n\tvoid removeChannel(UUID channelIdentifier);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IChannelManagerProvider.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport net.minecraft.world.World;\n\npublic interface IChannelManagerProvider {\n\n\tIChannelManager getChannelManager(World world);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IChannelRoutingConnection.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport logisticspipes.routing.ItemRoutingInformation;\n\npublic interface IChannelRoutingConnection {\n\n\tint getConnectionResistance();\n\n\tvoid addItem(ItemRoutingInformation info);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/ICraft.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport logisticspipes.request.ICraftingTemplate;\nimport logisticspipes.request.IPromise;\nimport logisticspipes.request.resources.IResource;\n\npublic interface ICraft extends IProvide {\n\n\tvoid registerExtras(IPromise promise);\n\n\tICraftingTemplate addCrafting(IResource type);\n\n\tboolean canCraft(IResource toCraft);\n\n\tint getTodo();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/ICraftItems.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.interfaces.routing;\n\nimport java.util.List;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface ICraftItems extends ICraft, IProvideItems, IItemSpaceControl, IRequireReliableTransport {\n\n\t//void canCraft(LogisticsTransaction transaction);\n\n\t/**\n\t * some items do not have a specific list of things they can craft (ie, AE\n\t * crafting system, fuzzy crafting) in this case enumerating them all will\n\t * be slow/impossible.\n\t *\n\t * @deprecated getCraftedItems can be slow, instead ask if the item you are\n\t *             after can be crafted\n\t */\n\t@Deprecated\n\tList<ItemIdentifierStack> getCraftedItems(); // list of all items that can be crafted.\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IFilter.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface IFilter {\n\n\tboolean isBlocked();\n\n\tboolean isFilteredItem(ItemIdentifier item);\n\n\tboolean isFilteredItem(IResource resultItem);\n\n\tboolean blockProvider();\n\n\tboolean blockCrafting();\n\n\tboolean blockRouting();\n\n\tboolean blockPower();\n\n\tDoubleCoordinates getLPPosition();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IFilteringPipe.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.List;\n\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\n\npublic interface IFilteringPipe {\n\n\tList<ExitRoute> getRouters(IRouter router);\n\n\tIFilter getFilter();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IFluidSink.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport javax.annotation.Nullable;\n\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.FluidSinkReply;\n\npublic interface IFluidSink {\n\n\t@Nullable\n\tFluidSinkReply sinkAmount(FluidIdentifierStack stack);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IItemSpaceControl.java",
    "content": "package logisticspipes.interfaces.routing;\n\npublic interface IItemSpaceControl extends IRequestItems {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IProvide.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.routing.IRouter;\n\npublic interface IProvide {\n\n\tvoid canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filter);\n\n\t@Nonnull\n\tIRouter getRouter();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IProvideFluids.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.Map;\n\nimport logisticspipes.routing.FluidLogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.FluidIdentifier;\n\npublic interface IProvideFluids extends IProvide {\n\n\tMap<FluidIdentifier, Integer> getAvailableFluids();\n\n\tIOrderInfoProvider fullFill(FluidLogisticsPromise promise, IRequestFluid destination, ResourceType type, IAdditionalTargetInformation info);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IProvideItems.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.interfaces.routing;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface IProvideItems extends IProvide {\n\n\tLogisticsOrder fullFill(LogisticsPromise promise, IRequestItems destination, IAdditionalTargetInformation info);\n\n\tvoid getAllItems(Map<ItemIdentifier, Integer> list, List<IFilter> filter);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IRequest.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport javax.annotation.Nonnull;\n\nimport logisticspipes.routing.IRouter;\n\npublic interface IRequest {\n\n\t@Nonnull\n\tIRouter getRouter();\n\n\tint getID();\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IRequestFluid.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport logisticspipes.utils.FluidIdentifier;\n\npublic interface IRequestFluid extends IRequest {\n\n\tvoid sendFailed(FluidIdentifier value1, Integer value2);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IRequestItems.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.interfaces.routing;\n\nimport javax.annotation.Nonnull;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IRequestItems extends Comparable<IRequestItems>, IRequest {\n\n\tvoid itemCouldNotBeSend(ItemIdentifierStack item, IAdditionalTargetInformation info);\n\n\t@Override\n\tint compareTo(@Nonnull IRequestItems other);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IRequireReliableFluidTransport.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport logisticspipes.utils.FluidIdentifier;\n\npublic interface IRequireReliableFluidTransport {\n\n\tvoid liquidLost(FluidIdentifier item, int amount);\n\n\tvoid liquidNotInserted(FluidIdentifier item, int amount);\n\n\tvoid liquidArrived(FluidIdentifier item, int amount);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/IRequireReliableTransport.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.interfaces.routing;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IRequireReliableTransport {\n\n\tvoid itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info);\n\n\tvoid itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/ISpecialPipedConnection.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.EnumSet;\nimport java.util.List;\n\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.proxy.specialconnection.SpecialPipeConnection.ConnectionInformation;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\n\npublic interface ISpecialPipedConnection {\n\n\tboolean init();\n\n\tboolean isType(IPipeInformationProvider startPipe);\n\n\tList<ConnectionInformation> getConnections(IPipeInformationProvider startPipe, EnumSet<PipeRoutingConnectionType> connection, EnumFacing side);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/ISpecialTileConnection.java",
    "content": "package logisticspipes.interfaces.routing;\n\nimport java.util.Collection;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.logisticspipes.IRoutedItem;\n\npublic interface ISpecialTileConnection {\n\n\tboolean init();\n\n\tboolean isType(TileEntity tile);\n\n\tCollection<TileEntity> getConnections(TileEntity tile);\n\n\tboolean needsInformationTransition();\n\n\tvoid transmit(TileEntity tile, IRoutedItem arrivingItem);\n}\n"
  },
  {
    "path": "common/logisticspipes/interfaces/routing/ITargetSlotInformation.java",
    "content": "package logisticspipes.interfaces.routing;\n\npublic interface ITargetSlotInformation {\n\n\tint getTargetSlot();\n\n\tint getAmount();\n\n\tboolean isLimited();\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemBlankModule.java",
    "content": "package logisticspipes.items;\n\npublic class ItemBlankModule extends LogisticsItem {\n\n\tpublic ItemBlankModule() {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic String getModelSubdir() {\n\t\treturn \"module\";\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemDisk.java",
    "content": "package logisticspipes.items;\n\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.world.World;\n\npublic class ItemDisk extends LogisticsItem {\n\n\t@Override\n\tpublic int getItemStackLimit() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tif (!stack.isEmpty() && stack.hasTagCompound()) {\n\t\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\t\tif (tag.hasKey(\"name\")) {\n\t\t\t\tString name = \"\\u00a78\" + tag.getString(\"name\");\n\t\t\t\ttooltip.add(name);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemHUDArmor.java",
    "content": "package logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.item.ItemArmor;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ActionResult;\nimport net.minecraft.util.DamageSource;\nimport net.minecraft.util.EnumActionResult;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.translation.I18n;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.ISpecialArmor;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.IHUDArmor;\nimport logisticspipes.interfaces.ILogisticsItem;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.proxy.MainProxy;\n\npublic class ItemHUDArmor extends ItemArmor implements ISpecialArmor, IHUDArmor, ILogisticsItem {\n\n\tpublic ItemHUDArmor() {\n\t\tsuper(ArmorMaterial.LEATHER, 0, EntityEquipmentSlot.HEAD);\n\t}\n\n\t@Override\n\tpublic ArmorProperties getProperties(EntityLivingBase player, @Nonnull ItemStack armor, DamageSource source, double damage, int slot) {\n\t\treturn new ArmorProperties(0, 0, 0);\n\t}\n\n\t@Override\n\tpublic int getArmorDisplay(EntityPlayer player, @Nonnull ItemStack armor, int slot) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void damageArmor(EntityLivingBase entity, @Nonnull ItemStack stack, DamageSource source, int damage, int slot) {\n\t\t// Does not get damaged\n\t}\n\n\t@Override\n\tpublic boolean getShareTag() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, @Nonnull EnumHand handIn) {\n\t\tItemStack stack = player.getHeldItem(handIn);\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn new ActionResult<>(EnumActionResult.PASS, stack);\n\t\t}\n\t\tuseItem(player, world);\n\t\treturn new ActionResult<>(EnumActionResult.SUCCESS, stack);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {\n\t\tuseItem(player, world);\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn EnumActionResult.PASS;\n\t\t}\n\t\treturn EnumActionResult.SUCCESS;\n\t}\n\n\tprivate void useItem(EntityPlayer player, World world) {\n\t\tplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_HUD_Settings, world, player.inventory.currentItem, -1, 0);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic CreativeTabs[] getCreativeTabs() {\n\t\t// is visible in the LP creative tab and the ItemArmor creative tab\n\t\treturn new CreativeTabs[] { getCreativeTab(), LogisticsPipes.CREATIVE_TAB_LP };\n\t}\n\n\t@Override\n\tpublic boolean isEnabled(@Nonnull ItemStack item) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getArmorTexture(@Nonnull ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type) {\n\t\treturn \"logisticspipes:textures/armor/LogisticsHUD_1.png\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getItemStackDisplayName(@Nonnull ItemStack itemstack) {\n\t\treturn I18n.translateToLocal(getTranslationKey(itemstack) + \".name\").trim();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemLogisticsChips.java",
    "content": "package logisticspipes.items;\n\npublic class ItemLogisticsChips extends LogisticsItem {\n\n\tpublic static final int ITEM_CHIP_BASIC = 0;\n\tpublic static final int ITEM_CHIP_BASIC_RAW = 1;\n\tpublic static final int ITEM_CHIP_ADVANCED = 2;\n\tpublic static final int ITEM_CHIP_ADVANCED_RAW = 3;\n\tpublic static final int ITEM_CHIP_FPGA = 4;\n\tpublic static final int ITEM_CHIP_FPGA_RAW = 5;\n\n\tpublic ItemLogisticsChips(int subItem) {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic String getModelSubdir() {\n\t\treturn \"chip\";\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemLogisticsPipe.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.advancements.CriteriaTriggers;\nimport net.minecraft.block.Block;\nimport net.minecraft.block.SoundType;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumActionResult;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.SoundCategory;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.Getter;\nimport org.apache.logging.log4j.Level;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.renderer.IIconProvider;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\n/**\n * A logistics pipe Item\n */\npublic class ItemLogisticsPipe extends LogisticsItem {\n\n\tprivate int newPipeIconIndex;\n\tprivate int newPipeRenderList = -1;\n\t@Getter\n\tprivate CoreUnroutedPipe dummyPipe;\n\n\tpublic ItemLogisticsPipe() {\n\t\tsuper();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {\n\t\tBlock block = LPBlocks.pipe;\n\n\t\tIBlockState iblockstate = worldIn.getBlockState(pos);\n\t\tBlock worldBlock = iblockstate.getBlock();\n\n\t\tif (!worldBlock.isReplaceable(worldIn, pos)) {\n\t\t\tpos = pos.offset(facing);\n\t\t}\n\n\t\tItemStack itemstack = player.getHeldItem(hand);\n\n\t\tif (itemstack.isEmpty()) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\n\t\tif (!dummyPipe.isMultiBlock()) {\n\t\t\tif (player.canPlayerEdit(pos, facing, itemstack) && worldIn.mayPlace(block, pos, false, facing, null)) {\n\t\t\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.createPipe(this);\n\n\t\t\t\tif (pipe == null) {\n\t\t\t\t\tLogisticsPipes.log.log(Level.WARN, \"Pipe failed to create during placement at {0},{1},{2}\", new Object[] { pos.getX(), pos.getY(), pos.getZ() });\n\t\t\t\t\treturn EnumActionResult.PASS;\n\t\t\t\t}\n\n\t\t\t\tif (LogisticsBlockGenericPipe.placePipe(pipe, worldIn, pos, block, null)) {\n\t\t\t\t\tIBlockState state = worldIn.getBlockState(pos);\n\t\t\t\t\tif (state.getBlock() == block) {\n\t\t\t\t\t\t//setTileEntityNBT(world, player, pos, stack);\n\t\t\t\t\t\tblock.onBlockPlacedBy(worldIn, pos, state, player, itemstack);\n\n\t\t\t\t\t\tif (player instanceof EntityPlayerMP)\n\t\t\t\t\t\t\tCriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP) player, pos, itemstack);\n\n\t\t\t\t\t\tIBlockState newBlockState = worldIn.getBlockState(pos);\n\t\t\t\t\t\tSoundType soundtype = newBlockState.getBlock().getSoundType(newBlockState, worldIn, pos, player);\n\t\t\t\t\t\tworldIn.playSound(player, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F,\n\t\t\t\t\t\t\t\tsoundtype.getPitch() * 0.8F);\n\n\t\t\t\t\t\titemstack.shrink(1);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn EnumActionResult.SUCCESS;\n\t\t\t} else {\n\t\t\t\treturn EnumActionResult.FAIL;\n\t\t\t}\n\t\t} else {\n\t\t\tCoreMultiBlockPipe multiPipe = (CoreMultiBlockPipe) dummyPipe;\n\t\t\tboolean isFreeSpace = true;\n\t\t\tDoubleCoordinates placeAt = new DoubleCoordinates(pos);\n\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> globalPos = new LPPositionSet<>(DoubleCoordinatesType.class);\n\t\t\tglobalPos.add(new DoubleCoordinatesType<>(placeAt, CoreMultiBlockPipe.SubBlockTypeForShare.NON_SHARE));\n\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> positions = multiPipe.getSubBlocks();\n\t\t\tITubeOrientation orientation = multiPipe.getTubeOrientation(player, pos.getX(), pos.getZ());\n\t\t\tif (orientation == null) {\n\t\t\t\treturn EnumActionResult.FAIL;\n\t\t\t}\n\t\t\torientation.rotatePositions(positions);\n\t\t\tpositions.stream().map(iPos -> iPos.add(placeAt)).forEach(globalPos::add);\n\t\t\tglobalPos.addToAll(orientation.getOffset());\n\t\t\tplaceAt.add(orientation.getOffset());\n\n\t\t\tfor (DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare> iPos : globalPos) {\n\t\t\t\tif (!player.canPlayerEdit(iPos.getBlockPos(), facing, itemstack) || !worldIn.mayPlace(block, iPos.getBlockPos(), false, facing, null)) {\n\t\t\t\t\tTileEntity tile = worldIn.getTileEntity(iPos.getBlockPos());\n\t\t\t\t\tboolean canPlace = false;\n\t\t\t\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\t\t\tif (CoreMultiBlockPipe.canShare(((LogisticsTileGenericSubMultiBlock) tile).getSubTypes(), iPos.getType())) {\n\t\t\t\t\t\t\tcanPlace = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!canPlace) {\n\t\t\t\t\t\tisFreeSpace = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (isFreeSpace) {\n\t\t\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.createPipe(this);\n\n\t\t\t\tif (pipe == null) {\n\t\t\t\t\tLogisticsPipes.log.log(Level.WARN, \"Pipe failed to create during placement at {0},{1},{2}\", new Object[] { pos.getX(), pos.getY(), pos.getZ() });\n\t\t\t\t\treturn EnumActionResult.SUCCESS;\n\t\t\t\t}\n\n\t\t\t\tif (LogisticsBlockGenericPipe.placePipe(pipe, worldIn, placeAt.getBlockPos(), block, orientation)) {\n\t\t\t\t\tIBlockState state = worldIn.getBlockState(placeAt.getBlockPos());\n\t\t\t\t\tif (state.getBlock() == block) {\n\t\t\t\t\t\t//setTileEntityNBT(world, player, pos, stack);\n\t\t\t\t\t\tblock.onBlockPlacedBy(worldIn, pos, state, player, itemstack);\n\n\t\t\t\t\t\tif (player instanceof EntityPlayerMP)\n\t\t\t\t\t\t\tCriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP) player, placeAt.getBlockPos(), itemstack);\n\n\t\t\t\t\t\tIBlockState newBlockState = worldIn.getBlockState(placeAt.getBlockPos());\n\t\t\t\t\t\tSoundType soundtype = newBlockState.getBlock().getSoundType(newBlockState, worldIn, placeAt.getBlockPos(), player);\n\t\t\t\t\t\tworldIn.playSound(player, placeAt.getBlockPos(), soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F,\n\t\t\t\t\t\t\t\tsoundtype.getPitch() * 0.8F);\n\n\t\t\t\t\t\titemstack.shrink(1);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn EnumActionResult.SUCCESS;\n\t\t\t} else {\n\t\t\t\treturn EnumActionResult.FAIL;\n\t\t\t}\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic void setPipesIcons(IIconProvider iconProvider) {\n\t}\n\n\tpublic void setPipeIconIndex(int index, int newIndex) {\n\t\tnewPipeIconIndex = newIndex;\n\t}\n\n\tpublic int getNewPipeIconIndex() {\n\t\treturn newPipeIconIndex;\n\t}\n\n\tpublic int getNewPipeRenderList() {\n\t\treturn newPipeRenderList;\n\t}\n\n\tpublic void setNewPipeRenderList(int list) {\n\t\tif (newPipeRenderList != -1) {\n\t\t\tthrow new UnsupportedOperationException(\"Can't reset this\");\n\t\t}\n\t\tnewPipeRenderList = list;\n\t}\n\n\tpublic void setDummyPipe(CoreUnroutedPipe pipe) {\n\t\tdummyPipe = pipe;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemLogisticsProgrammer.java",
    "content": "package logisticspipes.items;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class ItemLogisticsProgrammer extends LogisticsItem {\n\n\tpublic static final String RECIPE_TARGET = \"LogisticsRecipeTarget\";\n\n\tpublic ItemLogisticsProgrammer() {\n\t\tsuper();\n\t\tsetNoRepair();\n\t\tsetContainerItem(this);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack getContainerItem(@Nonnull ItemStack itemStack) {\n\t\tItemStack items = super.getContainerItem(itemStack);\n\t\titems.setTagCompound(itemStack.getTagCompound());\n\t\treturn items;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tif (!stack.isEmpty()) {\n\t\t\tif (stack.hasTagCompound()) {\n\t\t\t\tNBTTagCompound nbt = stack.getTagCompound();\n\t\t\t\tString target = nbt.getString(RECIPE_TARGET);\n\t\t\t\tif (!target.isEmpty()) {\n\t\t\t\t\tItem targetItem = REGISTRY.getObject(new ResourceLocation(target));\n\t\t\t\t\tif (targetItem instanceof ItemModule) {\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForModule\"));\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(targetItem.getTranslationKey() + \".name\"));\n\t\t\t\t\t} else if (targetItem instanceof ItemUpgrade) {\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUpgrade\"));\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(targetItem.getTranslationKey() + \".name\"));\n\t\t\t\t\t} else if (targetItem instanceof ItemLogisticsPipe) {\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForPipe\"));\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(targetItem.getTranslationKey() + \".name\"));\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUnknown.1\"));\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUnknown.2\"));\n\t\t\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUnknown.3\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUnknown.1\"));\n\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUnknown.2\"));\n\t\t\t\ttooltip.add(TextUtil.translate(\"tooltip.programmerForUnknown.3\"));\n\t\t\t}\n\t\t}\n\t\tsuper.addInformation(stack, worldIn, tooltip, flagIn);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemModule.java",
    "content": "package logisticspipes.items;\n\nimport java.util.List;\nimport java.util.function.Supplier;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagString;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.ActionResult;\nimport net.minecraft.util.EnumActionResult;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\nimport net.minecraftforge.registries.IForgeRegistry;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.IWorldProvider;\nimport logisticspipes.logisticspipes.ItemModuleInformationManager;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.modules.ModuleCreativeTabBasedItemSink;\nimport logisticspipes.modules.ModuleEnchantmentSink;\nimport logisticspipes.modules.ModuleEnchantmentSinkMK2;\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.modules.ModuleModBasedItemSink;\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.modules.ModulePassiveSupplier;\nimport logisticspipes.modules.ModulePolymorphicItemSink;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.modules.ModuleTerminus;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.DummyWorldProvider;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.module.AsyncExtractorModule;\nimport network.rs485.logisticspipes.module.AsyncQuicksortModule;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class ItemModule extends LogisticsItem {\n\n\tprivate static class Module {\n\n\t\tprivate final Supplier<? extends LogisticsModule> moduleConstructor;\n\t\tprivate final Class<? extends LogisticsModule> moduleClass;\n\n\t\tprivate Module(Supplier<? extends LogisticsModule> moduleConstructor) {\n\t\t\tthis.moduleConstructor = moduleConstructor;\n\t\t\tthis.moduleClass = moduleConstructor.get().getClass();\n\t\t}\n\n\t\tprivate LogisticsModule getILogisticsModule() {\n\t\t\tif (moduleConstructor == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn moduleConstructor.get();\n\t\t}\n\n\t\tprivate Class<? extends LogisticsModule> getILogisticsModuleClass() {\n\t\t\treturn moduleClass;\n\t\t}\n\n\t}\n\n\tprivate final Module moduleType;\n\n\tpublic ItemModule(Module moduleType) {\n\t\tsuper();\n\t\tthis.moduleType = moduleType;\n\t\tsetHasSubtypes(false);\n\t}\n\n\tpublic static void loadModules(IForgeRegistry<Item> registry) {\n\t\tregisterModule(registry, ModuleItemSink.getName(), ModuleItemSink::new);\n\t\tregisterModule(registry, ModulePassiveSupplier.getName(), ModulePassiveSupplier::new);\n\t\tregisterModule(registry, AsyncExtractorModule.getName(), AsyncExtractorModule::new);\n\t\tregisterModule(registry, ModulePolymorphicItemSink.getName(), ModulePolymorphicItemSink::new);\n\t\tregisterModule(registry, AsyncQuicksortModule.getName(), AsyncQuicksortModule::new);\n\t\tregisterModule(registry, ModuleTerminus.getName(), ModuleTerminus::new);\n\t\tregisterModule(registry, AsyncAdvancedExtractor.getName(), AsyncAdvancedExtractor::new);\n\t\tregisterModule(registry, ModuleProvider.getName(), ModuleProvider::new);\n\t\tregisterModule(registry, ModuleModBasedItemSink.getName(), ModuleModBasedItemSink::new);\n\t\tregisterModule(registry, ModuleOreDictItemSink.getName(), ModuleOreDictItemSink::new);\n\t\tregisterModule(registry, ModuleEnchantmentSink.getName(), ModuleEnchantmentSink::new);\n\t\tregisterModule(registry, ModuleEnchantmentSinkMK2.getName(), ModuleEnchantmentSinkMK2::new);\n\t\t//registerModule(registry, \"quick_sort_cc\", ModuleCCBasedQuickSort::new);\n\t\t//registerModule(registry, \"item_sink_cc\", ModuleCCBasedItemSink::new);\n\t\tregisterModule(registry, ModuleCrafter.getName(), ModuleCrafter::new);\n\t\tregisterModule(registry, ModuleActiveSupplier.getName(), ModuleActiveSupplier::new);\n\t\tregisterModule(registry, ModuleCreativeTabBasedItemSink.getName(), ModuleCreativeTabBasedItemSink::new);\n\t}\n\n\tpublic static void registerModule(IForgeRegistry<Item> registry, String name,\n\t\t\t@Nonnull Supplier<? extends LogisticsModule> moduleConstructor) {\n\t\tregisterModule(registry, name, moduleConstructor, LPConstants.LP_MOD_ID);\n\t}\n\n\tpublic static void registerModule(IForgeRegistry<Item> registry, String name,\n\t\t\t@Nonnull Supplier<? extends LogisticsModule> moduleConstructor, String modID) {\n\t\tItemModule module = LogisticsPipes\n\t\t\t\t.setName(new ItemModule(new Module(moduleConstructor)), String.format(\"module_%s\", name), modID);\n\t\tLPItems.modules.put(name, module.getRegistryName());\n\t\tregistry.register(module);\n\t}\n\n\t@Nullable\n\tpublic static LogisticsModule getLogisticsModule(@Nonnull EntityPlayer player, int invSlot) {\n\t\tItemStack item = player.inventory.mainInventory.get(invSlot);\n\t\tif (item.isEmpty() || !(item.getItem() instanceof ItemModule)) return null;\n\t\tLogisticsModule module = ((ItemModule) item.getItem()).getModuleForItem(\n\t\t\t\titem, null, new DummyWorldProvider(player.getEntityWorld()), null\n\t\t);\n\t\tif (module == null) return null;\n\t\tmodule.registerPosition(ModulePositionType.IN_HAND, invSlot);\n\t\tItemModuleInformationManager.readInformation(item, module);\n\t\treturn module;\n\t}\n\n\tprivate void openConfigGui(@Nonnull ItemStack stack, EntityPlayer player, World world) {\n\t\tLogisticsModule module = getModuleForItem(stack, null, new DummyWorldProvider(world), null);\n\t\tif (module instanceof Gui && !stack.isEmpty()) {\n\t\t\tmodule.registerPosition(ModulePositionType.IN_HAND, player.inventory.currentItem);\n\t\t\tItemModuleInformationManager.readInformation(stack, module);\n\t\t\tGui.getInHandGuiProvider((Gui) module).open(player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasEffect(@Nonnull ItemStack stack) {\n\t\tLogisticsModule module = getModuleForItem(stack, null, null, null);\n\t\tif (module != null) {\n\t\t\tif (stack.getCount() > 0) {\n\t\t\t\treturn module.hasEffect();\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ActionResult<ItemStack> onItemRightClick(final World world, final EntityPlayer player,\n\t\t\t@Nonnull final EnumHand hand) {\n\t\tif (MainProxy.isServer(player.world)) {\n\t\t\topenConfigGui(player.getHeldItem(hand), player, world);\n\t\t}\n\t\treturn super.onItemRightClick(world, player, hand);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing,\n\t\t\tfloat hitX, float hitY, float hitZ) {\n\t\tif (MainProxy.isServer(player.world)) {\n\t\t\tTileEntity tile = world.getTileEntity(pos);\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\tif (player.getDisplayName().getUnformattedText()\n\t\t\t\t\t\t.equals(\"ComputerCraft\")) { // Allow turtle to place modules in pipes.\n\t\t\t\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\t\t\t\t\tif (LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\t\t\t\tpipe.blockActivated(player);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn EnumActionResult.PASS;\n\t\t\t}\n\t\t\topenConfigGui(player.inventory.getCurrentItem(), player, world);\n\t\t}\n\t\treturn EnumActionResult.PASS;\n\t}\n\n\t@Nullable\n\tpublic LogisticsModule getModule(\n\t\t\t@Nullable LogisticsModule currentModule,\n\t\t\t@Nullable IWorldProvider world,\n\t\t\t@Nullable IPipeServiceProvider service\n\t) {\n\t\tif (currentModule != null) {\n\t\t\tif (moduleType.getILogisticsModuleClass().equals(currentModule.getClass())) {\n\t\t\t\treturn currentModule;\n\t\t\t}\n\t\t}\n\t\tLogisticsModule newModule = moduleType.getILogisticsModule();\n\t\tif (newModule == null) {\n\t\t\treturn null;\n\t\t}\n\t\tnewModule.registerHandler(world, service);\n\t\treturn newModule;\n\t}\n\n\t@Nullable\n\tpublic LogisticsModule getModuleForItem(\n\t\t\t@Nonnull ItemStack itemStack,\n\t\t\t@Nullable LogisticsModule currentModule,\n\t\t\t@Nullable IWorldProvider world,\n\t\t\t@Nullable IPipeServiceProvider service\n\t) {\n\n\t\tif (itemStack.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\t\tif (itemStack.getItem() != this) {\n\t\t\treturn null;\n\t\t}\n\t\treturn getModule(currentModule, world, service);\n\t}\n\n\t@Override\n\tpublic String getModelSubdir() {\n\t\treturn \"module\";\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip,\n\t\t\tITooltipFlag flagIn) {\n\t\tif (stack.hasTagCompound()) {\n\t\t\tNBTTagCompound nbt = stack.getTagCompound();\n\t\t\tassert nbt != null;\n\n\t\t\tif (nbt.hasKey(\"informationList\")) {\n\t\t\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {\n\t\t\t\t\tNBTTagList nbttaglist = nbt.getTagList(\"informationList\", 8);\n\t\t\t\t\tfor (int i = 0; i < nbttaglist.tagCount(); i++) {\n\t\t\t\t\t\tObject nbtTag = nbttaglist.get(i);\n\t\t\t\t\t\tString data = ((NBTTagString) nbtTag).getString();\n\t\t\t\t\t\tif (data.equals(\"<inventory>\") && i + 1 < nbttaglist.tagCount()) {\n\t\t\t\t\t\t\tnbtTag = nbttaglist.get(i + 1);\n\t\t\t\t\t\t\tdata = ((NBTTagString) nbtTag).getString();\n\t\t\t\t\t\t\tif (data.startsWith(\"<that>\")) {\n\t\t\t\t\t\t\t\tString prefix = data.substring(6);\n\t\t\t\t\t\t\t\tNBTTagCompound module = nbt.getCompoundTag(\"moduleInformation\");\n\t\t\t\t\t\t\t\tint size = module.getTagList(prefix + \"items\", module.getId()).tagCount();\n\t\t\t\t\t\t\t\tif (module.hasKey(prefix + \"itemsCount\")) {\n\t\t\t\t\t\t\t\t\tsize = module.getInteger(prefix + \"itemsCount\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tItemIdentifierInventory inv = new ItemIdentifierInventory(size,\n\t\t\t\t\t\t\t\t\t\t\"InformationTempInventory\", Integer.MAX_VALUE);\n\t\t\t\t\t\t\t\tinv.readFromNBT(module, prefix);\n\t\t\t\t\t\t\t\tfor (int pos = 0; pos < inv.getSizeInventory(); pos++) {\n\t\t\t\t\t\t\t\t\tItemIdentifierStack identStack = inv.getIDStackInSlot(pos);\n\t\t\t\t\t\t\t\t\tif (identStack != null) {\n\t\t\t\t\t\t\t\t\t\tif (identStack.getStackSize() > 1) {\n\t\t\t\t\t\t\t\t\t\t\ttooltip.add(\"  \" + identStack.getStackSize() + \"x \" + identStack\n\t\t\t\t\t\t\t\t\t\t\t\t\t.getFriendlyName());\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\ttooltip.add(\"  \" + identStack.getFriendlyName());\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttooltip.add(data);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tTextUtil.addTooltipInformation(stack, tooltip, false);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tTextUtil.addTooltipInformation(stack, tooltip, Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT));\n\t\t\t}\n\t\t} else {\n\t\t\tTextUtil.addTooltipInformation(stack, tooltip, Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemParts.java",
    "content": "package logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.NonNullList;\n\npublic class ItemParts extends LogisticsItem {\n\n\tpublic ItemParts() {\n\t\tsuper();\n\t\tsetHasSubtypes(true);\n\t}\n\n\t@Override\n\tpublic int getModelCount() {\n\t\treturn 4;\n\t}\n\n\t@Override\n\tpublic String getModelSubdir() {\n\t\treturn \"parts\";\n\t}\n\n\t@Override\n\tpublic void getSubItems(@Nonnull CreativeTabs tab, @Nonnull NonNullList<ItemStack> items) {\n\t\tif (isInCreativeTab(tab)) {\n\t\t\titems.add(new ItemStack(this, 1, 0));\n\t\t\titems.add(new ItemStack(this, 1, 1));\n\t\t\titems.add(new ItemStack(this, 1, 2));\n\t\t\titems.add(new ItemStack(this, 1, 3));\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemPipeController.java",
    "content": "package logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ActionResult;\nimport net.minecraft.util.EnumActionResult;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.guis.LogisticsPlayerSettingsGuiProvider;\nimport logisticspipes.proxy.MainProxy;\n\npublic class ItemPipeController extends LogisticsItem {\n\n\tpublic ItemPipeController() {\n\t\tsuper();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, @Nonnull EnumHand handIn) {\n\t\tItemStack stack = player.getHeldItem(handIn);\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn new ActionResult<>(EnumActionResult.PASS, stack);\n\t\t}\n\t\tuseItem(player, world);\n\t\treturn new ActionResult<>(EnumActionResult.SUCCESS, stack);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn EnumActionResult.PASS;\n\t\t}\n\t\tuseItem(player, world);\n\t\treturn EnumActionResult.SUCCESS;\n\t}\n\n\tprivate void useItem(EntityPlayer player, World world) {\n\t\tNewGuiHandler.getGui(LogisticsPlayerSettingsGuiProvider.class).open(player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemPipeManager.java",
    "content": "package logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\n\nimport logisticspipes.api.ILPPipeConfigTool;\nimport logisticspipes.api.ILPPipeTile;\n\npublic class ItemPipeManager extends LogisticsItem implements ILPPipeConfigTool {\n\n\tpublic ItemPipeManager() {\n\t\tsuper();\n\t}\n\n\t@Override\n\tpublic boolean canWrench(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void wrenchUsed(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {}\n\n\t@Override\n\tpublic boolean doesSneakBypassUse(@Nonnull ItemStack stack, IBlockAccess world, BlockPos pos, EntityPlayer player) {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemPipeSignCreator.java",
    "content": "package logisticspipes.items;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.enchantment.Enchantment;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.ActionResult;\nimport net.minecraft.util.EnumActionResult;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.signs.CraftingPipeSign;\nimport logisticspipes.pipes.signs.IPipeSign;\nimport logisticspipes.pipes.signs.ItemAmountPipeSign;\nimport logisticspipes.proxy.MainProxy;\n\npublic class ItemPipeSignCreator extends LogisticsItem {\n\n\tpublic static final List<Class<? extends IPipeSign>> signTypes = new ArrayList<>();\n\n\t//private TextureAtlasSprite[] itemIcon = new TextureAtlasSprite[2];\n\n\tpublic ItemPipeSignCreator() {\n\t\tsuper();\n\t\tsetMaxStackSize(1);\n\t\tsetMaxDamage(250);\n\t\tsetHasSubtypes(true);\n\t}\n\n\t@Override\n\tpublic boolean isEnchantable(@Nonnull ItemStack stack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canApplyAtEnchantingTable(@Nonnull ItemStack stack, Enchantment enchantment) {\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\t\tItemStack itemStack = player.inventory.getCurrentItem();\n\t\tif (itemStack.isEmpty() || itemStack.getItemDamage() > this.getMaxDamage()) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\n\t\tif (!itemStack.hasTagCompound()) {\n\t\t\titemStack.setTagCompound(new NBTTagCompound());\n\t\t}\n\t\titemStack.getTagCompound().setInteger(\"PipeClicked\", 0);\n\n\t\tint mode = itemStack.getTagCompound().getInteger(\"CreatorMode\");\n\n\t\tif (facing == null) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\n\t\tif (!(((LogisticsTileGenericPipe) tile).pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\n\t\tCoreRoutedPipe pipe = (CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe;\n\t\tif (pipe == null) {\n\t\t\treturn EnumActionResult.FAIL;\n\t\t}\n\t\tif (!player.isSneaking()) {\n\t\t\tif (pipe.hasPipeSign(facing)) {\n\t\t\t\tpipe.activatePipeSign(facing, player);\n\t\t\t\treturn EnumActionResult.SUCCESS;\n\t\t\t} else if (mode >= 0 && mode < ItemPipeSignCreator.signTypes.size()) {\n\t\t\t\tClass<? extends IPipeSign> signClass = ItemPipeSignCreator.signTypes.get(mode);\n\t\t\t\ttry {\n\t\t\t\t\tIPipeSign sign = signClass.newInstance();\n\t\t\t\t\tif (sign.isAllowedFor(pipe)) {\n\t\t\t\t\t\titemStack.damageItem(1, player);\n\t\t\t\t\t\tsign.addSignTo(pipe, facing, player);\n\t\t\t\t\t\treturn EnumActionResult.SUCCESS;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn EnumActionResult.FAIL;\n\t\t\t\t\t}\n\t\t\t\t} catch (InstantiationException | IllegalAccessException e) {\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn EnumActionResult.FAIL;\n\t\t\t}\n\t\t} else {\n\t\t\tif (pipe.hasPipeSign(facing)) {\n\t\t\t\tpipe.removePipeSign(facing, player);\n\t\t\t\titemStack.damageItem(-1, player);\n\t\t\t}\n\t\t\treturn EnumActionResult.SUCCESS;\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getMetadata(@Nonnull ItemStack stack) {\n\t\tif (stack.isEmpty() || !stack.hasTagCompound()) return 0;\n\t\tint mode = Objects.requireNonNull(stack.getTagCompound()).getInteger(\"CreatorMode\");\n\t\treturn Math.min(mode, ItemPipeSignCreator.signTypes.size() - 1);\n\t}\n\n\t@Override\n\tpublic int getModelCount() {\n\t\treturn signTypes.size();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ActionResult<ItemStack> onItemRightClick(final World world, final EntityPlayer player, @Nonnull final EnumHand hand) {\n\t\tItemStack stack = player.inventory.getCurrentItem();\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn ActionResult.newResult(EnumActionResult.PASS, stack);\n\t\t}\n\t\tif (player.isSneaking()) {\n\t\t\tif (!stack.hasTagCompound()) {\n\t\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t\t}\n\t\t\tif (!stack.getTagCompound().hasKey(\"PipeClicked\")) {\n\t\t\t\tint mode = stack.getTagCompound().getInteger(\"CreatorMode\");\n\t\t\t\tmode++;\n\t\t\t\tif (mode >= ItemPipeSignCreator.signTypes.size()) {\n\t\t\t\t\tmode = 0;\n\t\t\t\t}\n\t\t\t\tstack.getTagCompound().setInteger(\"CreatorMode\", mode);\n\t\t\t}\n\t\t}\n\t\tif (stack.hasTagCompound()) {\n\t\t\tstack.getTagCompound().removeTag(\"PipeClicked\");\n\t\t}\n\t\treturn ActionResult.newResult(EnumActionResult.SUCCESS, stack);\n\t}\n\n\tpublic static void registerPipeSignTypes() {\n\t\t// Never change this order. It defines the id each signType has.\n\t\tItemPipeSignCreator.signTypes.add(CraftingPipeSign.class);\n\t\tItemPipeSignCreator.signTypes.add(ItemAmountPipeSign.class);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/ItemUpgrade.java",
    "content": "package logisticspipes.items;\n\nimport java.text.MessageFormat;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.function.Supplier;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\nimport net.minecraftforge.registries.IForgeRegistry;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.pipes.upgrades.ActionSpeedUpgrade;\nimport logisticspipes.pipes.upgrades.AdvancedSatelliteUpgrade;\nimport logisticspipes.pipes.upgrades.CCRemoteControlUpgrade;\nimport logisticspipes.pipes.upgrades.CombinedSneakyUpgrade;\nimport logisticspipes.pipes.upgrades.ConnectionUpgradeConfig;\nimport logisticspipes.pipes.upgrades.CraftingByproductUpgrade;\nimport logisticspipes.pipes.upgrades.CraftingCleanupUpgrade;\nimport logisticspipes.pipes.upgrades.CraftingMonitoringUpgrade;\nimport logisticspipes.pipes.upgrades.FluidCraftingUpgrade;\nimport logisticspipes.pipes.upgrades.FuzzyUpgrade;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\nimport logisticspipes.pipes.upgrades.ItemExtractionUpgrade;\nimport logisticspipes.pipes.upgrades.ItemStackExtractionUpgrade;\nimport logisticspipes.pipes.upgrades.LogicControllerUpgrade;\nimport logisticspipes.pipes.upgrades.OpaqueUpgrade;\nimport logisticspipes.pipes.upgrades.PatternUpgrade;\nimport logisticspipes.pipes.upgrades.PowerTransportationUpgrade;\nimport logisticspipes.pipes.upgrades.SneakyUpgradeConfig;\nimport logisticspipes.pipes.upgrades.SpeedUpgrade;\nimport logisticspipes.pipes.upgrades.UpgradeModuleUpgrade;\nimport logisticspipes.pipes.upgrades.power.BCPowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.IC2EVPowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.IC2HVPowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.IC2LVPowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.IC2MVPowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.RFPowerSupplierUpgrade;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class ItemUpgrade extends LogisticsItem {\n\n\t//Values\n\tpublic static final int MAX_LIQUID_CRAFTER = 3;\n\tpublic static final int MAX_CRAFTING_CLEANUP = 4;\n\tpublic static final int MAX_ITEM_EXTRACTION = 8;\n\tpublic static final int MAX_ITEM_STACK_EXTRACTION = 8;\n\n\tprivate static class Upgrade {\n\n\t\tprivate Supplier<? extends IPipeUpgrade> upgradeConstructor;\n\t\tprivate Class<? extends IPipeUpgrade> upgradeClass;\n\n\t\tprivate Upgrade(Supplier<? extends IPipeUpgrade> moduleConstructor) {\n\t\t\tupgradeConstructor = moduleConstructor;\n\t\t\tupgradeClass = moduleConstructor.get().getClass();\n\t\t}\n\n\t\tprivate IPipeUpgrade getIPipeUpgrade() {\n\t\t\tif (upgradeConstructor == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn upgradeConstructor.get();\n\t\t}\n\n\t\tprivate Class<? extends IPipeUpgrade> getIPipeUpgradeClass() {\n\t\t\treturn upgradeClass;\n\t\t}\n\t}\n\n\tprivate Upgrade upgradeType;\n\n\tpublic ItemUpgrade(Upgrade upgradeType) {\n\t\tsuper();\n\t\tthis.upgradeType = upgradeType;\n\t\tsetHasSubtypes(false);\n\t}\n\n\tpublic static void loadUpgrades(IForgeRegistry<Item> registry) {\n\t\tregisterUpgrade(registry, CombinedSneakyUpgrade.getName(), CombinedSneakyUpgrade::new);\n\t\tregisterUpgrade(registry, SneakyUpgradeConfig.getName(), SneakyUpgradeConfig::new);\n\t\tregisterUpgrade(registry, SpeedUpgrade.getName(), SpeedUpgrade::new);\n\t\tregisterUpgrade(registry, ConnectionUpgradeConfig.getName(), ConnectionUpgradeConfig::new);\n\n\t\tregisterUpgrade(registry, AdvancedSatelliteUpgrade.getName(), AdvancedSatelliteUpgrade::new);\n\t\tregisterUpgrade(registry, FluidCraftingUpgrade.getName(), FluidCraftingUpgrade::new);\n\t\tregisterUpgrade(registry, CraftingByproductUpgrade.getName(), CraftingByproductUpgrade::new);\n\t\tregisterUpgrade(registry, PatternUpgrade.getName(), PatternUpgrade::new);\n\t\tregisterUpgrade(registry, FuzzyUpgrade.getName(), FuzzyUpgrade::new);\n\t\tregisterUpgrade(registry, PowerTransportationUpgrade.getName(), PowerTransportationUpgrade::new);\n\t\tregisterUpgrade(registry, BCPowerSupplierUpgrade.getName(), BCPowerSupplierUpgrade::new);\n\t\tregisterUpgrade(registry, RFPowerSupplierUpgrade.getName(), RFPowerSupplierUpgrade::new);\n\t\tregisterUpgrade(registry, IC2LVPowerSupplierUpgrade.getName(), IC2LVPowerSupplierUpgrade::new);\n\t\tregisterUpgrade(registry, IC2MVPowerSupplierUpgrade.getName(), IC2MVPowerSupplierUpgrade::new);\n\t\tregisterUpgrade(registry, IC2HVPowerSupplierUpgrade.getName(), IC2HVPowerSupplierUpgrade::new);\n\t\tregisterUpgrade(registry, IC2EVPowerSupplierUpgrade.getName(), IC2EVPowerSupplierUpgrade::new);\n\t\tregisterUpgrade(registry, CCRemoteControlUpgrade.getName(), CCRemoteControlUpgrade::new);\n\t\tregisterUpgrade(registry, CraftingMonitoringUpgrade.getName(), CraftingMonitoringUpgrade::new);\n\t\tregisterUpgrade(registry, OpaqueUpgrade.getName(), OpaqueUpgrade::new);\n\t\tregisterUpgrade(registry, CraftingCleanupUpgrade.getName(), CraftingCleanupUpgrade::new);\n\t\tregisterUpgrade(registry, LogicControllerUpgrade.getName(), LogicControllerUpgrade::new);\n\t\tregisterUpgrade(registry, UpgradeModuleUpgrade.getName(), UpgradeModuleUpgrade::new);\n\t\tregisterUpgrade(registry, ActionSpeedUpgrade.getName(), ActionSpeedUpgrade::new);\n\t\tregisterUpgrade(registry, ItemExtractionUpgrade.getName(), ItemExtractionUpgrade::new);\n\t\tregisterUpgrade(registry, ItemStackExtractionUpgrade.getName(), ItemStackExtractionUpgrade::new);\n\t}\n\n\t@Nonnull\n\tpublic static Item getAndCheckUpgrade(ResourceLocation resource) {\n\t\tObjects.requireNonNull(resource, \"Resource for upgrade is null. Was the upgrade registered?\");\n\t\treturn Objects.requireNonNull(Item.REGISTRY.getObject(resource), \"Upgrade \" + resource.toString() + \" not found in Item registry\");\n\t}\n\n\tpublic static void registerUpgrade(IForgeRegistry<Item> registry, String name, Supplier<? extends IPipeUpgrade> upgradeConstructor) {\n\t\tItemUpgrade item = LogisticsPipes.setName(new ItemUpgrade(new Upgrade(upgradeConstructor)), String.format(\"upgrade_%s\", name));\n\t\tLPItems.upgrades.put(name, item.getRegistryName());\n\t\tregistry.register(item);\n\t}\n\n\tpublic IPipeUpgrade getUpgradeForItem(@Nonnull ItemStack itemStack, IPipeUpgrade currentUpgrade) {\n\t\tif (itemStack.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\t\tif (itemStack.getItem() != this) {\n\t\t\treturn null;\n\t\t}\n\t\tif (upgradeType.getIPipeUpgradeClass() == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (currentUpgrade != null) {\n\t\t\tif (upgradeType.getIPipeUpgradeClass().equals(currentUpgrade.getClass())) {\n\t\t\t\treturn currentUpgrade;\n\t\t\t}\n\t\t}\n\t\tIPipeUpgrade newUpgrade = upgradeType.getIPipeUpgrade();\n\t\tif (newUpgrade == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn newUpgrade;\n\t}\n\n\t@Override\n\tpublic String getModelSubdir() {\n\t\treturn \"upgrade\";\n\t}\n\n\tpublic static String SHIFT_INFO_PREFIX = \"item.upgrade.info.\";\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tsuper.addInformation(stack, worldIn, tooltip, flagIn);\n\t\tIPipeUpgrade upgrade = getUpgradeForItem(stack, null);\n\t\tif (upgrade == null) {\n\t\t\treturn;\n\t\t}\n\t\tList<String> pipe = Arrays.asList(upgrade.getAllowedPipes());\n\t\tList<String> module = Arrays.asList(upgrade.getAllowedModules());\n\t\tif (pipe.isEmpty() && module.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {\n\t\t\tif (!pipe.isEmpty() && !module.isEmpty()) {\n\t\t\t\t//Can be applied to {0} pipes\n\t\t\t\t//and {0} modules\n\t\t\t\tString base1 = TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + \"both1\");\n\t\t\t\tString base2 = TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + \"both2\");\n\t\t\t\ttooltip.add(MessageFormat.format(base1, join(pipe)));\n\t\t\t\ttooltip.add(MessageFormat.format(base2, join(module)));\n\t\t\t} else if (!pipe.isEmpty()) {\n\t\t\t\t//Can be applied to {0} pipes\n\t\t\t\tString base = TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + \"pipe\");\n\t\t\t\ttooltip.add(MessageFormat.format(base, join(pipe)));\n\t\t\t} else {\n\t\t\t\t//Can be applied to {0} modules\n\t\t\t\tString base = TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + \"module\");\n\t\t\t\ttooltip.add(MessageFormat.format(base, join(module)));\n\t\t\t}\n\t\t} else {\n\t\t\tTextUtil.addTooltipInformation(stack, tooltip, false);\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprivate String join(List<String> join) {\n\t\tStringBuilder builder = new StringBuilder();\n\t\tfor (int i = 0; i < join.size() - 2; i++) {\n\t\t\tbuilder.append(TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + join.get(i)));\n\t\t\tbuilder.append(\", \");\n\t\t}\n\t\tif (join.size() > 1) {\n\t\t\tbuilder.append(TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + join.get(join.size() - 2)));\n\t\t\tbuilder.append(\" and \");\n\t\t}\n\t\tbuilder.append(TextUtil.translate(ItemUpgrade.SHIFT_INFO_PREFIX + join.get(join.size() - 1)));\n\t\treturn builder.toString();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/LogisticsBrokenItem.java",
    "content": "package logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.interfaces.IItemAdvancedExistance;\n\npublic class LogisticsBrokenItem extends LogisticsItem implements IItemAdvancedExistance {\n\n\tprivate static final String PREFIX = \"tooltip.brokenItem.\";\n\n\t@Override\n\tpublic boolean canExistInNormalInventory(@Nonnull ItemStack stack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canExistInWorld(@Nonnull ItemStack stack) {\n\t\treturn false;\n\t}\n\n//\t@Override\n//\t@SideOnly(Side.CLIENT)\n//\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n//\t\ttooltip.add(\" - \" + TextUtil.translate(LogisticsBrokenItem.PREFIX + \"1\"));\n//\t\ttooltip.add(\" - \" + TextUtil.translate(LogisticsBrokenItem.PREFIX + \"2\"));\n//\t\ttooltip.add(\"    \" + TextUtil.translate(LogisticsBrokenItem.PREFIX + \"3\"));\n//\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/LogisticsFluidContainer.java",
    "content": "package logisticspipes.items;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.text.translation.I18n;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.interfaces.IItemAdvancedExistance;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class LogisticsFluidContainer extends LogisticsItem implements IItemAdvancedExistance {\n\n\tstatic int capacity = 8000;\n\n\tpublic LogisticsFluidContainer() {\n\t\tsetMaxStackSize(1);\n\t}\n\n\t@Override\n\tpublic boolean canExistInNormalInventory(@Nonnull ItemStack stack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canExistInWorld(@Nonnull ItemStack stack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic String getTranslationKey(@Nonnull ItemStack stack) {\n\t\tFluidIdentifierStack fluidStack = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(ItemIdentifierStack.getFromStack(stack));\n\t\tif (fluidStack != null) {\n\t\t\tString s = fluidStack.makeFluidStack().getFluid().getUnlocalizedName();\n\t\t\tif (s != null) {\n\t\t\t\treturn s;\n\t\t\t}\n\t\t}\n\t\treturn super.getTranslationKey(stack);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic String getItemStackDisplayName(@Nonnull ItemStack itemstack) {\n\t\tString translationKey = getTranslationKey(itemstack);\n\t\tString unlocalizedNameInefficiently = getUnlocalizedNameInefficiently(itemstack); // Fix for Logistics fluid container naming\n\t\treturn I18n.translateToLocal(translationKey + (translationKey.equals(unlocalizedNameInefficiently) ? \".name\" : \"\")).trim();\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tsuper.addInformation(stack, worldIn, tooltip, flagIn);\n\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {\n\t\t\tFluidIdentifierStack fluidStack = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(ItemIdentifierStack.getFromStack(stack));\n\t\t\tif (fluidStack != null) {\n\t\t\t\ttooltip.add(\"Type:  \" + fluidStack.makeFluidStack().getFluid().getLocalizedName(fluidStack.makeFluidStack()));\n\t\t\t\ttooltip.add(\"Value: \" + fluidStack.getAmount() + \"mB\");\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void getSubItems(@Nonnull CreativeTabs tab, @Nonnull NonNullList<ItemStack> items) {\n\t\t// don't add to creative tabs in any way\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/LogisticsItem.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * <p>\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.items;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.text.translation.I18n;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ILogisticsItem;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class LogisticsItem extends Item implements ILogisticsItem {\n\n\tpublic LogisticsItem() {\n\t\tsetCreativeTab(LogisticsPipes.CREATIVE_TAB_LP);\n\t}\n\n\t@Override\n\tpublic String getModelPath() {\n\t\tString modelFile = getRegistryName().getPath();\n\t\tString dir = getModelSubdir();\n\t\tif (!dir.isEmpty()) {\n\t\t\tif (modelFile.startsWith(String.format(\"%s_\", dir))) {\n\t\t\t\tmodelFile = modelFile.substring(dir.length() + 1);\n\t\t\t}\n\t\t\treturn String.format(\"%s/%s\", dir, modelFile).replaceAll(\"/+\", \"/\");\n\t\t}\n\t\treturn modelFile;\n\t}\n\n\tpublic String getModelSubdir() {\n\t\treturn \"\";\n\t}\n\n\tpublic int getModelCount() {\n\t\treturn 1;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getTranslationKey(@Nonnull ItemStack stack) {\n\t\tif (getHasSubtypes()) {\n\t\t\treturn String.format(\"%s.%d\", super.getTranslationKey(stack), stack.getMetadata());\n\t\t}\n\t\treturn super.getTranslationKey(stack);\n\t}\n\n\t/**\n\t * Adds all keys from the translation file in the format:\n\t * item.className.tip([0-9]*) Tips start from 1 and increment. Sparse rows\n\t * should be left empty (ie empty line must still have a key present) Shift\n\t * shows full tooltip, without it, you just get the first line.\n\t */\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tsuper.addInformation(stack, worldIn, tooltip, flagIn);\n\t\tif (addShiftInfo()) {\n\t\t\tTextUtil.addTooltipInformation(stack, tooltip, Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT));\n\t\t}\n\t}\n\n\tpublic boolean addShiftInfo() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getItemStackDisplayName(@Nonnull ItemStack itemstack) {\n\t\treturn I18n.translateToLocal(getTranslationKey(itemstack) + \".name\").trim();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/LogisticsItemCard.java",
    "content": "package logisticspipes.items;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.interfaces.IItemAdvancedExistance;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class LogisticsItemCard extends LogisticsItem implements IItemAdvancedExistance {\n\n\tpublic static final int FREQ_CARD = 0;\n\tpublic static final int SEC_CARD = 1;\n\n\tpublic LogisticsItemCard() {\n\t\thasSubtypes = true;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tsuper.addInformation(stack, worldIn, tooltip, flagIn);\n\t\tif (!stack.hasTagCompound()) {\n\t\t\ttooltip.add(TextUtil.translate(\"tooltip.logisticsItemCard\"));\n\t\t} else {\n\t\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\t\tif (tag.hasKey(\"UUID\")) {\n\t\t\t\tif (stack.getItemDamage() == LogisticsItemCard.FREQ_CARD) {\n\t\t\t\t\ttooltip.add(\"Freq. Card\");\n\t\t\t\t} else if (stack.getItemDamage() == LogisticsItemCard.SEC_CARD) {\n\t\t\t\t\ttooltip.add(\"Sec. Card\");\n\t\t\t\t}\n\t\t\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {\n\t\t\t\t\ttooltip.add(\"Id: \" + tag.getString(\"UUID\"));\n\t\t\t\t\tif (stack.getItemDamage() == LogisticsItemCard.SEC_CARD) {\n\t\t\t\t\t\tUUID id = UUID.fromString(tag.getString(\"UUID\"));\n\t\t\t\t\t\ttooltip.add(\"Authorization: \" + (SimpleServiceLocator.securityStationManager.isAuthorized(id) ? \"Authorized\" : \"Unauthorized\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean getShareTag() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int getItemStackLimit() {\n\t\treturn 64;\n\t}\n\n\t@Override\n\tpublic boolean canExistInNormalInventory(@Nonnull ItemStack stack) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean canExistInWorld(@Nonnull ItemStack stack) {\n\t\treturn stack.getItemDamage() != LogisticsItemCard.SEC_CARD;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/items/LogisticsSolidBlockItem.java",
    "content": "package logisticspipes.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemBlock;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.text.translation.I18n;\n\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.BlockDummy;\nimport logisticspipes.blocks.LogisticsSolidBlock;\nimport logisticspipes.interfaces.ILogisticsItem;\n\npublic class LogisticsSolidBlockItem extends ItemBlock implements ILogisticsItem {\n\n\t@Getter\n\tprivate final LogisticsSolidBlock.Type type;\n\n\tpublic LogisticsSolidBlockItem(LogisticsSolidBlock block) {\n\t\tsuper(block);\n\t\tsetCreativeTab(LogisticsPipes.CREATIVE_TAB_LP);\n\t\ttype = block.getType();\n\t\tBlockDummy.updateItemMap.put(type.getMeta(), this);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getItemStackDisplayName(@Nonnull ItemStack itemstack) {\n\t\treturn I18n.translateToLocal(getTranslationKey(itemstack) + \".name\");\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/items/RemoteOrderer.java",
    "content": "package logisticspipes.items;\n\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.ActionResult;\nimport net.minecraft.util.EnumActionResult;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.DimensionManager;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.RequestPipeDimension;\nimport logisticspipes.pipes.PipeItemsRemoteOrdererLogistics;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\n\npublic class RemoteOrderer extends LogisticsItem {\n\n\t@Override\n\tpublic String getModelSubdir() {\n\t\treturn \"remote_orderer\";\n\t}\n\n\t@Override\n\tpublic int getModelCount() {\n\t\treturn 17;\n\t}\n\n\t@Override\n\tpublic boolean getShareTag() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {\n\t\tsuper.addInformation(stack, worldIn, tooltip, flagIn);\n\n\t\tif (stack.hasTagCompound() && Objects.requireNonNull(stack.getTagCompound()).hasKey(\"connectedPipe-x\")) {\n\t\t\ttooltip.add(\"\\u00a77Has Remote Pipe\");\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, @Nonnull EnumHand handIn) {\n\t\tItemStack par1ItemStack = player.inventory.getCurrentItem();\n\t\tif (par1ItemStack.isEmpty() || !par1ItemStack.hasTagCompound()) {\n\t\t\treturn ActionResult.newResult(EnumActionResult.FAIL, par1ItemStack);\n\t\t}\n\t\tPipeItemsRemoteOrdererLogistics pipe = RemoteOrderer.getPipe(par1ItemStack);\n\t\tif (pipe != null) {\n\t\t\tif (MainProxy.isServer(player.world)) {\n\t\t\t\tint energyUse = 0;\n\t\t\t\tif (pipe.getWorld() != player.world) {\n\t\t\t\t\tenergyUse += 2500;\n\t\t\t\t}\n\t\t\t\tenergyUse += Math.sqrt(Math.pow(pipe.getX() - player.posX, 2) + Math.pow(pipe.getY() - player.posY, 2) + Math.pow(pipe.getZ() - player.posZ, 2));\n\t\t\t\tif (pipe.useEnergy(energyUse)) {\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RequestPipeDimension.class).setInteger(pipe.getWorld().provider.getDimension()), player);\n\t\t\t\t\tplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Normal_Orderer_ID, pipe.getWorld(), pipe.getX(), pipe.getY(), pipe.getZ());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ActionResult.newResult(EnumActionResult.PASS, par1ItemStack);\n\t}\n\n\tpublic static void connectToPipe(@Nonnull ItemStack stack, PipeItemsRemoteOrdererLogistics pipe) {\n\t\tstack.setTagCompound(new NBTTagCompound());\n\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\ttag.setInteger(\"connectedPipe-x\", pipe.getX());\n\t\ttag.setInteger(\"connectedPipe-y\", pipe.getY());\n\t\ttag.setInteger(\"connectedPipe-z\", pipe.getZ());\n\t\tint dimension = 0;\n\t\tfor (Integer dim : DimensionManager.getIDs()) {\n\t\t\tif (pipe.getWorld().equals(DimensionManager.getWorld(dim))) {\n\t\t\t\tdimension = dim;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ttag.setInteger(\"connectedPipe-world-dim\", dimension);\n\t}\n\n\tpublic static PipeItemsRemoteOrdererLogistics getPipe(@Nonnull ItemStack stack) {\n\t\tif (stack.isEmpty() || !stack.hasTagCompound()) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\tif (!tag.hasKey(\"connectedPipe-x\") || !tag.hasKey(\"connectedPipe-y\") || !tag.hasKey(\"connectedPipe-z\")) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!tag.hasKey(\"connectedPipe-world-dim\")) {\n\t\t\treturn null;\n\t\t}\n\t\tint dim = tag.getInteger(\"connectedPipe-world-dim\");\n\t\tWorld world = DimensionManager.getWorld(dim);\n\t\tif (world == null) {\n\t\t\treturn null;\n\t\t}\n\t\tTileEntity tile = world.getTileEntity(new BlockPos(tag.getInteger(\"connectedPipe-x\"), tag.getInteger(\"connectedPipe-y\"), tag.getInteger(\"connectedPipe-z\")));\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\tCoreUnroutedPipe pipe = ((LogisticsTileGenericPipe) tile).pipe;\n\t\tif (pipe instanceof PipeItemsRemoteOrdererLogistics) {\n\t\t\treturn (PipeItemsRemoteOrdererLogistics) pipe;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void getSubItems(@Nonnull CreativeTabs tab, @Nonnull NonNullList<ItemStack> items) {\n\t\tif (isInCreativeTab(tab)) {\n\t\t\tfor (int meta = 0; meta < 17; meta++) {\n\t\t\t\titems.add(new ItemStack(this, 1, meta));\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/logic/BaseLogicConnection.java",
    "content": "package logisticspipes.logic;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\npublic abstract class BaseLogicConnection {\n\n\t@Getter\n\tprivate final BaseLogicTask source;\n\t@Getter\n\tprivate final int sourceIndex;\n\t@Getter\n\tprivate final BaseLogicTask target;\n\t@Getter\n\tprivate final int targetIndex;\n\t@Getter\n\tprivate final LogicParameterType type;\n\n\t@Getter\n\t@Setter\n\tprivate boolean isInvalidConnection;\n\n\tpublic BaseLogicConnection(BaseLogicTask source, int sourceIndex, BaseLogicTask target, int targetIndex, LogicParameterType type) {\n\t\tthis.source = source;\n\t\tthis.sourceIndex = sourceIndex;\n\t\tthis.target = target;\n\t\tthis.targetIndex = targetIndex;\n\t\tthis.type = type;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/logic/BaseLogicTask.java",
    "content": "package logisticspipes.logic;\n\nimport java.util.UUID;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\n\nimport lombok.Getter;\n\npublic abstract class BaseLogicTask {\n\n\t//Graphical Interface\n\t@Getter\n\tprotected int posX;\n\t@Getter\n\tprotected int posY;\n\t@Getter\n\tprotected String name = getTypeName();\n\t@Getter\n\tprotected String comment = \"\";\n\n\t//Saving and Server/Client sync\n\t@Getter\n\tprotected UUID uuid;\n\n\tpublic BaseLogicTask(NBTTagCompound nbt) {\n\t\tposX = nbt.getInteger(\"posX\");\n\t\tposY = nbt.getInteger(\"posY\");\n\t\tname = nbt.getString(\"name\");\n\t\tcomment = nbt.getString(\"comment\");\n\t\tuuid = UUID.fromString(nbt.getString(\"uuid\"));\n\t}\n\n\tpublic BaseLogicTask(int posX, int posY) {\n\t\tthis.posX = posX;\n\t\tthis.posY = posY;\n\t\tuuid = UUID.randomUUID();\n\t}\n\n\tpublic final NBTTagCompound getNBTTagCompound() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\taddToNBT(nbt);\n\t\treturn nbt;\n\t}\n\n\tprotected void addToNBT(NBTTagCompound nbt) {\n\t\tnbt.setInteger(\"posX\", posX);\n\t\tnbt.setInteger(\"posY\", posY);\n\t\tnbt.setString(\"name\", name);\n\t\tnbt.setString(\"comment\", comment);\n\t\tnbt.setString(\"uuid\", uuid.toString());\n\t}\n\n\tpublic abstract int getAmountOfInput();\n\n\tpublic abstract int getAmountOfOutput();\n\n\tpublic abstract LogicParameterType getInputParameterType(int i);\n\n\tpublic abstract LogicParameterType getOutputParameterType(int i);\n\n\tpublic abstract void setInputParameter(int i, Object value);\n\n\tpublic abstract boolean isCalculated();\n\n\tpublic abstract Object getResult(int i);\n\n\tpublic abstract void resetState();\n\n\tpublic abstract String getTypeName();\n\n\tpublic abstract void syncTick(TileEntity tile);\n}\n"
  },
  {
    "path": "common/logisticspipes/logic/LogicController.java",
    "content": "package logisticspipes.logic;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\n\nimport lombok.Getter;\n\nimport logisticspipes.utils.item.SimpleStackInventory;\n\npublic class LogicController {\n\n\tpublic SimpleStackInventory diskInv = new SimpleStackInventory(1, \"Disk Inv\", 1);\n\n\tpublic List<BaseLogicConnection> connections = new ArrayList<>();\n\tpublic List<BaseLogicTask> tasks = new ArrayList<>();\n\n\tprivate Thread oldThread = null;\n\t@Getter\n\tprivate boolean unresolvedTasks = false;\n\n\tpublic void calculate(TileEntity tile) {\n\t\tif (oldThread != null && oldThread.isAlive()) {\n\t\t\treturn;\n\t\t}\n\t\tfor (BaseLogicTask task : tasks) {\n\t\t\ttask.syncTick(tile);\n\t\t}\n\t\t//oldThread = new Thread() { @Override public void run() {\n\t\tfor (BaseLogicConnection connection : connections) {\n\t\t\tif (!connection.isInvalidConnection()) {\n\t\t\t\tif (connection.getSource().getAmountOfOutput() <= connection.getSourceIndex()) {\n\t\t\t\t\tconnection.setInvalidConnection(true);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (connection.getSource().getOutputParameterType(connection.getSourceIndex()) != connection.getType()) {\n\t\t\t\t\tconnection.setInvalidConnection(true);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (connection.getTarget().getAmountOfInput() <= connection.getTargetIndex()) {\n\t\t\t\t\tconnection.setInvalidConnection(true);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (connection.getTarget().getInputParameterType(connection.getTargetIndex()) != connection.getType()) {\n\t\t\t\t\tconnection.setInvalidConnection(true);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t\tList<BaseLogicTask> toDos = new ArrayList<>(tasks);\n\t\twhile (!toDos.isEmpty()) {\n\t\t\tboolean nothingDone = true;\n\t\t\tIterator<BaseLogicTask> iter = toDos.iterator();\n\t\t\twhile (iter.hasNext()) {\n\t\t\t\tBaseLogicTask task = iter.next();\n\t\t\t\tif (task.isCalculated()) {\n\t\t\t\t\titer.remove();\n\t\t\t\t\tnothingDone = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (BaseLogicConnection connection : connections) {\n\t\t\t\tif (!connection.isInvalidConnection() && connection.getSource().isCalculated()) {\n\t\t\t\t\tconnection.getTarget().setInputParameter(connection.getTargetIndex(), connection.getSource().getResult(connection.getSourceIndex()));\n\t\t\t\t\tnothingDone = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (nothingDone) {\n\t\t\t\tunresolvedTasks = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tunresolvedTasks = false;\n\t\t/*}};\n\t\toldThread.setDaemon(true);\n\t\toldThread.start();\n\t\t//*/\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbt) {\n\t\tdiskInv.writeToNBT(nbt, \"LogicDiskInv\");\n\t\t//TODO\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tdiskInv.readFromNBT(nbt, \"LogicDiskInv\");\n\t\t//TODO\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logic/LogicParameterType.java",
    "content": "package logisticspipes.logic;\n\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\n\npublic enum LogicParameterType {\n\tNumber(long.class),\n\tFloat(double.class),\n\tBoolean(boolean.class),\n\tDirection(EnumFacing.class);\n\n\t@Getter\n\tprivate final Class<?> javaClass;\n\n\tLogicParameterType(Class<?> clazz) {\n\t\tjavaClass = clazz;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logic/gui/LogicLayoutGui.java",
    "content": "package logisticspipes.logic.gui;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.ItemRenderer;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.logic.LogicController;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SimpleGraphics;\nimport logisticspipes.utils.string.ChatColor;\n\npublic class LogicLayoutGui extends LogisticsBaseGuiScreen {\n\n\tprivate enum ZOOM_LEVEL {\n\t\tNORMAL(1, 165, 224, 1, 0),\n\t\tLEVEL_1(0.5F, 330, 465, 1, 50),\n\t\tLEVEL_2(0.25F, 660, 950, 2, 100);\n\n\t\tZOOM_LEVEL(float zoom, int bottom, int right, int line, int moveY) {\n\t\t\tthis.zoom = zoom;\n\t\t\tbottomRenderBorder = bottom;\n\t\t\trightRenderBorder = right;\n\t\t\tthis.line = line;\n\t\t\tthis.moveY = moveY;\n\t\t}\n\n\t\tfinal float zoom;\n\t\tfinal int bottomRenderBorder;\n\t\tfinal int rightRenderBorder;\n\t\tfinal int line;\n\t\tfinal int moveY;\n\n\t\tZOOM_LEVEL next() {\n\t\t\tint id = ordinal();\n\t\t\tif (id + 1 >= ZOOM_LEVEL.values().length) {\n\t\t\t\treturn this;\n\t\t\t} else {\n\t\t\t\treturn ZOOM_LEVEL.values()[id + 1];\n\t\t\t}\n\t\t}\n\n\t\tZOOM_LEVEL prev() {\n\t\t\tint id = ordinal();\n\t\t\tif (id - 1 < 0) {\n\t\t\t\treturn this;\n\t\t\t} else {\n\t\t\t\treturn ZOOM_LEVEL.values()[id - 1];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static final ResourceLocation achievementTextures = new ResourceLocation(\"textures/gui/achievement/achievement_background.png\");\n\n\tprivate final ItemRenderer renderItem = new ItemRenderer(mc);\n\n\tprivate int isMouseButtonDown;\n\tprivate int mouseX;\n\tprivate int mouseY;\n\tprivate double guiMapX;\n\tprivate double guiMapY;\n\tprivate ZOOM_LEVEL zoom = ZOOM_LEVEL.NORMAL;\n\n\tprivate Object[] tooltip = null;\n\n\tpublic LogicLayoutGui(LogicController controller, EntityPlayer player) {\n\t\tsuper(256, 202 + 90, 0, 0);\n\t\tguiMapY = -200;\n\t\tMouse.getDWheel(); // Reset DWheel on GUI open\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, null);\n\t\tdummy.addNormalSlotsForPlayerInventory(50, 205);\n\t\tinventorySlots = dummy;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\t/*\n\t\tbuttonList.clear();\n\t\tthis.buttonList.add(new GuiButton(0, this.width / 2 + 45, this.height / 2 + 74, 80, 20, \"Close\"));\n\t\t */\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {}\n\n\t@Override\n\tpublic void drawScreen(int mouseX, int mouseY, float partialTicks) {\n\t\tsuper.drawScreen(mouseX, mouseY, partialTicks);\n\t\tif (Mouse.isButtonDown(0)) {\n\t\t\tint k = (width - xSize) / 2;\n\t\t\tint l = (height - ySize) / 2;\n\t\t\tint i1 = k + 8;\n\t\t\tint j1 = l + 17;\n\n\t\t\tif ((isMouseButtonDown == 0 || isMouseButtonDown == 1) && mouseX >= i1 && mouseX < i1 + 224 && mouseY >= j1 && mouseY < j1 + 155) {\n\t\t\t\tif (isMouseButtonDown == 0) {\n\t\t\t\t\tisMouseButtonDown = 1;\n\t\t\t\t} else {\n\t\t\t\t\tguiMapX -= (double) (mouseX - this.mouseX) / zoom.zoom;\n\t\t\t\t\tguiMapY -= (double) (mouseY - this.mouseY) / zoom.zoom;\n\t\t\t\t}\n\n\t\t\t\tthis.mouseX = mouseX;\n\t\t\t\tthis.mouseY = mouseY;\n\t\t\t}\n\n\t\t} else {\n\t\t\tisMouseButtonDown = 0;\n\t\t}\n\n\t\tint dWheel = Mouse.getDWheel();\n\t\tif (dWheel < 0) {\n\t\t\tzoom = zoom.next();\n\t\t} else if (dWheel > 0) {\n\t\t\tzoom = zoom.prev();\n\t\t}\n\t\tGL11.glTranslatef(0.0F, 0.0F, 100.0F);\n\t\tif (tooltip != null) {\n\t\t\tGuiGraphics.displayItemToolTip(tooltip, zLevel, guiLeft, guiTop, true);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int i, int j) {\n\t\tsuper.drawGuiContainerBackgroundLayer(f, i, j);\n\t\tdrawTransparentBack();\n\t\tdrawMap(i, j);\n\t\tGuiGraphics.drawGuiBackGround(getMC(), guiLeft, guiTop + 180, right, bottom, zLevel, true, false, true, true, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(getMC(), guiLeft + 50, guiTop + 205);\n\t}\n\n\tprivate void drawTransparentBack() {\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tSimpleGraphics.drawGradientRect(0, 0, width, height, Color.BLANK, Color.BLANK, 0.0);\n\t}\n\n\tprivate void drawMap(int par1, int par2) {\n\t\ttooltip = null;\n\t\tint mapX = (int) Math.floor(guiMapX);\n\t\tint mapY = (int) Math.floor(guiMapY - zoom.moveY);\n\t\tint leftSide = ((width - xSize) / 2);\n\t\tint topSide = ((height - ySize) / 2);\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, 100.0F);\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.getTextureManager().bindTexture(LogicLayoutGui.achievementTextures);\n\t\tdrawTexturedModalRect(leftSide, topSide, 0, 0, 256, 202);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -100.0F);\n\n\t\tguiTop *= 1 / zoom.zoom;\n\t\tguiLeft *= 1 / zoom.zoom;\n\t\txSize *= 1 / zoom.zoom;\n\t\tySize *= 1 / zoom.zoom;\n\t\tleftSide *= 1 / zoom.zoom;\n\t\ttopSide *= 1 / zoom.zoom;\n\n\t\tint innerLeftSide = leftSide + 16;\n\t\tint innerTopSide = topSide + 17;\n\t\tzLevel = 0.0F;\n\n\t\tGL11.glDepthFunc(GL11.GL_GEQUAL);\n\t\tGL11.glPushMatrix();\n\t\tGL11.glScalef(zoom.zoom, zoom.zoom, 1);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -100.0F);\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\tGL11.glEnable(GL11.GL_COLOR_MATERIAL);\n\n\t\tint moveBackgroundX = (mapX) % 16 + (mapX < 0 ? 16 : 0);\n\t\tint moveBackgroundY = (mapY) % 16 + (mapY < 0 ? 16 : 0);\n\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\tfor (int yVar = 0; yVar * 16 - moveBackgroundY < zoom.bottomRenderBorder; yVar++) {\n\t\t\tfor (int xVar = 0; xVar * 16 - moveBackgroundX < zoom.rightRenderBorder; xVar++) {\n\t\t\t\t/*\n\t\t\t\tTextureAtlasSprite icon = Blocks.STONE.getIcon(0, 0);\n\t\t\t\tmc.getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\t\t\tdrawTexturedModalRect(innerLeftSide + xVar * 16 - moveBackgroundX, innerTopSide + yVar * 16 - moveBackgroundY, icon, 16, 16);\n\t\t\t\t*/\n\t\t\t}\n\t\t}\n\n\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glDepthFunc(GL11.GL_LEQUAL);\n\t\tGL11.glDisable(GL11.GL_TEXTURE_2D);\n\n\t\tGL11.glPushMatrix();\n\t\tGL11.glLoadIdentity();\n\t\t//Draw Content\n\t\t//Lines\n\n\t\t//Draw Background\n\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\n\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glEnable(GL12.GL_RESCALE_NORMAL);\n\t\tGL11.glEnable(GL11.GL_COLOR_MATERIAL);\n\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\n\t\tmc.getTextureManager().bindTexture(LogicLayoutGui.achievementTextures);\n\n\t\t//Draw Content\n\t\t//Items\n\n\t\tGL11.glPopMatrix();\n\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\tguiTop *= zoom.zoom;\n\t\tguiLeft *= zoom.zoom;\n\t\txSize *= zoom.zoom;\n\t\tySize *= zoom.zoom;\n\t\tleftSide *= zoom.zoom;\n\t\ttopSide *= zoom.zoom;\n\n\t\tGL11.glScalef(1 / zoom.zoom, 1 / zoom.zoom, 1);\n\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.getTextureManager().bindTexture(LogicLayoutGui.achievementTextures);\n\t\tdrawTexturedModalRect(leftSide, topSide, 0, 0, 256, 202);\n\n\t\tGL11.glPopMatrix();\n\t\tzLevel = 0.0F;\n\t\tGL11.glDepthFunc(GL11.GL_LEQUAL);\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\t//GL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\tRenderHelper.disableStandardItemLighting();\n\t}\n\n\tprivate void renderLinkedOrderListItems(LinkedLogisticsOrderList list, int xPos, int yPos, int par1, int par2) {\n\t\tint size = list.size();\n\t\tint startLeft = -(size - 1) * (30 / 2) + xPos;\n\t\tyPos += 13;\n\t\tfor (IOrderInfoProvider aList : list) {\n\t\t\tif (aList.isInProgress()) {\n\t\t\t\tGL11.glColor4f(0.1F, 0.9F, 0.1F, 1.0F);\n\t\t\t} else {\n\t\t\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\t\t}\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\tmc.getTextureManager().bindTexture(LogicLayoutGui.achievementTextures);\n\t\t\tdrawTexturedModalRect(startLeft - 5, yPos - 5, 0, 202, 26, 26);\n\t\t\tGL11.glColor4f(0.7F, 0.7F, 0.7F, 1.0F);\n\t\t\t//renderItemAt(aList.getAsDisplayItem(), startLeft, yPos);\n\t\t\tif (aList.isInProgress() && aList.getMachineProgress() != 0) {\n\t\t\t\tGui.drawRect(startLeft - 4, yPos + 20, startLeft + 20, yPos + 24, 0xff000000);\n\t\t\t\tGui.drawRect(startLeft - 3, yPos + 21, startLeft + 19, yPos + 23, 0xffffffff);\n\t\t\t\tGui.drawRect(startLeft - 3, yPos + 21, startLeft - 3 + (22 * aList\n\t\t\t\t\t\t.getMachineProgress() / 100), yPos + 23, 0xffff0000);\n\t\t\t}\n\t\t\tif (startLeft - 10 < par1 && par1 < startLeft + 20 && yPos - 6 < par2 && par2 < yPos + 20) {\n\t\t\t\tif (guiLeft < par1 && par1 < guiLeft + xSize - 16 && guiTop < par2 && par2 < guiTop + ySize - 16) {\n\t\t\t\t\tIOrderInfoProvider order = aList;\n\t\t\t\t\tList<String> tooltipList = new ArrayList<>();\n\t\t\t\t\ttooltipList.add(ChatColor.BLUE + \"Request Type: \" + ChatColor.YELLOW + order.getType().name());\n\t\t\t\t\ttooltipList.add(ChatColor.BLUE + \"Send to Router ID: \" + ChatColor.YELLOW + order.getRouterId());\n\t\t\t\t\ttooltip = new Object[] { (int) (par1 * zoom.zoom - 10), (int) (par2 * zoom.zoom), order\n\t\t\t\t\t\t\t.getAsDisplayItem().makeNormalStack(), true, tooltipList };\n\t\t\t\t}\n\t\t\t}\n\t\t\tstartLeft += 30;\n\t\t}\n\t\tstartLeft = xPos + 20 - list.getSubTreeRootSize() * (40 / 2);\n\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\tfor (int i = 0; i < list.getSubOrders().size(); i++) {\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t\trenderLinkedOrderListItems(list.getSubOrders().get(i), startLeft - 20, yPos + 48, par1, par2);\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void renderLinkedOrderListLines(LinkedLogisticsOrderList list, int xPos, int yPos) {\n\t\tint size = list.size();\n\t\tif (list.isEmpty()) {\n\t\t\tsize = 1;\n\t\t}\n\t\tint startLeft = -(size - 1) * (30 / 2) + xPos;\n\t\tyPos += 13;\n\t\tint left = startLeft;\n\t\tfor (int i = 0; i < list.size(); i++) {\n\t\t\tSimpleGraphics.drawVerticalLine(startLeft + 8, yPos - 13, yPos - 3, Color.GREEN, zoom.line);\n\t\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\t\tSimpleGraphics.drawVerticalLine(startLeft + 8, yPos + 18, yPos + 28, Color.GREEN, zoom.line);\n\t\t\t}\n\t\t\tstartLeft += 30;\n\t\t}\n\t\tif (!list.isEmpty()) {\n\t\t\tSimpleGraphics.drawHorizontalLine(left + 8, startLeft - 22, yPos - 13, Color.GREEN, zoom.line);\n\t\t}\n\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\tif (!list.isEmpty()) {\n\t\t\t\tSimpleGraphics.drawHorizontalLine(left + 8, startLeft - 22, yPos + 28, Color.GREEN, zoom.line);\n\t\t\t\tstartLeft -= 30;\n\t\t\t}\n\t\t\tSimpleGraphics.drawVerticalLine(left + ((startLeft - left) / 2) + 8, yPos + 28, yPos + 38, Color.GREEN, zoom.line);\n\t\t\tstartLeft = xPos + 20 - list.getSubTreeRootSize() * (40 / 2);\n\t\t\tleft = startLeft;\n\t\t\tfor (int i = 0; i < list.getSubOrders().size(); i++) {\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t\tSimpleGraphics.drawVerticalLine(startLeft - 12, yPos + 38, yPos + 48, Color.GREEN, zoom.line);\n\t\t\t\tdrawPointFor(list, xPos, yPos, i, startLeft);\n\t\t\t\trenderLinkedOrderListLines(list.getSubOrders().get(i), startLeft - 20, yPos + 48);\n\t\t\t\tstartLeft += list.getSubOrders().get(i).getTreeRootSize() * (40 / 2);\n\t\t\t}\n\t\t\tif (!list.getSubOrders().isEmpty()) {\n\t\t\t\tleft += list.getSubOrders().get(0).getTreeRootSize() * (40 / 2);\n\t\t\t\tstartLeft -= list.getSubOrders().get(list.getSubOrders().size() - 1).getTreeRootSize() * (40 / 2);\n\t\t\t}\n\t\t\tSimpleGraphics.drawHorizontalLine(left - 12, startLeft - 12, yPos + 38, Color.GREEN, zoom.line);\n\t\t}\n\t}\n\n\tprivate void drawPointFor(LinkedLogisticsOrderList list, int xPos, int yPos, int i, int startLeft) {\n\t\tfloat totalLine = 10 + 1 + 10 + 1 + Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10;\n\t\tfor (Float point : list.getSubOrders().get(i).getProgresses()) {\n\t\t\tint pos = (int) (totalLine * (1.0F - point));\n\t\t\tif (pos < 13) {\n\t\t\t\tint newSize = list.getSubOrders().get(i).size();\n\t\t\t\tint newStartLeft = -(newSize - 1) * (30 / 2) + startLeft - 20;\n\t\t\t\tfor (int j = 0; j < newSize; j++) {\n\t\t\t\t\tdrawProgressPoint(newStartLeft + 8, yPos + 48 + 12 - pos, 0xff00ff00);\n\t\t\t\t\tnewStartLeft += 30;\n\t\t\t\t}\n\t\t\t} else if (pos < 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10;\n\t\t\t\tdrawProgressPoint(startLeft - 20 + 8, yPos + 38 + 12 - pos, 0xff00ff00);\n\t\t\t} else if (pos < Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10 + 1 + 10 + 1;\n\t\t\t\tif (startLeft < xPos + 20) {\n\t\t\t\t\tpos *= -1;\n\t\t\t\t}\n\t\t\t\tdrawProgressPoint(startLeft - 12 - pos, yPos + 38, 0xff00ff00);\n\t\t\t} else if (pos < Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10 + 1 + 10 + 1 + Math.abs(startLeft - (xPos + 20)) + 10 + 1;\n\t\t\t\tdrawProgressPoint(xPos + 8, yPos + 27 - pos, 0xff00ff00);\n\t\t\t} else if (pos < Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1 + 10 + 1 + 10 + 1) {\n\t\t\t\tpos -= 10 + 1 + 10 + 1 + Math.abs(startLeft - (xPos + 20)) + 10 + 1 + 10 + 1;\n\t\t\t\tint newSize = list.size();\n\t\t\t\tint newStartLeft = -(newSize - 1) * (30 / 2) + xPos;\n\t\t\t\tfor (int j = 0; j < newSize; j++) {\n\t\t\t\t\tdrawProgressPoint(newStartLeft + 8, yPos + 16 - pos, 0xff00ff00);\n\t\t\t\t\tnewStartLeft += 30;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void drawProgressPoint(int x, int y, int color) {\n\t\tint line = zoom.line + 1;\n\t\tGui.drawRect(x - line + 1, y - line + 1, x + line, y + line, color);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logic/interfaces/ILogicControllerTile.java",
    "content": "package logisticspipes.logic.interfaces;\n\nimport logisticspipes.logic.LogicController;\n\npublic interface ILogicControllerTile {\n\n\tLogicController getLogicController();\n}\n"
  },
  {
    "path": "common/logisticspipes/logistics/ILogisticsFluidManager.java",
    "content": "package logisticspipes.logistics;\n\nimport java.util.List;\nimport java.util.TreeSet;\nimport javax.annotation.Nullable;\n\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.FluidSinkReply;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\npublic interface ILogisticsFluidManager {\n\n\t@Nullable\n\tPair<Integer, FluidSinkReply> getBestReply(FluidIdentifierStack stack, IRouter sourceRouter, List<Integer> jamList);\n\n\tItemIdentifierStack getFluidContainer(FluidIdentifierStack stack);\n\n\tFluidIdentifierStack getFluidFromContainer(ItemIdentifierStack stack);\n\n\tTreeSet<FluidIdentifierStack> getAvailableFluid(List<ExitRoute> list);\n}\n"
  },
  {
    "path": "common/logisticspipes/logistics/ILogisticsManager.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.logistics;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface ILogisticsManager {\n\n\tIRoutedItem assignDestinationFor(IRoutedItem item, int sourceRouterint, boolean excludeSource);\n\n\tLinkedList<ItemIdentifier> getCraftableItems(List<ExitRoute> list);\n\n\tMap<ItemIdentifier, Integer> getAvailableItems(List<ExitRoute> list);\n\n\tString getBetterRouterName(IRouter r);\n\n\tint getAmountFor(ItemIdentifier item, List<ExitRoute> validDestinations);\n\t//boolean request(LogisticsTransaction transaction, List<IRouter> validDestinations, List<ItemMessage> errors, boolean realrequest, boolean denyCrafterAdding);\n\t//boolean request(LogisticsTransaction transaction, List<IRouter> validDestinations, List<ItemMessage> errors);\n\t//boolean request(LogisticsRequest originalRequest, List<IRouter> validDestinations, List<ItemMessage> errors);\n}\n"
  },
  {
    "path": "common/logisticspipes/logistics/LogisticsFluidManager.java",
    "content": "package logisticspipes.logistics;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Optional;\nimport java.util.TreeSet;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.interfaces.routing.IFluidSink;\nimport logisticspipes.interfaces.routing.IProvideFluids;\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.FluidSinkReply;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class LogisticsFluidManager implements ILogisticsFluidManager {\n\n\t@Override\n\tpublic @Nullable Pair<Integer, FluidSinkReply> getBestReply(FluidIdentifierStack stack, IRouter sourceRouter, List<Integer> jamList) {\n\t\tOptional<Pair<Integer, FluidSinkReply>> bestReply = sourceRouter.getIRoutersByCost().stream()\n\t\t\t\t.filter(it -> it.containsFlag(PipeRoutingConnectionType.canRouteTo) &&\n\t\t\t\t\t\tit.destination.getId() != sourceRouter.getId() &&\n\t\t\t\t\t\t!jamList.contains(it.destination.getSimpleID()) &&\n\t\t\t\t\t\tit.destination.getPipe() instanceof IFluidSink &&\n\t\t\t\t\t\tit.destination.getPipe().isEnabled() &&\n\t\t\t\t\t\t!it.destination.getPipe().isOnSameContainer(sourceRouter.getPipe()))\n\t\t\t\t.sorted()\n\t\t\t\t.map(it -> new Pair<>(it.destination.getSimpleID(),\n\t\t\t\t\t\t((IFluidSink) it.destination.getPipe()).sinkAmount(stack)))\n\t\t\t\t.filter(pair -> pair.getValue2() != null && pair.getValue2().sinkAmount != 0L)\n\t\t\t\t.reduce((left, right) ->\n\t\t\t\t\t\tleft.getValue2().fixedPriority.compareTo(right.getValue2().fixedPriority) < 0 ? right : left);\n\t\tbestReply.ifPresent(pair -> {\n\t\t\tServerRouter serverRouter = SimpleServiceLocator.routerManager.getServerRouter(pair.getValue1());\n\t\t\tif (serverRouter == null) return;\n\t\t\tCoreRoutedPipe pipe = serverRouter.getPipe();\n\t\t\tif (pipe != null) pipe.spawnParticle(Particles.BlueParticle, 10);\n\t\t});\n\t\treturn bestReply.orElse(null);\n\t}\n\n\t@Override\n\tpublic ItemIdentifierStack getFluidContainer(FluidIdentifierStack stack) {\n\t\tItemStack item = new ItemStack(LPItems.fluidContainer, 1);\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\tstack.makeFluidStack().writeToNBT(nbt);\n\t\titem.setTagCompound(nbt);\n\t\treturn ItemIdentifierStack.getFromStack(item);\n\t}\n\n\t@Override\n\tpublic FluidIdentifierStack getFluidFromContainer(ItemIdentifierStack stack) {\n\t\tItemStack itemStack = stack.makeNormalStack();\n\t\tif (itemStack.getItem() instanceof LogisticsFluidContainer && stack.getItem().tag != null) {\n\t\t\treturn FluidIdentifierStack.getFromStack(FluidStack.loadFluidStackFromNBT(stack.getItem().tag));\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic TreeSet<FluidIdentifierStack> getAvailableFluid(List<ExitRoute> validDestinations) {\n\t\tMap<FluidIdentifier, Integer> allAvailableItems = new HashMap<>();\n\t\tfor (ExitRoute r : validDestinations) {\n\t\t\tif (r == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!r.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(r.destination.getPipe() instanceof IProvideFluids)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tIProvideFluids provider = (IProvideFluids) r.destination.getPipe();\n\t\t\tMap<FluidIdentifier, Integer> allItems = provider.getAvailableFluids();\n\n\t\t\tfor (Entry<FluidIdentifier, Integer> liquid : allItems.entrySet()) {\n\t\t\t\tInteger amount = allAvailableItems.get(liquid.getKey());\n\t\t\t\tif (amount == null) {\n\t\t\t\t\tallAvailableItems.put(liquid.getKey(), liquid.getValue());\n\t\t\t\t} else {\n\t\t\t\t\tlong addition = ((long) amount) + liquid.getValue();\n\t\t\t\t\tif (addition > Integer.MAX_VALUE) {\n\t\t\t\t\t\taddition = Integer.MAX_VALUE;\n\t\t\t\t\t}\n\t\t\t\t\tallAvailableItems.put(liquid.getKey(), (int) addition);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn allAvailableItems.entrySet().stream()\n\t\t\t\t.map(item -> new FluidIdentifierStack(item.getKey(), item.getValue()))\n\t\t\t\t.collect(Collectors.toCollection(TreeSet::new));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logistics/LogisticsManager.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.logistics;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.PipeItemsProviderLogistics;\nimport logisticspipes.pipes.PipeItemsRequestLogistics;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.utils.FluidSinkReply;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\n\npublic class LogisticsManager implements ILogisticsManager {\n\n\tprivate Triplet<Integer, SinkReply, List<IFilter>> getBestReply(@Nonnull ItemStack stack, ItemIdentifier item, @Nonnull IRouter sourceRouter, @Nonnull List<ExitRoute> validDestinations, boolean excludeSource, List<Integer> jamList, Triplet<Integer, SinkReply, List<IFilter>> result, boolean allowDefault) {\n\t\tif (result == null) {\n\t\t\tresult = new Triplet<>(null, null, null);\n\t\t}\n\n\t\touter:\n\t\tfor (ExitRoute candidateRouter : validDestinations) {\n\t\t\tif (excludeSource) {\n\t\t\t\tif (candidateRouter.destination.getId().equals(sourceRouter.getId())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (jamList.contains(candidateRouter.destination.getSimpleID())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!candidateRouter.containsFlag(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (IFilter filter : candidateRouter.filters) {\n\t\t\t\tif (filter.blockRouting() || (filter.isBlocked() == filter.isFilteredItem(item))) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSinkReply reply = LogisticsManager.canSink(stack, candidateRouter.destination, sourceRouter, excludeSource, item, result.getValue2(), false, allowDefault);\n\n\t\t\tif (reply == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (result.getValue1() == null) {\n\t\t\t\tresult.setValue1(candidateRouter.destination.getSimpleID());\n\t\t\t\tresult.setValue2(reply);\n\t\t\t\tList<IFilter> list = new LinkedList<>();\n\t\t\t\tresult.setValue3(list);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (reply.fixedPriority.ordinal() > result.getValue2().fixedPriority.ordinal()) {\n\t\t\t\tresult.setValue1(candidateRouter.destination.getSimpleID());\n\t\t\t\tresult.setValue2(reply);\n\t\t\t\tList<IFilter> list = new LinkedList<>();\n\t\t\t\tresult.setValue3(list);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (reply.fixedPriority == result.getValue2().fixedPriority && reply.customPriority > result.getValue2().customPriority) {\n\t\t\t\tresult.setValue1(candidateRouter.destination.getSimpleID());\n\t\t\t\tresult.setValue2(reply);\n\t\t\t\tList<IFilter> list = new LinkedList<>();\n\t\t\t\tresult.setValue3(list);\n\t\t\t}\n\t\t}\n\t\tif (result.getValue1() != null) {\n\t\t\tCoreRoutedPipe pipe = SimpleServiceLocator.routerManager.getServerRouter(result.getValue1()).getPipe();\n\t\t\tpipe.useEnergy(result.getValue2().energyUse);\n\t\t\tpipe.spawnParticle(Particles.BlueParticle, 10);\n\t\t}\n\t\treturn result;\n\t}\n\n\tpublic static SinkReply canSink(@Nonnull ItemStack stack, @Nonnull IRouter destination, IRouter sourceRouter, boolean excludeSource, ItemIdentifier item, SinkReply result, boolean activeRequest, boolean allowDefault) {\n\t\treturn canSink(stack, destination, sourceRouter, excludeSource, item, result, activeRequest, allowDefault, true);\n\t}\n\n\tpublic static SinkReply canSink(@Nonnull ItemStack stack, @Nonnull IRouter destination, IRouter sourceRouter, boolean excludeSource, ItemIdentifier item, SinkReply result, boolean activeRequest, boolean allowDefault, boolean forcePassive) {\n\n\t\tSinkReply reply;\n\t\tLogisticsModule module = destination.getLogisticsModule();\n\t\tCoreRoutedPipe crp = destination.getPipe();\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!(module.receivePassive() || activeRequest)) {\n\t\t\treturn null;\n\t\t}\n\t\tif (crp == null || !crp.isEnabled()) {\n\t\t\treturn null;\n\t\t}\n\t\tif (excludeSource && sourceRouter != null) {\n\t\t\tif (destination.getPipe().isOnSameContainer(sourceRouter.getPipe())) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tif (result == null) {\n\t\t\treply = module.sinksItem(stack, item, -1, 0, allowDefault, true, forcePassive);\n\t\t} else {\n\t\t\treply = module.sinksItem(stack, item, result.fixedPriority.ordinal(), result.customPriority, allowDefault, true, forcePassive);\n\t\t}\n\t\tif (result != null && result.maxNumberOfItems < 0) {\n\t\t\treturn null;\n\t\t}\n\t\treturn reply;\n\t}\n\n\t/**\n\t * Will assign a destination for a IRoutedItem based on the best sink reply\n\t * received from other pipes.\n\t *\n\t * @param item\n\t *            The item that needs to be routed.\n\t * @param sourceRouterID\n\t *            The SimpleID of the pipe that is sending the item. (the\n\t *            routedItem will cache the UUID, and that the SimpleID belongs\n\t *            to the UUID will be checked when appropriate)\n\t * @param excludeSource\n\t *            Boolean, true means that it won't set the source as the\n\t *            destination.\n\t * @return IRoutedItem with a newly assigned destination\n\t */\n\t@Override\n\tpublic IRoutedItem assignDestinationFor(IRoutedItem item, int sourceRouterID, boolean excludeSource) {\n\n\t\t//Assert: only called server side.\n\n\t\t//If we for some reason can't get the router we can't do anything either\n\t\tIRouter sourceRouter = SimpleServiceLocator.routerManager.getServerRouter(sourceRouterID);\n\t\tif (sourceRouter == null) {\n\t\t\treturn item;\n\t\t}\n\n\t\t//Wipe current destination\n\t\titem.clearDestination();\n\n\t\tfinal ItemIdentifierStack itemIdStack = item.getItemIdentifierStack();\n\t\tif (itemIdStack == null) {\n\t\t\treturn item;\n\t\t}\n\t\tBitSet routersIndex = ServerRouter.getRoutersInterestedIn(itemIdStack.getItem());\n\t\tList<ExitRoute> validDestinations = new ArrayList<>(); // get the routing table\n\t\tfor (int i = routersIndex.nextSetBit(0); i >= 0; i = routersIndex.nextSetBit(i + 1)) {\n\t\t\tIRouter r = SimpleServiceLocator.routerManager.getServerRouter(i);\n\t\t\tList<ExitRoute> exits = sourceRouter.getDistanceTo(r);\n\t\t\tif (exits != null) {\n\t\t\t\tvalidDestinations\n\t\t\t\t\t\t.addAll(exits.stream().filter(e -> e.containsFlag(PipeRoutingConnectionType.canRouteTo))\n\t\t\t\t\t\t\t\t.collect(Collectors.toList()));\n\t\t\t}\n\t\t}\n\t\tCollections.sort(validDestinations);\n\t\tfinal ItemStack stack = itemIdStack.makeNormalStack();\n\t\tif (stack.getItem() instanceof LogisticsFluidContainer) {\n\t\t\tPair<Integer, FluidSinkReply> bestReply = SimpleServiceLocator.logisticsFluidManager.getBestReply(SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(itemIdStack), sourceRouter, item.getJamList());\n\t\t\tif (bestReply != null) {\n\t\t\t\titem.setDestination(bestReply.getValue1());\n\t\t\t}\n\t\t} else {\n\t\t\tTriplet<Integer, SinkReply, List<IFilter>> bestReply = getBestReply(stack, itemIdStack.getItem(), sourceRouter, validDestinations, excludeSource, item.getJamList(), null, true);\n\t\t\tif (bestReply.getValue1() != null && bestReply.getValue1() != 0) {\n\t\t\t\titem.setDestination(bestReply.getValue1());\n\t\t\t\tif (bestReply.getValue2().isPassive) {\n\t\t\t\t\tif (bestReply.getValue2().isDefault) {\n\t\t\t\t\t\titem.setTransportMode(TransportMode.Default);\n\t\t\t\t\t} else {\n\t\t\t\t\t\titem.setTransportMode(TransportMode.Passive);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\titem.setTransportMode(TransportMode.Active);\n\t\t\t\t}\n\t\t\t\titem.setAdditionalTargetInformation(bestReply.getValue2().addInfo);\n\t\t\t}\n\t\t}\n\t\treturn item;\n\t}\n\n\t/**\n\t * If there is a better router name available, it will return it. Else, it\n\t * will return the UUID as a string.\n\t *\n\t * @param r\n\t *            The IRouter that you want the name for.\n\t * @return String with value of a better name if available, else just the\n\t *         UUID as a string.\n\t */\n\t@Override\n\tpublic String getBetterRouterName(IRouter r) {\n\n\t\tif (r.getPipe() instanceof PipeItemsCraftingLogistics) {\n\t\t\tPipeItemsCraftingLogistics pipe = (PipeItemsCraftingLogistics) r.getPipe();\n\t\t\tif (pipe.getCraftedItems() != null) {\n\t\t\t\tList<ItemIdentifierStack> items = pipe.getCraftedItems();\n\t\t\t\tif (items.size() == 1) {\n\t\t\t\t\treturn (\"Crafter<\" + items.get(0).getFriendlyName() + \">\");\n\t\t\t\t}\n\t\t\t\treturn (\"Crafter< MULTIPLE ITEMS >\");\n\t\t\t}\n\t\t}\n\n\t\tif (r.getPipe() instanceof PipeItemsProviderLogistics) {\n\t\t\treturn (\"Provider\");\n\t\t}\n\n\t\tif (r.getPipe() instanceof PipeLogisticsChassis) {\n\t\t\treturn \"Chassis\";\n\t\t}\n\t\tif (r.getPipe() instanceof PipeItemsRequestLogistics) {\n\t\t\treturn \"Request\";\n\t\t}\n\n\t\treturn r.getId().toString();\n\n\t}\n\n\t/**\n\t * @param validDestinations\n\t *            a list of ExitRoute of valid destinations.\n\t * @return HashMap with ItemIdentifier and Integer item count of available\n\t *         items.\n\t */\n\t@Override\n\tpublic HashMap<ItemIdentifier, Integer> getAvailableItems(List<ExitRoute> validDestinations) {\n\t\t//TODO: Replace this entire function with a fetch from the pre-built arrays (path incoming later)\n\t\tList<Map<ItemIdentifier, Integer>> items = new ArrayList<>(ServerRouter.getBiggestSimpleID());\n\t\tfor (int i = 0; i < ServerRouter.getBiggestSimpleID(); i++) {\n\t\t\titems.add(new HashMap<>());\n\t\t}\n\t\tBitSet used = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\touter:\n\t\tfor (ExitRoute r : validDestinations) {\n\t\t\tif (r == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!r.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(r.destination.getPipe() instanceof IProvideItems)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (IFilter filter : r.filters) {\n\t\t\t\tif (filter.blockProvider()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tIProvideItems provider = (IProvideItems) r.destination.getPipe();\n\t\t\tprovider.getAllItems(items.get(r.destination.getSimpleID()), r.filters);\n\t\t\tused.set(r.destination.getSimpleID(), true);\n\t\t}\n\t\t//TODO: Fix this doubly nested list\n\t\tHashMap<ItemIdentifier, Integer> allAvailableItems = new HashMap<>();\n\t\tfor (Map<ItemIdentifier, Integer> allItems : items) {\n\t\t\tfor (Entry<ItemIdentifier, Integer> item : allItems.entrySet()) {\n\t\t\t\tallAvailableItems.merge(item.getKey(), item.getValue(), Integer::sum);\n\t\t\t}\n\t\t}\n\t\treturn allAvailableItems;\n\t}\n\n\t/**\n\t * @param validDestinations\n\t *            a List of ExitRoute of valid destinations.\n\t * @return LinkedList with ItemIdentifier\n\t */\n\t@Override\n\tpublic LinkedList<ItemIdentifier> getCraftableItems(List<ExitRoute> validDestinations) {\n\t\tLinkedList<ItemIdentifier> craftableItems = new LinkedList<>();\n\t\tBitSet used = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\touter:\n\t\tfor (ExitRoute r : validDestinations) {\n\t\t\tif (r == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!r.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (used.get(r.destination.getSimpleID())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(r.destination.getPipe() instanceof ICraftItems)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (IFilter filter : r.filters) {\n\t\t\t\tif (filter.blockCrafting()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tICraftItems crafter = (ICraftItems) r.destination.getPipe();\n\t\t\tList<ItemIdentifierStack> craftedItems = crafter.getCraftedItems();\n\t\t\tif (craftedItems != null) {\n\t\t\t\touter2:\n\t\t\t\tfor (ItemIdentifierStack craftedItem : craftedItems) {\n\t\t\t\t\tif (craftedItem != null && !craftableItems.contains(craftedItem.getItem())) {\n\t\t\t\t\t\tfor (IFilter filter : r.filters) {\n\t\t\t\t\t\t\tif (filter.isBlocked() == filter.isFilteredItem(craftedItem.getItem())) {\n\t\t\t\t\t\t\t\tcontinue outer2;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcraftableItems.add(craftedItem.getItem());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tused.set(r.destination.getSimpleID(), true);\n\t\t}\n\t\treturn craftableItems;\n\t}\n\n\t@Override\n\tpublic int getAmountFor(ItemIdentifier itemType, List<ExitRoute> validDestinations) {\n\t\t// TODO: Replace this entire function with a fetch from the pre-built arrays (path incoming later)\n\t\tList<Map<ItemIdentifier, Integer>> items = new ArrayList<>(ServerRouter.getBiggestSimpleID());\n\t\tfor (int i = 0; i < ServerRouter.getBiggestSimpleID(); i++) {\n\t\t\titems.add(new HashMap<>());\n\t\t}\n\t\tBitSet used = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\touter:\n\t\tfor (ExitRoute r : validDestinations) {\n\t\t\tif (r == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!r.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(r.destination.getPipe() instanceof IProvideItems)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (IFilter filter : r.filters) {\n\t\t\t\tif (filter.blockProvider()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tIProvideItems provider = (IProvideItems) r.destination.getPipe();\n\t\t\tprovider.getAllItems(items.get(r.destination.getSimpleID()), r.filters);\n\t\t\tused.set(r.destination.getSimpleID(), true);\n\t\t}\n\t\t// TODO: Fix this doubly nested list\n\t\tint amount = 0;\n\t\tfor (Map<ItemIdentifier, Integer> allItems : items) {\n\t\t\tfor (Entry<ItemIdentifier, Integer> item : allItems.entrySet()) {\n\t\t\t\tif (item.getKey().equals(itemType)) {\n\t\t\t\t\tamount += item.getValue();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn amount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/ChassisTransportLayer.java",
    "content": "package logisticspipes.logisticspipes;\n\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class ChassisTransportLayer extends TransportLayer {\n\n\tprivate final PipeLogisticsChassis _chassisPipe;\n\n\tpublic ChassisTransportLayer(PipeLogisticsChassis chassisPipe) {\n\t\t_chassisPipe = chassisPipe;\n\t}\n\n\t@Override\n\tpublic EnumFacing itemArrived(IRoutedItem item, EnumFacing denied) {\n\t\tif (item.getItemIdentifierStack() != null) {\n\t\t\t_chassisPipe.receivedItem(item.getItemIdentifierStack().getStackSize());\n\t\t}\n\t\treturn _chassisPipe.getPointedOrientation();\n\t}\n\n\t@Override\n\tpublic boolean stillWantItem(IRoutedItem item) {\n\t\tLogisticsModule module = _chassisPipe.getLogisticsModule();\n\t\tif (module == null) {\n\t\t\t_chassisPipe.notifyOfItemArival(item.getInfo());\n\t\t\treturn false;\n\t\t}\n\t\tif (!_chassisPipe.isEnabled()) {\n\t\t\t_chassisPipe.notifyOfItemArival(item.getInfo());\n\t\t\treturn false;\n\t\t}\n\t\tfinal ItemIdentifierStack itemIdStack = item.getItemIdentifierStack();\n\t\tSinkReply reply = module.sinksItem(itemIdStack.makeNormalStack(), itemIdStack.getItem(), -1, 0, true, false, false);\n\t\tif (reply == null || reply.maxNumberOfItems < 0) {\n\t\t\t_chassisPipe.notifyOfItemArival(item.getInfo());\n\t\t\treturn false;\n\t\t}\n\n\t\tif (reply.maxNumberOfItems > 0 && itemIdStack.getStackSize() > reply.maxNumberOfItems) {\n\t\t\tEnumFacing o = _chassisPipe.getPointedOrientation();\n\t\t\tif (o == null) {\n\t\t\t\to = EnumFacing.UP;\n\t\t\t}\n\n\t\t\titem.split(reply.maxNumberOfItems, o);\n\t\t}\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/IRoutedItem.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.logisticspipes;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.order.IDistanceTracker;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\n/**\n * This interface describes the actions that must be available on an item that\n * is considered routed\n */\npublic interface IRoutedItem {\n\n\tenum TransportMode {\n\t\tUnknown,\n\t\tDefault,\n\t\tPassive,\n\t\tActive\n\t}\n\n\tint getDestination();\n\n\tUUID getDestinationUUID();\n\n\tvoid setDestination(int destination);\n\n\tvoid clearDestination();\n\n\tvoid setTransportMode(TransportMode transportMode);\n\n\tTransportMode getTransportMode();\n\n\tvoid setAdditionalTargetInformation(IAdditionalTargetInformation info);\n\n\tIAdditionalTargetInformation getAdditionalTargetInformation();\n\n\tvoid setDoNotBuffer(boolean doNotBuffer);\n\n\tboolean getDoNotBuffer();\n\n\tint getBufferCounter();\n\n\tvoid setBufferCounter(int counter);\n\n\tvoid setArrived(boolean flag);\n\n\tboolean getArrived();\n\n\tvoid addToJamList(IRouter router);\n\n\tList<Integer> getJamList();\n\n\tvoid checkIDFromUUID();\n\n\tItemIdentifierStack getItemIdentifierStack();\n\n\tvoid readFromNBT(NBTTagCompound data);\n\n\tvoid writeToNBT(NBTTagCompound tagEntityItem);\n\n\tvoid setDistanceTracker(IDistanceTracker tracker);\n\n\tIDistanceTracker getDistanceTracker();\n\n\tItemRoutingInformation getInfo();\n\n\tvoid split(int itemsToTake, EnumFacing orientation);\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/ITrackStatistics.java",
    "content": "package logisticspipes.logisticspipes;\n\n/**\n * This interface tracks statistics\n *\n * @author Krapht\n */\npublic interface ITrackStatistics {\n\n\tvoid receivedItem(int count);\n\n\tvoid relayedItem(int count);\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/ItemModuleInformationManager.java",
    "content": "package logisticspipes.logisticspipes;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Random;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagString;\n\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.proxy.MainProxy;\n\npublic class ItemModuleInformationManager {\n\n\tpublic static void saveInformation(@Nonnull ItemStack stack, LogisticsModule module) {\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\tmodule.writeToNBT(nbt);\n\t\tif (nbt.equals(new NBTTagCompound())) {\n\t\t\treturn;\n\t\t}\n\t\tif (MainProxy.isClient()) {\n\t\t\tNBTTagList list = new NBTTagList();\n\t\t\tString info1 = \"Please reopen the window\";\n\t\t\tString info2 = \"to see the information.\";\n\t\t\tlist.appendTag(new NBTTagString(info1));\n\t\t\tlist.appendTag(new NBTTagString(info2));\n\t\t\tif (!stack.hasTagCompound()) {\n\t\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t\t}\n\t\t\tNBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\t\ttag.setTag(\"informationList\", list);\n\t\t\ttag.setDouble(\"Random-Stack-Prevent\", new Random().nextDouble());\n\t\t\treturn;\n\t\t}\n\t\tif (!stack.hasTagCompound()) {\n\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t}\n\t\tNBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\ttag.setTag(\"moduleInformation\", nbt);\n\t\tif (module instanceof IClientInformationProvider) {\n\t\t\tList<String> information = ((IClientInformationProvider) module).getClientInformation();\n\t\t\tif (information.size() > 0) {\n\t\t\t\tNBTTagList list = new NBTTagList();\n\t\t\t\tfor (String info : information) {\n\t\t\t\t\tlist.appendTag(new NBTTagString(info));\n\t\t\t\t}\n\t\t\t\ttag.setTag(\"informationList\", list);\n\t\t\t}\n\t\t}\n\t\ttag.setDouble(\"Random-Stack-Prevent\", new Random().nextDouble());\n\t}\n\n\tpublic static void readInformation(@Nonnull ItemStack stack, LogisticsModule module) {\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (stack.hasTagCompound()) {\n\t\t\tNBTTagCompound nbt = Objects.requireNonNull(stack.getTagCompound());\n\t\t\tif (nbt.hasKey(\"moduleInformation\")) {\n\t\t\t\tNBTTagCompound moduleInformation = nbt.getCompoundTag(\"moduleInformation\");\n\t\t\t\tmodule.readFromNBT(moduleInformation);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/PipeTransportLayer.java",
    "content": "package logisticspipes.logisticspipes;\n\nimport java.util.LinkedList;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.routing.IRouter;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\n/**\n * This class is responsible for handling incoming items for standard pipes\n *\n * @author Krapht\n */\npublic class PipeTransportLayer extends TransportLayer {\n\n\tprivate final CoreRoutedPipe routedPipe;\n\tprivate final ITrackStatistics _trackStatistics;\n\tprivate final @Nonnull IRouter _router;\n\n\tpublic PipeTransportLayer(CoreRoutedPipe routedPipe, ITrackStatistics trackStatistics, @Nonnull IRouter router) {\n\t\tthis.routedPipe = routedPipe;\n\t\t_trackStatistics = trackStatistics;\n\t\t_router = router;\n\t}\n\n\t@Override\n\tpublic EnumFacing itemArrived(IRoutedItem item, EnumFacing denied) {\n\t\tif (item.getItemIdentifierStack() != null) {\n\t\t\t_trackStatistics.receivedItem(item.getItemIdentifierStack().getStackSize());\n\t\t}\n\n\t\t// 1st priority, deliver to adjacent inventories\n\t\tLinkedList<EnumFacing> possibleEnumFacing = new LinkedList<>();\n\t\tfor (NeighborTileEntity<TileEntity> adjacent : routedPipe.getAvailableAdjacent().inventories()) {\n\t\t\tif (_router.isRoutedExit(adjacent.getDirection())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (denied != null && denied.equals(adjacent.getDirection())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tCoreRoutedPipe pipe = _router.getPipe();\n\t\t\tif (pipe != null) {\n\t\t\t\tif (pipe.isLockedExit(adjacent.getDirection())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tpossibleEnumFacing.add(adjacent.getDirection());\n\t\t}\n\t\tif (possibleEnumFacing.size() != 0) {\n\t\t\treturn possibleEnumFacing.get(routedPipe.getWorld().rand.nextInt(possibleEnumFacing.size()));\n\t\t}\n\n\t\t// 2nd priority, deliver to non-routed exit\n\t\tnew WorldCoordinatesWrapper(routedPipe.container).connectedTileEntities().stream()\n\t\t\t\t.filter(neighbor -> {\n\t\t\t\t\tif (_router.isRoutedExit(neighbor.getDirection())) return false;\n\t\t\t\t\tfinal CoreRoutedPipe routerPipe = _router.getPipe();\n\t\t\t\t\treturn routerPipe == null || !routerPipe.isLockedExit(neighbor.getDirection());\n\t\t\t\t})\n\t\t\t\t.forEach(neighbor -> possibleEnumFacing.add(neighbor.getDirection()));\n\n\t\tif (possibleEnumFacing.size() == 0) {\n\t\t\t// last resort, drop item\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn possibleEnumFacing.get(routedPipe.getWorld().rand.nextInt(possibleEnumFacing.size()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean stillWantItem(IRoutedItem item) {\n\t\t// pipes are dumb and always want the item\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/RouteLayer.java",
    "content": "/**\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.logisticspipes;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\n\n/**\n * @author Krapht This class is responsible for resolving where incoming items\n * should go.\n */\npublic class RouteLayer {\n\n\tprotected final @Nonnull IRouter _router;\n\tprivate final TransportLayer _transport;\n\tprivate final CoreRoutedPipe _pipe;\n\n\tpublic RouteLayer(@Nonnull IRouter router, TransportLayer transportLayer, CoreRoutedPipe pipe) {\n\t\t_router = router;\n\t\t_transport = transportLayer;\n\t\t_pipe = pipe;\n\t}\n\n\tpublic EnumFacing getOrientationForItem(IRoutedItem item, EnumFacing blocked) {\n\n\t\titem.checkIDFromUUID();\n\t\t//If a item has no destination, find one\n\t\tif (item.getDestination() < 0) {\n\t\t\titem = SimpleServiceLocator.logisticsManager.assignDestinationFor(item, _router.getSimpleID(), false);\n\t\t\t_pipe.debug.log(\"No Destination, assigned new destination: (\" + item.getInfo());\n\t\t}\n\n\t\t//If the destination is unknown / unroutable or it already arrived at its destination and somehow looped back\n\t\tif (item.getDestination() >= 0 && (!_router.hasRoute(item.getDestination(), item.getTransportMode() == TransportMode.Active, item.getItemIdentifierStack().getItem()) || item.getArrived())) {\n\t\t\titem = SimpleServiceLocator.logisticsManager.assignDestinationFor(item, _router.getSimpleID(), false);\n\t\t\t_pipe.debug.log(\"Unreachable Destination, assigned new destination: (\" + item.getInfo());\n\t\t}\n\n\t\titem.checkIDFromUUID();\n\t\t//If we still have no destination or client side unroutable, drop it\n\t\tif (item.getDestination() < 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Are we the destination? Deliver it\n\t\tif (item.getDestinationUUID().equals(_router.getId())) {\n\n\t\t\t_transport.handleItem(item);\n\n\t\t\tif (item.getDistanceTracker() != null) {\n\t\t\t\titem.getDistanceTracker().setCurrentDistanceToTarget(0);\n\t\t\t\titem.getDistanceTracker().setDestinationReached();\n\t\t\t}\n\n\t\t\tif (item.getTransportMode() != TransportMode.Active && !_transport.stillWantItem(item)) {\n\t\t\t\treturn getOrientationForItem(SimpleServiceLocator.logisticsManager.assignDestinationFor(item, _router.getSimpleID(), true), null);\n\t\t\t}\n\n\t\t\titem.setDoNotBuffer(true);\n\t\t\titem.setArrived(true);\n\t\t\treturn _transport.itemArrived(item, blocked);\n\t\t}\n\n\t\t//Do we now know the destination?\n\t\tif (!_router.hasRoute(item.getDestination(), item.getTransportMode() == TransportMode.Active, item.getItemIdentifierStack().getItem())) {\n\t\t\treturn null;\n\t\t}\n\n\t\t//Which direction should we send it\n\t\tExitRoute exit = _router.getExitFor(item.getDestination(), item.getTransportMode() == TransportMode.Active, item.getItemIdentifierStack().getItem());\n\t\tif (exit == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (item.getDistanceTracker() != null) {\n\t\t\titem.getDistanceTracker().setCurrentDistanceToTarget(exit.blockDistance);\n\t\t}\n\n\t\treturn exit.exitOrientation;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/logisticspipes/TransportLayer.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.logisticspipes;\n\nimport net.minecraft.util.EnumFacing;\n\n/**\n * This class is responsible for handling items arriving at its destination\n *\n * @author Krapht\n */\npublic abstract class TransportLayer {\n\n\tpublic abstract boolean stillWantItem(IRoutedItem item);\n\n\tpublic abstract EnumFacing itemArrived(IRoutedItem item, EnumFacing denied);\n\n\tpublic void handleItem(IRoutedItem item) {}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/jei/AdvancedGuiHandler.java",
    "content": "package logisticspipes.modplugins.jei;\n\nimport java.awt.Rectangle;\nimport java.util.List;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport mezz.jei.api.gui.IAdvancedGuiHandler;\n\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class AdvancedGuiHandler implements IAdvancedGuiHandler<LogisticsBaseGuiScreen> {\n\n\t@Override\n\tpublic @Nonnull Class<LogisticsBaseGuiScreen> getGuiContainerClass() {\n\t\treturn LogisticsBaseGuiScreen.class;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic List<Rectangle> getGuiExtraAreas(@Nonnull LogisticsBaseGuiScreen guiContainer) {\n\t\treturn guiContainer.getGuiExtraAreas();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/jei/GhostIngredientHandler.java",
    "content": "package logisticspipes.modplugins.jei;\n\nimport java.awt.Rectangle;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport mezz.jei.api.gui.IGhostIngredientHandler;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.SetGhostItemPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.gui.DummySlot;\nimport logisticspipes.utils.gui.FluidSlot;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class GhostIngredientHandler implements IGhostIngredientHandler<LogisticsBaseGuiScreen> {\n\n\t@Nonnull\n\t@Override\n\tpublic <I> List<Target<I>> getTargets(@Nonnull LogisticsBaseGuiScreen gui, @Nonnull I ingredient, boolean doStart) {\n\t\tif (ingredient instanceof ItemStack) {\n\t\t\tStream<Target<I>> slotStream = gui.inventorySlots.inventorySlots.stream().filter(it -> it instanceof DummySlot).map(it -> (DummySlot) it)\n\t\t\t\t\t.map(it -> new Target<I>() {\n\n\t\t\t\t\t\t@Nonnull\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic Rectangle getArea() {\n\t\t\t\t\t\t\treturn new Rectangle(gui.getGuiLeft() + it.xPos, gui.getGuiTop() + it.yPos, 17, 17);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void accept(@Nonnull I ingredient) {\n\t\t\t\t\t\t\tit.putStack((ItemStack) ingredient);\n\t\t\t\t\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\t\t\t\t\tPacketHandler.getPacket(SetGhostItemPacket.class).setInteger(it.slotNumber).setStack((ItemStack) ingredient));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\tif (FluidIdentifier.get((ItemStack) ingredient) != null) {\n\t\t\t\tStream<Target<I>> fluidStream = gui.inventorySlots.inventorySlots.stream().filter(it -> it instanceof FluidSlot).map(it -> (FluidSlot) it)\n\t\t\t\t\t\t.map(it -> new Target<I>() {\n\n\t\t\t\t\t\t\t@Nonnull\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic Rectangle getArea() {\n\t\t\t\t\t\t\t\treturn new Rectangle(gui.getGuiLeft() + it.xPos, gui.getGuiTop() + it.yPos, 17, 17);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic void accept(@Nonnull I ingredient) {\n\t\t\t\t\t\t\t\tFluidIdentifier ident = FluidIdentifier.get((ItemStack) ingredient);\n\t\t\t\t\t\t\t\tif (ident != null) {\n\t\t\t\t\t\t\t\t\tItemStack stack = ident.getItemIdentifier().unsafeMakeNormalStack(1);\n\t\t\t\t\t\t\t\t\tit.putStack(stack);\n\t\t\t\t\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SetGhostItemPacket.class).setInteger(it.slotNumber).setStack(stack));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\tslotStream = Stream.concat(slotStream, fluidStream);\n\t\t\t}\n\t\t\treturn slotStream.collect(Collectors.toList());\n\t\t} else if (ingredient instanceof FluidStack) {\n\t\t\treturn gui.inventorySlots.inventorySlots.stream().filter(it -> it instanceof FluidSlot).map(it -> (FluidSlot) it).map(it -> new Target<I>() {\n\n\t\t\t\t@Nonnull\n\t\t\t\t@Override\n\t\t\t\tpublic Rectangle getArea() {\n\t\t\t\t\treturn new Rectangle(gui.getGuiLeft() + it.xPos, gui.getGuiTop() + it.yPos, 17, 17);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void accept(@Nonnull I ingredient) {\n\t\t\t\t\tFluidIdentifier ident = FluidIdentifier.get((FluidStack) ingredient);\n\t\t\t\t\tif (ident != null) {\n\t\t\t\t\t\tItemStack stack = ident.getItemIdentifier().unsafeMakeNormalStack(1);\n\t\t\t\t\t\tit.putStack(stack);\n\t\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SetGhostItemPacket.class).setInteger(it.slotNumber).setStack(stack));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}).collect(Collectors.toList());\n\t\t}\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic void onComplete() {}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/jei/JEIPluginLoader.java",
    "content": "package logisticspipes.modplugins.jei;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport mezz.jei.api.IJeiRuntime;\nimport mezz.jei.api.IModPlugin;\nimport mezz.jei.api.IModRegistry;\nimport mezz.jei.api.JEIPlugin;\nimport mezz.jei.api.recipe.IFocus;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferRegistry;\n\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport network.rs485.logisticspipes.compat.JEIAdvancedGuiHandler;\nimport network.rs485.logisticspipes.compat.JEIGhostIngredientHandler;\nimport network.rs485.logisticspipes.gui.BaseGuiContainer;\n\n@JEIPlugin\npublic class JEIPluginLoader implements IModPlugin {\n\n\tprivate static IJeiRuntime jeiRuntime;\n\n\t@Override\n\tpublic void register(IModRegistry registry) {\n\t\tIRecipeTransferRegistry recipeTransferRegistry = registry.getRecipeTransferRegistry();\n\t\trecipeTransferRegistry.addUniversalRecipeTransferHandler(new RecipeTransferHandler(registry.getJeiHelpers().recipeTransferHandlerHelper()));\n\t\tregistry.addGhostIngredientHandler(LogisticsBaseGuiScreen.class, new GhostIngredientHandler());\n\t\tregistry.addGhostIngredientHandler(BaseGuiContainer.class, new JEIGhostIngredientHandler());\n\t\tregistry.addAdvancedGuiHandlers(new AdvancedGuiHandler(), new JEIAdvancedGuiHandler());\n\t}\n\n\t@Override\n\tpublic void onRuntimeAvailable(@Nonnull IJeiRuntime jeiRuntime) {\n\t\tJEIPluginLoader.jeiRuntime = jeiRuntime;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic static void showRecipe(ItemStack stack) {\n\t\tjeiRuntime.getRecipesGui().show(jeiRuntime.getRecipeRegistry().createFocus(IFocus.Mode.OUTPUT, stack));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/jei/RecipeTransferHandler.java",
    "content": "package logisticspipes.modplugins.jei;\n\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.NonNullList;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport mezz.jei.api.gui.IGuiIngredient;\nimport mezz.jei.api.gui.IGuiItemStackGroup;\nimport mezz.jei.api.gui.IRecipeLayout;\nimport mezz.jei.api.recipe.VanillaRecipeCategoryUid;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferError;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferHandler;\nimport mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper;\n\nimport logisticspipes.gui.GuiLogisticsCraftingTable;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.gui.popup.GuiRecipeImport;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.NEISetCraftingRecipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\npublic class RecipeTransferHandler implements IRecipeTransferHandler<DummyContainer> {\n\n\tprivate final IRecipeTransferHandlerHelper recipeTransferHandlerHelper;\n\n\tpublic RecipeTransferHandler(IRecipeTransferHandlerHelper recipeTransferHandlerHelper) {\n\t\tthis.recipeTransferHandlerHelper = recipeTransferHandlerHelper;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Class<DummyContainer> getContainerClass() {\n\t\treturn DummyContainer.class;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic IRecipeTransferError transferRecipe(@Nonnull DummyContainer container, @Nonnull IRecipeLayout recipeLayout, @Nonnull EntityPlayer player, boolean maxTransfer, boolean doTransfer) {\n\t\tLogisticsBaseGuiScreen gui = container.guiHolderForJEI;\n\n\t\tif (gui instanceof GuiLogisticsCraftingTable || gui instanceof GuiRequestTable) {\n\n\t\t\tTileEntity tile;\n\t\t\tif (gui instanceof GuiLogisticsCraftingTable) {\n\t\t\t\ttile = ((GuiLogisticsCraftingTable) gui)._crafter;\n\t\t\t} else {\n\t\t\t\ttile = ((GuiRequestTable) gui)._table.container;\n\t\t\t}\n\n\t\t\tif (tile == null) {\n\t\t\t\treturn recipeTransferHandlerHelper.createInternalError();\n\t\t\t}\n\n\t\t\tif (!recipeLayout.getRecipeCategory().getUid().equals(VanillaRecipeCategoryUid.CRAFTING)) {\n\t\t\t\treturn recipeTransferHandlerHelper.createInternalError();\n\t\t\t}\n\n\t\t\tNEISetCraftingRecipe packet = PacketHandler.getPacket(NEISetCraftingRecipe.class);\n\t\t\tNonNullList<ItemStack> stackList = packet.getStackList();\n\t\t\tItemStack[][] stacks = new ItemStack[9][];\n\t\t\tboolean hasCandidates = false;\n\n\t\t\tIGuiItemStackGroup guiItemStackGroup = recipeLayout.getItemStacks();\n\t\t\tMap<Integer, ? extends IGuiIngredient<ItemStack>> guiIngredients = guiItemStackGroup.getGuiIngredients();\n\n\t\t\tif (doTransfer) {\n\t\t\t\tfor (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> ps : guiIngredients.entrySet()) {\n\t\t\t\t\tif (!ps.getValue().isInput()) continue;\n\n\t\t\t\t\tint slot = ps.getKey() - 1;\n\n\t\t\t\t\tif (slot < 9) {\n\t\t\t\t\t\tfinal ItemStack displayedIngredient = ps.getValue().getDisplayedIngredient();\n\t\t\t\t\t\tstackList.set(slot, displayedIngredient == null ? ItemStack.EMPTY : displayedIngredient);\n\t\t\t\t\t\tNonNullList<ItemStack> itemCandidateList = NonNullList.create();\n\n\t\t\t\t\t\t// add all non-null non-empty ingredients to the itemCandidateList\n\t\t\t\t\t\tps.getValue().getAllIngredients().stream()\n\t\t\t\t\t\t\t\t.filter(itemStack -> Objects.nonNull(itemStack) && !itemStack.isEmpty())\n\t\t\t\t\t\t\t\t.forEach(itemCandidateList::add);\n\n\t\t\t\t\t\tif (!itemCandidateList.isEmpty()) {\n\t\t\t\t\t\t\tIterator<ItemStack> iter = itemCandidateList.iterator();\n\t\t\t\t\t\t\twhile (iter.hasNext()) {\n\t\t\t\t\t\t\t\tItemStack wildCardCheckStack = iter.next();\n\t\t\t\t\t\t\t\tif (wildCardCheckStack.getItemDamage() == OreDictionary.WILDCARD_VALUE) {\n\t\t\t\t\t\t\t\t\titer.remove();\n\t\t\t\t\t\t\t\t\tfinal CreativeTabs creativeTab = wildCardCheckStack.getItem().getCreativeTab();\n\t\t\t\t\t\t\t\t\tif (creativeTab != null) {\n\t\t\t\t\t\t\t\t\t\tNonNullList<ItemStack> secondList = NonNullList.create();\n\t\t\t\t\t\t\t\t\t\twildCardCheckStack.getItem().getSubItems(creativeTab, secondList);\n\t\t\t\t\t\t\t\t\t\titemCandidateList.addAll(secondList);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\titer = itemCandidateList.iterator();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tstacks[slot] = itemCandidateList.toArray(new ItemStack[0]);\n\t\t\t\t\t\t\tif (stacks[slot].length > 1) {\n\t\t\t\t\t\t\t\thasCandidates = true;\n\t\t\t\t\t\t\t} else if (stacks[slot].length == 1) {\n\t\t\t\t\t\t\t\tstackList.set(slot, stacks[slot][0]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (hasCandidates) {\n\t\t\t\t\tgui.setSubGui(new GuiRecipeImport(tile, stacks));\n\t\t\t\t} else {\n\t\t\t\t\tMainProxy.sendPacketToServer(packet.setTilePos(tile));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\treturn recipeTransferHandlerHelper.createInternalError();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/mcmp/LPMCMPAddon.java",
    "content": "package logisticspipes.modplugins.mcmp;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.common.MinecraftForge;\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.capabilities.ICapabilityProvider;\nimport net.minecraftforge.event.AttachCapabilitiesEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\n\nimport mcmultipart.api.addon.IMCMPAddon;\nimport mcmultipart.api.addon.MCMPAddon;\nimport mcmultipart.api.multipart.IMultipartRegistry;\nimport mcmultipart.api.multipart.IMultipartTile;\nimport mcmultipart.api.ref.MCMPCapabilities;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.LPConstants;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\n@MCMPAddon\npublic class LPMCMPAddon implements IMCMPAddon {\n\n\tpublic static final LPPipeMultipart lpPipeMultipart = new LPPipeMultipart();\n\n\t@Override\n\tpublic void registerParts(IMultipartRegistry registry) {\n\t\tMinecraftForge.EVENT_BUS.register(this);\n\t\tregistry.registerPartWrapper(LPBlocks.pipe, lpPipeMultipart);\n\t}\n\n\t@SubscribeEvent\n\tpublic void attachCapability(AttachCapabilitiesEvent<TileEntity> e) {\n\t\tfinal TileEntity tile = e.getObject();\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\te.addCapability(new ResourceLocation(LPConstants.LP_MOD_ID, \"mcmpaddon.cap\"), new ICapabilityProvider() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\t\t\t\treturn capability == MCMPCapabilities.MULTIPART_TILE;\n\t\t\t\t}\n\n\t\t\t\t@Nullable\n\t\t\t\t@Override\n\t\t\t\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\t\t\t\tif (capability == MCMPCapabilities.MULTIPART_TILE) {\n\t\t\t\t\t\t//noinspection unchecked\n\t\t\t\t\t\treturn (T) IMultipartTile.wrap(tile);\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/mcmp/LPMultipartTile.java",
    "content": "package logisticspipes.modplugins.mcmp;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.network.NetworkManager;\nimport net.minecraft.network.play.server.SPacketUpdateTileEntity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ITickable;\nimport net.minecraft.util.Mirror;\nimport net.minecraft.util.Rotation;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.capabilities.Capability;\n\nimport mcmultipart.api.container.IPartInfo;\nimport mcmultipart.api.multipart.IMultipartTile;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\npublic class LPMultipartTile implements IMultipartTile {\n\n\tprivate final LogisticsTileGenericPipe tile;\n\n\tpublic LPMultipartTile(LogisticsTileGenericPipe tile) {\n\t\tthis.tile = tile;\n\t}\n\n\t@Override\n\tpublic TileEntity getTileEntity() {\n\t\treturn tile;\n\t}\n\n\tpublic boolean isTickable() {\n\t\treturn false;\n\t}\n\n\tpublic ITickable getTickable() {\n\t\treturn null;\n\t}\n\n\tpublic void setPartInfo(IPartInfo info) {}\n\n\tpublic World getPartWorld() {\n\t\treturn tile.getWorld();\n\t}\n\n\tpublic void setPartWorld(World world) {}\n\n\tpublic boolean hasPartWorld() {\n\t\treturn tile.hasWorld();\n\t}\n\n\tpublic BlockPos getPartPos() {\n\t\treturn tile.getPos();\n\t}\n\n\tpublic void setPartPos(BlockPos pos) {}\n\n\tpublic void readPartFromNBT(NBTTagCompound compound) {}\n\n\tpublic NBTTagCompound writePartToNBT(NBTTagCompound compound) {\n\t\treturn compound;\n\t}\n\n\tpublic void markPartDirty() {}\n\n\tpublic double getMaxPartRenderDistanceSquared() {\n\t\treturn 0;\n\t}\n\n\tpublic boolean isPartInvalid() {\n\t\treturn false;\n\t}\n\n\tpublic void invalidatePart() {}\n\n\tpublic void validatePart() {}\n\n\tpublic void updatePartContainerInfo() {}\n\n\tpublic void rotatePart(Rotation rotation) {}\n\n\tpublic void mirrorPart(Mirror mirror) {}\n\n\tpublic SPacketUpdateTileEntity getPartUpdatePacket() {\n\t\treturn null;\n\t}\n\n\tpublic void onPartDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { }\n\n\tpublic NBTTagCompound getPartUpdateTag() {\n\t\treturn new NBTTagCompound();\n\t}\n\n\tpublic void handlePartUpdateTag(NBTTagCompound tag) {}\n\n\tpublic void onPartChunkUnload() {}\n\n\tpublic boolean shouldRefreshPart(World world, BlockPos pos, IBlockState oldState, IBlockState newState) {\n\t\treturn false;\n\t}\n\n\tpublic boolean shouldRenderPartInPass(int pass) {\n\t\treturn false;\n\t}\n\n\tpublic AxisAlignedBB getPartRenderBoundingBox() {\n\t\treturn Block.FULL_BLOCK_AABB;\n\t}\n\n\tpublic boolean canPartRenderBreaking() {\n\t\treturn false;\n\t}\n\n\tpublic void onPartLoad() {}\n\n\tpublic boolean hasFastPartRenderer() {\n\t\treturn false;\n\t}\n\n\tpublic boolean hasPartCapability(Capability<?> capability, EnumFacing facing) {\n\t\treturn false;\n\t}\n\n\tpublic <T> T getPartCapability(Capability<T> capability, EnumFacing facing) {\n\t\treturn null;\n\t}\n\n\tpublic boolean onlyOpsCanSetPartNbt() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/mcmp/LPPipeMultipart.java",
    "content": "package logisticspipes.modplugins.mcmp;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Random;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.state.BlockFaceShape;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.particle.ParticleManager;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.EntityLiving;\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.BlockRenderLayer;\nimport net.minecraft.util.EnumBlockRenderType;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.Explosion;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.IPlantable;\n\nimport mcmultipart.api.container.IPartInfo;\nimport mcmultipart.api.multipart.IMultipart;\nimport mcmultipart.api.multipart.IMultipartTile;\nimport mcmultipart.api.multipart.MultipartOcclusionHelper;\nimport mcmultipart.api.slot.EnumCenterSlot;\nimport mcmultipart.api.slot.IPartSlot;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\npublic class LPPipeMultipart implements IMultipart {\n\n\t@Override\n\tpublic IPartSlot getSlotForPlacement(World world, BlockPos blockPos, IBlockState iBlockState, EnumFacing enumFacing, float v, float v1, float v2, EntityLivingBase entityLivingBase) {\n\t\treturn EnumCenterSlot.CENTER;\n\t}\n\n\t@Override\n\tpublic IPartSlot getSlotFromWorld(IBlockAccess iBlockAccess, BlockPos blockPos, IBlockState iBlockState) {\n\t\treturn EnumCenterSlot.CENTER;\n\t}\n\n\t@Override\n\tpublic Block getBlock() {\n\t\treturn LPBlocks.pipe;\n\t}\n\n\t@Override\n\tpublic List<AxisAlignedBB> getOcclusionBoxes(IPartInfo part) {\n\t\treturn Collections.singletonList(LogisticsBlockGenericPipe.PIPE_CENTER_BB);\n\t}\n\n\t@Override\n\tpublic IBlockState getExtendedState(IBlockAccess world, BlockPos pos, IPartInfo part, IBlockState state) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic RayTraceResult collisionRayTrace(IPartInfo part, Vec3d start, Vec3d end) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic IMultipartTile loadMultipartTile(World world, NBTTagCompound tag) {\n\t\treturn new LPMultipartTile(null);\n\t}\n\n\t@Override\n\tpublic IMultipartTile convertToMultipartTile(TileEntity tileEntity) {\n\t\treturn new LPMultipartTile((LogisticsTileGenericPipe) tileEntity);\n\t}\n\n\t@Override\n\tpublic boolean shouldWrapWorld() {\n\t\treturn false;\n\t}\n\n\tpublic boolean testIntersection(IPartInfo self, IPartInfo otherPart) {\n\t\treturn MultipartOcclusionHelper.testBoxIntersection(this.getOcclusionBoxes(self), otherPart.getPart().getOcclusionBoxes(otherPart));\n\t}\n\n\tpublic IBlockState getActualState(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn part.getState();\n\t}\n\n\tpublic boolean canRenderInLayer(IBlockAccess world, BlockPos pos, IPartInfo part, IBlockState state, BlockRenderLayer layer) {\n\t\treturn false;\n\t}\n\n\tpublic void onPartPlacedBy(IPartInfo part, EntityLivingBase placer, @Nonnull ItemStack stack) {}\n\n\tpublic boolean isSideSolid(IBlockAccess world, BlockPos pos, IPartInfo part, EnumFacing side) {\n\t\treturn false;\n\t}\n\n\tpublic void randomDisplayTick(IPartInfo part, Random rand) {}\n\n\tpublic boolean addDestroyEffects(IPartInfo part, ParticleManager manager) {\n\t\treturn false;\n\t}\n\n\tpublic boolean addHitEffects(IPartInfo part, RayTraceResult hit, ParticleManager manager) {\n\t\treturn false;\n\t}\n\n\tpublic EnumBlockRenderType getRenderType(IPartInfo part) {\n\t\treturn part.getState().getRenderType();\n\t}\n\n\tpublic static final AxisAlignedBB EMPTY_BLOCK_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);\n\n\tpublic AxisAlignedBB getBoundingBox(IPartInfo part) {\n\t\treturn EMPTY_BLOCK_AABB;\n\t}\n\n\tpublic boolean canConnectRedstone(IBlockAccess world, BlockPos pos, IPartInfo part, EnumFacing side) {\n\t\treturn false;\n\t}\n\n\tpublic int getWeakPower(IBlockAccess world, BlockPos pos, IPartInfo part, EnumFacing side) {\n\t\treturn 0;\n\t}\n\n\tpublic int getStrongPower(IBlockAccess world, BlockPos pos, IPartInfo part, EnumFacing side) {\n\t\treturn 0;\n\t}\n\n\tpublic boolean canCreatureSpawn(IBlockAccess world, BlockPos pos, IPartInfo part, EntityLiving.SpawnPlacementType type) {\n\t\treturn false;\n\t}\n\n\tpublic boolean canSustainLeaves(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic boolean canSustainPlant(IBlockAccess world, BlockPos pos, IPartInfo part, EnumFacing direction, IPlantable plantable) {\n\t\treturn false;\n\t}\n\n\tpublic void fillWithRain(IPartInfo part) {}\n\n\tpublic int getComparatorInputOverride(IPartInfo part) {\n\t\treturn 0;\n\t}\n\n\tpublic List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IPartInfo part, int fortune) {\n\t\treturn Collections.emptyList();\n\t}\n\n\tpublic float getExplosionResistance(IPartInfo part, Entity exploder, Explosion explosion) {\n\t\treturn 0;\n\t}\n\n\tpublic float getEnchantPowerBonus(IPartInfo part) {\n\t\treturn 0;\n\t}\n\n\tpublic int getLightOpacity(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn 0;\n\t}\n\n\tpublic int getLightOpacity(IBlockState state) {\n\t\treturn 0;\n\t}\n\n\tpublic int getLightValue(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn 0;\n\t}\n\n\tpublic int getLightValue(IBlockState state) {\n\t\treturn 0;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getPickPart(IPartInfo part, RayTraceResult hit, EntityPlayer player) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\tpublic float getPlayerRelativePartHardness(IPartInfo part, RayTraceResult hit, EntityPlayer player) {\n\t\treturn 0;\n\t}\n\n\tpublic Boolean isAABBInsideMaterial(IPartInfo part, AxisAlignedBB boundingBox, Material material) {\n\t\treturn null;\n\t}\n\n\tpublic boolean isBeaconBase(IBlockAccess world, BlockPos pos, IPartInfo part, BlockPos beacon) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isBurning(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic Boolean isEntityInsideMaterial(IBlockAccess world, BlockPos pos, IPartInfo part, Entity entity, double yToTest, Material material, boolean testingHead) {\n\t\treturn null;\n\t}\n\n\tpublic boolean isFertile(IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isFireSource(IPartInfo part, EnumFacing side) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isFlammable(IBlockAccess world, BlockPos pos, IPartInfo part, EnumFacing face) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isFoliage(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isLadder(IBlockAccess world, BlockPos pos, IPartInfo part, EntityLivingBase entity) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isLeaves(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isPassable(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic boolean isWood(IBlockAccess world, BlockPos pos, IPartInfo part) {\n\t\treturn false;\n\t}\n\n\tpublic void onPartClicked(IPartInfo part, EntityPlayer player, RayTraceResult hit) {}\n\n\tpublic void neighborChanged(IPartInfo part, Block neighborBlock, BlockPos neighborPos) {\n\t}\n\n\tpublic void onNeighborChange(IPartInfo part, BlockPos neighbor) {\n\t}\n\n\tpublic boolean onPartActivated(IPartInfo part, EntityPlayer player, EnumHand hand, RayTraceResult hit) {\n\t\treturn false;\n\t}\n\n\tpublic void onPlantGrow(IPartInfo part, BlockPos source) {}\n\n\tpublic boolean canPlayerDestroy(IPartInfo part, EntityPlayer player) {\n\t\treturn true;\n\t}\n\n\tpublic void onPartHarvested(IPartInfo part, EntityPlayer player) {}\n\n\tpublic void randomTick(IPartInfo part, Random random) {}\n\n\tpublic BlockFaceShape getPartFaceShape(IPartInfo part, EnumFacing face) {\n\t\treturn BlockFaceShape.SOLID;\n\t}\n\n\tpublic boolean canPlacePartAt(World world, BlockPos pos) {\n\t\treturn true;\n\t}\n\n\tpublic void breakPart(IPartInfo part) {\n\t\tthis.getBlock().breakBlock(part.getPartWorld(), part.getPartPos(), part.getState());\n\t}\n\n\tpublic void updateTick(IPartInfo part, Random rand) {}\n\n\tpublic void addCollisionBoxToList(IPartInfo part, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entity, boolean unknown) {}\n\n\tpublic AxisAlignedBB getCollisionBoundingBox(World world, BlockPos pos, IBlockState state) {\n\t\treturn null;\n\t}\n\n\tpublic AxisAlignedBB getSelectedBoundingBox(IPartInfo part) {\n\t\treturn EMPTY_BLOCK_AABB;\n\t}\n\n\tpublic void onEntityCollidedWithPart(IPartInfo part, Entity entity) {}\n\n\tpublic void dropPartAsItem(IPartInfo part, int fortune) {}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/nei/DebugHelper.java",
    "content": "package logisticspipes.modplugins.nei;\n\nimport java.awt.BorderLayout;\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.swing.JFrame;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTree;\nimport javax.swing.tree.DefaultMutableTreeNode;\n\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTBase;\nimport net.minecraft.nbt.NBTTagByte;\nimport net.minecraft.nbt.NBTTagByteArray;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagDouble;\nimport net.minecraft.nbt.NBTTagFloat;\nimport net.minecraft.nbt.NBTTagInt;\nimport net.minecraft.nbt.NBTTagIntArray;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagLong;\nimport net.minecraft.nbt.NBTTagShort;\nimport net.minecraft.nbt.NBTTagString;\n\nimport codechicken.nei.guihook.IContainerTooltipHandler;\nimport org.lwjgl.input.Keyboard;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class DebugHelper implements IContainerTooltipHandler {\n\n\tprivate static long lastTime = 0;\n\n\t@Override\n\tpublic void handleTooltip(GuiScreen gui, int mouseX, int mouseY, List<String> currentTip) {}\n\n\t@Override\n\tpublic void handleItemDisplayName(GuiScreen gui, @Nonnull ItemStack itemstack, List<String> currentTip) {\n\t\tif (Configs.TOOLTIP_INFO && !itemstack.isEmpty()) {\n\t\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && Keyboard.isKeyDown(Keyboard.KEY_H)) {\n\t\t\t\tif (DebugHelper.lastTime + 1000 < System.currentTimeMillis()) {\n\t\t\t\t\tDebugHelper.lastTime = System.currentTimeMillis();\n\t\t\t\t\tnew Thread(() -> {\n\t\t\t\t\t\twhile (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_H)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tThread.sleep(50);\n\t\t\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\t\t\te.printStackTrace();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tDefaultMutableTreeNode node = new DefaultMutableTreeNode(ItemIdentifier.get(itemstack).getFriendlyName());\n\t\t\t\t\t\tnode.add(new DefaultMutableTreeNode(\"ItemId: \" + Item.getIdFromItem(itemstack.getItem())));\n\t\t\t\t\t\tnode.add(new DefaultMutableTreeNode(\"ItemDamage: \" + itemstack.getItemDamage()));\n\t\t\t\t\t\tif (itemstack.hasTagCompound()) {\n\t\t\t\t\t\t\tDefaultMutableTreeNode tag = new DefaultMutableTreeNode(\"Tag:\");\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\taddNBTToTree(itemstack.getTagCompound(), tag);\n\t\t\t\t\t\t\t} catch (Exception e) {\n\t\t\t\t\t\t\t\ttag.add(new DefaultMutableTreeNode(e));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnode.add(tag);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tJTree tree = new JTree(node);\n\t\t\t\t\t\tJScrollPane treeView = new JScrollPane(tree);\n\t\t\t\t\t\tJFrame frame = new JFrame(\"Item Info\");\n\t\t\t\t\t\tframe.getContentPane().add(treeView, BorderLayout.CENTER);\n\t\t\t\t\t\tframe.setLocationRelativeTo(null);\n\t\t\t\t\t\tframe.pack();\n\t\t\t\t\t\tframe.setVisible(true);\n\t\t\t\t\t}).start();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void addNBTToTree(NBTBase nbt, DefaultMutableTreeNode node) throws SecurityException, IllegalArgumentException {\n\t\tif (nbt == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (nbt instanceof NBTTagByte) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagByte\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: \" + ((NBTTagByte) nbt).getByte()));\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagByteArray) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagByteArray\");\n\t\t\tDefaultMutableTreeNode content = new DefaultMutableTreeNode(\"Data\");\n\t\t\tint i = 0;\n\t\t\tfor (byte byt : ((NBTTagByteArray) nbt).getByteArray()) {\n\t\t\t\tcontent.add(new DefaultMutableTreeNode(\"[\" + i + \"]: \" + byt));\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tnode.add(content);\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagDouble) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagDouble\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: \" + ((NBTTagDouble) nbt).getDouble()));\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagFloat) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagFloat\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: \" + ((NBTTagFloat) nbt).getFloat()));\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagInt) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagInt\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: \" + ((NBTTagInt) nbt).getInt()));\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagIntArray) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagIntArray\");\n\t\t\tDefaultMutableTreeNode content = new DefaultMutableTreeNode(\"Data\");\n\t\t\tint i = 0;\n\t\t\tfor (int byt : ((NBTTagIntArray) nbt).getIntArray()) {\n\t\t\t\tcontent.add(new DefaultMutableTreeNode(\"[\" + i + \"]: \" + byt));\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ttype.add(content);\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagList) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagList\");\n\t\t\tDefaultMutableTreeNode content = new DefaultMutableTreeNode(\"Data\");\n\n\t\t\tint i = 0;\n\n\t\t\tfor (NBTBase object : (NBTTagList) nbt) {\n\t\t\t\tDefaultMutableTreeNode nbtNode = new DefaultMutableTreeNode(\"[\" + i + \"]\");\n\t\t\t\taddNBTToTree(object, nbtNode);\n\t\t\t\tcontent.add(nbtNode);\n\t\t\t\ti++;\n\t\t\t}\n\t\t\ttype.add(content);\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagCompound) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagCompound\");\n\t\t\tDefaultMutableTreeNode content = new DefaultMutableTreeNode(\"Data\");\n\n\t\t\tfor (String key : ((NBTTagCompound) nbt).getKeySet()) {\n\t\t\t\tNBTBase value = ((NBTTagCompound) nbt).getTag(key);\n\t\t\t\tDefaultMutableTreeNode nbtNode = new DefaultMutableTreeNode(key);\n\t\t\t\taddNBTToTree(value, nbtNode);\n\t\t\t\tcontent.add(nbtNode);\n\t\t\t}\n\t\t\ttype.add(content);\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagLong) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagLong\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: \" + ((NBTTagLong) nbt).getLong()));\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagShort) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagShort\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: \" + ((NBTTagShort) nbt).getShort()));\n\t\t\tnode.add(type);\n\t\t} else if (nbt instanceof NBTTagString) {\n\t\t\tDefaultMutableTreeNode type = new DefaultMutableTreeNode(\"NBTTagString\");\n\t\t\ttype.add(new DefaultMutableTreeNode(\"Data: '\" + ((NBTTagString) nbt).getString() + \"'\"));\n\t\t\tnode.add(type);\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(\"Unsupported NBTBase of type:\" + nbt.getClass().getName());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/nei/DrawHandler.java",
    "content": "package logisticspipes.modplugins.nei;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.inventory.Slot;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport codechicken.nei.guihook.IContainerDrawHandler;\n\nimport logisticspipes.utils.QuickSortChestMarkerStorage;\nimport logisticspipes.utils.gui.GuiGraphics;\n\n@SideOnly(Side.CLIENT)\npublic class DrawHandler implements IContainerDrawHandler {\n\n\t@Override\n\tpublic void renderObjects(GuiContainer gui, int mouseX, int mouseY) {}\n\n\t@Override\n\tpublic void postRenderObjects(GuiContainer gui, int mouseX, int mouseY) {}\n\n\t//TODO: Find way to replicate this with the new api\n/*\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void renderSlotUnderlay(GuiContainer gui, Slot slotActive) {\n\t\tif (slotActive.slotNumber == 0) {\n\t\t\tif (QuickSortChestMarkerStorage.getInstance().isActivated()) {\n\t\t\t\t((List<Slot>) gui.inventorySlots.inventorySlots).stream()\n\t\t\t\t\t\t.filter(slot -> QuickSortChestMarkerStorage.getInstance().getMarker().contains(slot.slotNumber))\n\t\t\t\t\t\t.forEach(slot -> {\n\t\t\t\t\t\t\tMinecraft.getMinecraft().renderEngine.bindTexture(GuiGraphics.WIDGETS_TEXTURE);\n\t\t\t\t\t\t\tgui.drawTexturedModalRect(slot.xPos - 3, slot.yPos - 3, 1, 23, 22, 22);\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n*/\n\t@Override\n\tpublic void renderSlotOverlay(GuiContainer gui, Slot slotActive) {\n\t\t//TODO: Same as above\n\t\tif (slotActive.slotNumber == 0) {\n\t\t\tif (QuickSortChestMarkerStorage.getInstance().isActivated()) {\n\t\t\t\tgui.inventorySlots.inventorySlots.stream()\n\t\t\t\t\t\t.filter(slot -> QuickSortChestMarkerStorage.getInstance().getMarker().contains(slot.slotNumber))\n\t\t\t\t\t\t.forEach(slot -> {\n\t\t\t\t\t\t\tMinecraft.getMinecraft().renderEngine.bindTexture(GuiGraphics.WIDGETS_TEXTURE);\n\t\t\t\t\t\t\tgui.drawTexturedModalRect(slot.xPos - 3, slot.yPos - 3, 1, 23, 22, 22);\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/nei/LoadingHelper.java",
    "content": "package logisticspipes.modplugins.nei;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport codechicken.nei.handler.NEIClientEventHandler;\n\nimport logisticspipes.config.Configs;\n\npublic class LoadingHelper {\n\n\tpublic static void LoadNeiNBTDebugHelper() {\n\t\tif (Configs.TOOLTIP_INFO && !NEILogisticsPipesConfig.added) {\n\t\t\tNEIClientEventHandler.addTooltipHandler(new DebugHelper());\n\t\t\tNEILogisticsPipesConfig.added = true;\n\t\t\tif (FMLClientHandler.instance().getClient() != null && FMLClientHandler.instance().getClient().player != null) {\n\t\t\t\tFMLClientHandler.instance().getClient().player.sendChatMessage(\"Enabled.\");\n\t\t\t}\n\t\t} else if (NEILogisticsPipesConfig.added) {\n\t\t\tif (FMLClientHandler.instance().getClient() != null && FMLClientHandler.instance().getClient().player != null) {\n\t\t\t\tFMLClientHandler.instance().getClient().player.sendChatMessage(\"Already enabled.\");\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/nei/LogisticsCraftingOverlayHandler.java",
    "content": "/*\npackage logisticspipes.nei;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport logisticspipes.gui.GuiLogisticsCraftingTable;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.gui.popup.GuiRecipeImport;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.NEISetCraftingRecipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\n\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\npublic class LogisticsCraftingOverlayHandler implements IOverlayHandler {\n\n\t@Override\n\tpublic void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift) {\n\n\t\tTileEntity tile;\n\t\tLogisticsBaseGuiScreen gui;\n\t\tif (firstGui instanceof GuiLogisticsCraftingTable) {\n\t\t\ttile = ((GuiLogisticsCraftingTable) firstGui)._crafter;\n\t\t\tgui = (GuiLogisticsCraftingTable) firstGui;\n\t\t} else if (firstGui instanceof GuiRequestTable) {\n\t\t\ttile = ((GuiRequestTable) firstGui)._table.container;\n\t\t\tgui = (GuiRequestTable) firstGui;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tItemStack[] stack = new ItemStack[9];\n\t\tItemStack[][] stacks = new ItemStack[9][];\n\t\tboolean hasCanidates = false;\n\t\tNEISetCraftingRecipe packet = PacketHandler.getPacket(NEISetCraftingRecipe.class);\n\t\tfor (PositionedStack ps : recipe.getIngredientStacks(recipeIndex)) {\n\t\t\tint x = (ps.relx - 25) / 18;\n\t\t\tint y = (ps.rely - 6) / 18;\n\t\t\tint slot = x + y * 3;\n\t\t\tif (x < 0 || x > 2 || y < 0 || y > 2 || slot < 0 || slot > 8) {\n\t\t\t\tFMLClientHandler.instance().getClient().thePlayer.sendChatMessage(\"Internal Error. This button is broken.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (slot < 9) {\n\t\t\t\tstack[slot] = ps.items[0];\n\t\t\t\tList<ItemStack> list = new ArrayList<>(Arrays.asList(ps.items));\n\t\t\t\tIterator<ItemStack> iter = list.iterator();\n\t\t\t\twhile (iter.hasNext()) {\n\t\t\t\t\tItemStack wildCardCheckStack = iter.next();\n\t\t\t\t\tif (wildCardCheckStack.getItemDamage() == OreDictionary.WILDCARD_VALUE) {\n\t\t\t\t\t\titer.remove();\n\t\t\t\t\t\twildCardCheckStack.getItem().getSubItems(wildCardCheckStack.getItem(), wildCardCheckStack.getItem().getCreativeTab(), list);\n\t\t\t\t\t\titer = list.iterator();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstacks[slot] = list.toArray(new ItemStack[0]);\n\t\t\t\tif (stacks[slot].length > 1) {\n\t\t\t\t\thasCanidates = true;\n\t\t\t\t} else if(stacks[slot].length == 1) {\n\t\t\t\t\tstack[slot] = stacks[slot][0];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (hasCanidates) {\n\t\t\tgui.setSubGui(new GuiRecipeImport(tile, stacks));\n\t\t} else {\n\t\t\tMainProxy.sendPacketToServer(packet.setContent(stack).setTilePos(tile));\n\t\t}\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/modplugins/nei/NEILogisticsPipesConfig.java",
    "content": "package logisticspipes.modplugins.nei;\n\nimport net.minecraftforge.fml.common.Mod;\n\nimport codechicken.nei.api.IConfigureNEI;\nimport codechicken.nei.api.NEIPlugin;\nimport codechicken.nei.handler.NEIClientEventHandler;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.config.Configs;\n\n@NEIPlugin\npublic class NEILogisticsPipesConfig implements IConfigureNEI {\n\n\tpublic static boolean added = false;\n\n\t@Override\n\tpublic void loadConfig() {\n\n\t\tif (Configs.TOOLTIP_INFO && !NEILogisticsPipesConfig.added) {\n\t\t\tNEIClientEventHandler.addTooltipHandler(new DebugHelper());\n\t\t\tNEILogisticsPipesConfig.added = true;\n\t\t}\n\n\t\tNEIClientEventHandler.addDrawHandler(new DrawHandler());\n\n\t\t/*\n\t\tMultiItemRange main = new MultiItemRange();\n\t\tmain.add(LogisticsPipes.LogisticsNetworkMonitior);\n\t\tmain.add(LogisticsPipes.LogisticsRemoteOrderer);\n\t\tmain.add(LogisticsPipes.LogisticsCraftingSignCreator);\n\n\t\tMultiItemRange pipesChassi = new MultiItemRange();\n\t\tpipesChassi.add(LogisticsPipes.LogisticsChassisPipeMk1);\n\t\tpipesChassi.add(LogisticsPipes.LogisticsChassisPipeMk2);\n\t\tpipesChassi.add(LogisticsPipes.LogisticsChassisPipeMk3);\n\t\tpipesChassi.add(LogisticsPipes.LogisticsChassisPipeMk4);\n\t\tpipesChassi.add(LogisticsPipes.LogisticsChassisPipeMk5);\n\n\t\tMultiItemRange modules = new MultiItemRange();\n\t\tmodules.add(LogisticsPipes.ModuleItem, 0, 1000);\n\n\t\taddSetRange(\"LogisticsPipes\", main);\n\t\taddSetRange(\"LogisticsPipes.Modules\", modules);\n\t\t//addSetRange(\"LogisticsPipes.Pipes\", pipes);\n\t\taddSetRange(\"LogisticsPipes.Pipes.Chassi\", pipesChassi);\n\t\t */\n\n\t\t//TODO: Uncomment\n/*\t\tAPI.registerRecipeHandler(new NEISolderingStationRecipeManager());\n\t\tAPI.registerUsageHandler(new NEISolderingStationRecipeManager());\n\t\tAPI.registerGuiOverlay(GuiSolderingStation.class, \"solderingstation\");\n\t\tAPI.registerGuiOverlayHandler(GuiLogisticsCraftingTable.class, new LogisticsCraftingOverlayHandler(), \"crafting\");\n\t\tAPI.registerGuiOverlayHandler(GuiRequestTable.class, new LogisticsCraftingOverlayHandler(), \"crafting\");\n\t\t*/\n\t}\n\n\t@Override\n\tpublic String getName() {\n\t\treturn LogisticsPipes.class.getAnnotation(Mod.class).name();\n\t}\n\n\t@Override\n\tpublic String getVersion() {\n\t\treturn LogisticsPipes.class.getAnnotation(Mod.class).version();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modplugins/nei/NEISolderingStationRecipeManager.java",
    "content": "/*package logisticspipes.nei;\n\nimport java.awt.Rectangle;\nimport java.util.stream.Collectors;\n\nimport logisticspipes.gui.GuiSolderingStation;\nimport logisticspipes.recipes.SolderingStationRecipes;\nimport logisticspipes.recipes.SolderingStationRecipes.SolderingStationRecipe;\n\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.init.Items;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.item.ItemStack;\n\nimport codechicken.nei.api.stack.PositionedStack;\nimport codechicken.nei.recipe.ShapedRecipeHandler;\nimport codechicken.nei.util.NEIServerUtils;\n\npublic class NEISolderingStationRecipeManager extends ShapedRecipeHandler {\n\n\tprivate ShapedRecipeHandler.CachedShapedRecipe getShape(SolderingStationRecipe recipe) {\n\t\tShapedRecipeHandler.CachedShapedRecipe shape = new ShapedRecipeHandler.CachedShapedRecipe(0, 0, null, recipe.result);\n\t\tfor (int x = 0; x < 3; x++) {\n\t\t\tfor (int y = 0; y < 3; y++) {\n\t\t\t\tif (recipe.source[y * 3 + x] == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tPositionedStack stack = new PositionedStack(recipe.source[y * 3 + x], 39 + x * 18, 6 + y * 18);\n\t\t\t\tstack.setMaxSize(1);\n\t\t\t\tshape.ingredients.add(stack);\n\t\t\t}\n\t\t}\n\t\tPositionedStack stack = new PositionedStack(new ItemStack(Items.IRON_INGOT, 1), 102, 6);\n\t\tstack.setMaxSize(1);\n\t\tshape.ingredients.add(stack);\n\t\tshape.result.relx = 136;\n\t\tshape.result.rely = 36;\n\t\treturn shape;\n\t}\n\n\t@Override\n\tpublic void loadCraftingRecipes(ItemStack result) {\n\t\tarecipes.addAll(SolderingStationRecipes.getRecipes().stream()\n\t\t\t\t.filter(recipe -> NEIServerUtils.areStacksSameTypeCrafting(recipe.result, result)).map(this::getShape)\n\t\t\t\t.collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic void loadTransferRects() {\n\t\ttransferRects.add(new RecipeTransferRect(new Rectangle(101, 27, 24, 26), \"solderingstation\"));\n\t}\n\n\t@Override\n\tpublic Class<? extends GuiContainer> getGuiClass() {\n\t\treturn GuiSolderingStation.class;\n\t}\n\n\t@Override\n\tpublic String getRecipeName() {\n\t\treturn \"Soldering Station\";\n\t}\n\n\t@Override\n\tpublic String getGuiTexture() {\n\t\treturn \"logisticspipes:textures/gui/soldering_station_nei.png\";\n\t}\n\n\t@Override\n\tpublic boolean hasOverlay(GuiContainer gui, Container container, int recipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void loadUsageRecipes(ItemStack ingredient) {\n\t\tfor (SolderingStationRecipe recipe : SolderingStationRecipes.getRecipes()) {\n\t\t\tfor (ItemStack source : recipe.source) {\n\t\t\t\tif (NEIServerUtils.areStacksSameTypeCrafting(source, ingredient)) {\n\t\t\t\t\tarecipes.add(getShape(recipe));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void loadCraftingRecipes(String outputId, Object... results) {\n\t\tif (outputId.equals(\"solderingstation\") && getClass() == NEISolderingStationRecipeManager.class) {\n\t\t\tarecipes.addAll(SolderingStationRecipes.getRecipes().stream()\n\t\t\t\t\t.map(this::getShape)\n\t\t\t\t\t.collect(Collectors.toList()));\n\t\t} else {\n\t\t\tsuper.loadCraftingRecipes(outputId, results);\n\t\t}\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/modules/ChassisModule.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport com.google.common.collect.ImmutableList;\n\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.pipe.ChassisGuiProvider;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.pipes.upgrades.ModuleUpgradeManager;\nimport logisticspipes.proxy.computers.objects.CCSinkResponder;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.PipeServiceProviderUtilKt;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.SlottedModule;\nimport network.rs485.logisticspipes.property.SlottedModuleListProperty;\nimport network.rs485.logisticspipes.property.UpgradeManagerListProperty;\n\npublic class ChassisModule extends LogisticsModule implements Gui {\n\n\tprivate final PipeLogisticsChassis parentChassis;\n\tprivate final SlottedModuleListProperty modules;\n\tprivate final UpgradeManagerListProperty slotUpgradeManagers;\n\n\tpublic ChassisModule(int moduleCount, PipeLogisticsChassis parentChassis) {\n\t\tthis.parentChassis = parentChassis;\n\t\tmodules = new SlottedModuleListProperty(moduleCount, \"modules\");\n\t\tslotUpgradeManagers = new UpgradeManagerListProperty(moduleCount, parentChassis, \"chassisUpgradeManagers\");\n\t\tregisterPosition(ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\tthrow new RuntimeException(\"Cannot get LP name for \" + this);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn ImmutableList.<Property<?>>builder()\n\t\t\t.add(modules)\n\t\t\t.add(slotUpgradeManagers)\n\t\t\t.build();\n\t}\n\n\tpublic void installModule(int slot, LogisticsModule module) {\n\t\tmodules.set(slot, module);\n\t}\n\n\tpublic void removeModule(int slot) {\n\t\tmodules.clear(slot);\n\t}\n\n\t@Nullable\n\tpublic LogisticsModule getModule(int slot) {\n\t\treturn modules.get(slot).getModule();\n\t}\n\n\tpublic boolean hasModule(int slot) {\n\t\treturn !modules.get(slot).isEmpty();\n\t}\n\n\tpublic Stream<LogisticsModule> getModules() {\n\t\treturn modules.stream()\n\t\t\t\t.filter(slottedModule -> !slottedModule.isEmpty())\n\t\t\t\t.map(SlottedModule::getModule);\n\t}\n\n\tpublic Stream<SlottedModule> slottedModules() {\n\t\treturn modules.stream();\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tSinkReply bestresult = null;\n\t\tfor (SlottedModule slottedModule : modules) {\n\t\t\tfinal LogisticsModule module = slottedModule.getModule();\n\t\t\tif (module != null) {\n\t\t\t\tif (!forcePassive || module.receivePassive()) {\n\t\t\t\t\tSinkReply result = module\n\t\t\t\t\t\t\t.sinksItem(stack, item, bestPriority, bestCustomPriority, allowDefault, includeInTransit,\n\t\t\t\t\t\t\t\t\tforcePassive);\n\t\t\t\t\tif (result != null && result.maxNumberOfItems >= 0) {\n\t\t\t\t\t\tbestresult = result;\n\t\t\t\t\t\tbestPriority = result.fixedPriority.ordinal();\n\t\t\t\t\t\tbestCustomPriority = result.customPriority;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (bestresult == null) {\n\t\t\treturn null;\n\t\t}\n\t\t//Always deny items when we can't put the item anywhere\n\t\tfinal ISlotUpgradeManager upgradeManager = parentChassis.getUpgradeManager(ModulePositionType.SLOT,\n\t\t\t\t((ChassiTargetInformation) bestresult.addInfo).getModuleSlot());\n\t\tIInventoryUtil invUtil = PipeServiceProviderUtilKt.availableSneakyInventories(parentChassis, upgradeManager)\n\t\t\t\t.stream().findFirst().orElse(null);\n\t\tif (invUtil == null) {\n\t\t\treturn null;\n\t\t}\n\t\tint roomForItem;\n\t\tif (includeInTransit) {\n\t\t\tint onRoute = parentChassis.countOnRoute(item);\n\t\t\tfinal ItemStack copy = stack.copy();\n\t\t\tcopy.setCount(onRoute + item.getMaxStackSize());\n\t\t\troomForItem = invUtil.roomForItem(copy);\n\t\t\troomForItem -= onRoute;\n\t\t} else {\n\t\t\troomForItem = invUtil.roomForItem(stack);\n\t\t}\n\t\tif (roomForItem < 1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (bestresult.maxNumberOfItems == 0) {\n\t\t\treturn new SinkReply(bestresult, roomForItem);\n\t\t}\n\t\treturn new SinkReply(bestresult, Math.min(bestresult.maxNumberOfItems, roomForItem));\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\t// FIXME: remove after 1.12\n\t\tmodules.stream()\n\t\t\t\t.filter(slottedModule -> !slottedModule.isEmpty() && tag.hasKey(\"slot\" + slottedModule.getSlot()))\n\t\t\t\t.forEach(slottedModule -> Objects.requireNonNull(slottedModule.getModule())\n\t\t\t\t\t\t.readFromNBT(tag.getCompoundTag(\"slot\" + slottedModule.getSlot())));\n\n\t\t// FIXME: remove after 1.12.2 update, backwards compatibility\n\t\tfor (int i = 0; i < parentChassis.getChassisSize(); i++) {\n\t\t\tslotUpgradeManagers.get(i).readFromNBT(tag, Integer.toString(i));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void tick() {\n\t\tfor (SlottedModule slottedModule : modules) {\n\t\t\tfinal LogisticsModule module = slottedModule.getModule();\n\t\t\tif (module == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmodule.tick();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void finishInit() {\n\t\tsuper.finishInit();\n\t\tgetModules().forEach(LogisticsModule::finishInit);\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\tfor (SlottedModule slottedModule : modules) {\n\t\t\tfinal LogisticsModule module = slottedModule.getModule();\n\t\t\tif (module != null && module.receivePassive()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic List<CCSinkResponder> queueCCSinkEvent(ItemIdentifierStack item) {\n\t\tList<CCSinkResponder> list = new ArrayList<>();\n\t\tfor (SlottedModule slottedModule : modules) {\n\t\t\tfinal LogisticsModule module = slottedModule.getModule();\n\t\t\tif (module != null) {\n\t\t\t\tlist.addAll(module.queueCCSinkEvent(item));\n\t\t\t}\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ChassisGuiProvider.class)\n\t\t\t\t.setFlag(parentChassis.getUpgradeManager().hasUpgradeModuleUpgrade());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\tthrow new UnsupportedOperationException(\"Chassis GUI can never be opened in hand\");\n\t}\n\n\t@Nonnull\n\tpublic ModuleUpgradeManager getModuleUpgradeManager(int slot) {\n\t\treturn slotUpgradeManagers.get(slot);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/LogisticsModule.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.*;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport kotlin.Unit;\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.interfaces.IWorldProvider;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.proxy.computers.objects.CCSinkResponder;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.IStore;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.PropertyHolder;\nimport network.rs485.logisticspipes.property.UtilKt;\n\n@CCType(name = \"LogisticsModule\")\npublic abstract class LogisticsModule implements IStore, ILPCCTypeHolder, PropertyHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\t@Nullable\n\tprotected IWorldProvider _world;\n\t@Nullable\n\tprotected IPipeServiceProvider _service;\n\tprotected ModulePositionType slot;\n\tprotected int positionInt;\n\tprotected boolean initialized;\n\n\t/**\n\t * Registers the Inventory and ItemSender to the module\n\t *\n\t * @param world   that the module is in.\n\t * @param service Inventory access, power and utility functions provided by the pipe.\n\t */\n\tpublic void registerHandler(IWorldProvider world, IPipeServiceProvider service) {\n\t\t_world = world;\n\t\t_service = service;\n\t}\n\n\t/**\n\t * Returns the name this module is registered in LP with, as used in\n\t * {@link logisticspipes.items.ItemModule#registerModule} and saved in {@link logisticspipes.LPItems#modules}.\n\t */\n\t@Nonnull\n\tpublic abstract String getLPName();\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.emptyList();\n\t}\n\n\t/**\n\t * Registers the slot type the module is in\n\t */\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tthis.slot = slot;\n\t\tthis.positionInt = positionInt;\n\t}\n\n\t@Nonnull\n\tpublic BlockPos getBlockPos() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tthrow new IllegalStateException(\"Module has no service, but getBlockPos was called\");\n\t\t\t}\n\t\t\treturn BlockPos.ORIGIN;\n\t\t} else if (slot.isInWorld()) {\n\t\t\treturn service.getPos();\n\t\t} else {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tthrow new IllegalStateException(\"Module is not in world, but getBlockPos was called\");\n\t\t\t}\n\t\t\treturn BlockPos.ORIGIN;\n\t\t}\n\t}\n\n\t@Nullable\n\tpublic World getWorld() {\n\t\tfinal IWorldProvider worldProvider = _world;\n\t\tif (worldProvider == null) return null;\n\t\treturn worldProvider.getWorld();\n\t}\n\n\tpublic ModulePositionType getSlot() {\n\t\treturn this.slot;\n\t}\n\n\tpublic int getPositionInt() {\n\t\treturn this.positionInt;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tPropertyHolder.readFromNBT(tag, this);\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound tag) {\n\t\tPropertyHolder.writeToNBT(tag, this);\n\t}\n\n\t/**\n\t * Gives a sink answer on the given itemstack\n\t *\n\t * @param stack              to sink\n\t * @param item               to sink\n\t * @param bestPriority       best priority seen so far\n\t * @param bestCustomPriority best custom sub-priority\n\t * @param allowDefault       is a default only sink allowed to sink this?\n\t * @param includeInTransit   include the \"in transit\" items? -- true for a destination\n\t *                           search, false for a sink check.\n\t * @param forcePassive       check for passive routing only, in case this method is redirected to other sinks\n\t * @return SinkReply whether the module sinks the item or not\n\t */\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\treturn null;\n\t}\n\n\t/**\n\t * A tick for the Module\n\t */\n\tpublic abstract void tick();\n\n\t/**\n\t * Is this module interested in all items, or just some specific ones?\n\t *\n\t * @return true: this module will be checked against every item request\n\t * false: only requests involving items collected by {@link #collectSpecificInterests(Collection)} will be checked\n\t */\n\tpublic abstract boolean hasGenericInterests();\n\n\t/**\n\t * Collects the items which this module is capable of providing or supplying\n\t * (or is otherwise interested in)\n\t *\n\t * @param itemIdentifiers the collection to add the interests to\n\t */\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t}\n\n\tpublic abstract boolean interestedInAttachedInventory();\n\n\t/**\n\t * is this module interested in receiving any damage variant of items in the\n\t * attached inventory?\n\t */\n\tpublic abstract boolean interestedInUndamagedID();\n\n\t/**\n\t * is this module a valid destination for bounced items.\n\t */\n\tpublic abstract boolean receivePassive();\n\n\t/**\n\t * Returns whether the module should be displayed the effect when as an\n\t * item.\n\t *\n\t * @return True to show effect False to no effect (default)\n\t */\n\tpublic boolean hasEffect() {\n\t\treturn false;\n\t}\n\n\tpublic List<CCSinkResponder> queueCCSinkEvent(ItemIdentifierStack item) {\n\t\treturn new ArrayList<>(0);\n\t}\n\n\t@CCCommand(description = \"Returns true if the Pipe has a gui\")\n\tpublic boolean hasGui() {\n\t\treturn this instanceof Gui;\n\t}\n\n\t@Nonnull\n\tpublic LogisticsModule getModule() {\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\tprotected ISlotUpgradeManager getUpgradeManager() {\n\t\treturn Objects.requireNonNull(_service, \"service object was null in \" + this)\n\t\t\t\t.getUpgradeManager(slot, positionInt);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tString at = \"{service is null}\";\n\t\tif (_service != null) {\n\t\t\tat = Objects.toString(_service.getPos());\n\t\t}\n\t\tString in = \"{world is null}\";\n\t\tif (_world != null) {\n\t\t\tin = Objects.toString(_world.getWorld());\n\t\t}\n\t\treturn String.format(\"%s at %s in %s\", getClass().getName(), at, in);\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n\tpublic void finishInit() {\n\t\tif (initialized) {\n\t\t\tif (LogisticsPipes.isTesting()) {\n\t\t\t\tthrow new IllegalStateException(\"finishInit called on initialized \" + getClass().getName());\n\t\t\t} else if (LogisticsPipes.isDEBUG()) {\n\t\t\t\tSystem.err.println(\"finishInit called on initialized \" + getClass().getName());\n\t\t\t\tnew Exception().printStackTrace();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (_service != null) {\n\t\t\tfinal IBlockAccess blockAccess = _world == null ? null : _world.getWorld();\n\t\t\tMainProxy.runOnServer(blockAccess, () -> () ->\n\t\t\t\t\tUtilKt.addObserver(getProperties(), (prop) -> {\n\t\t\t\t\t\t_service.markTileDirty();\n\t\t\t\t\t\treturn Unit.INSTANCE;\n\t\t\t\t\t})\n\t\t\t);\n\t\t}\n\t\tinitialized = true;\n\t}\n\n\tpublic enum ModulePositionType {\n\t\tSLOT(true), IN_HAND(false), IN_PIPE(true);\n\n\t\t@Getter\n\t\tprivate final boolean inWorld;\n\n\t\tModulePositionType(boolean inWorld) {\n\t\t\tthis.inWorld = inWorld;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleActiveSupplier.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport com.google.common.collect.ImmutableList;\nimport org.jetbrains.annotations.NotNull;\n\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.interfaces.routing.IRequireReliableTransport;\nimport logisticspipes.interfaces.routing.ITargetSlotInformation;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inhand.ActiveSupplierInHand;\nimport logisticspipes.network.guis.module.inpipe.ActiveSupplierSlot;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleInventory;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.pipes.basic.debug.StatusEntry;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.AdjacentUtilKt;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.EnumProperty;\nimport network.rs485.logisticspipes.property.IntListProperty;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\n\npublic class ModuleActiveSupplier extends LogisticsModule\n\t\timplements IRequestItems, IRequireReliableTransport, IClientInformationProvider, IHUDModuleHandler,\n\t\tIModuleWatchReciver, IModuleInventoryReceive, ISimpleInventoryEventHandler, Gui {\n\n\tpublic static final int SUPPLIER_SLOTS = 9;\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final HashMap<ItemIdentifier, Integer> _requestedItems = new HashMap<>();\n\n\t// properties for the pattern upgrade\n\tpublic final IntListProperty slotAssignmentPattern = new IntListProperty(\"slotpattern\");\n\tpublic final EnumProperty<PatternMode> patternMode =\n\t\t\tnew EnumProperty<>(PatternMode.Bulk50, \"patternmode\", PatternMode.values());\n\n\t// properties for the regular configuration\n\tpublic final ItemIdentifierInventoryProperty inventory =\n\t\t\tnew ItemIdentifierInventoryProperty(new ItemIdentifierInventory(SUPPLIER_SLOTS, \"\", 127), \"\");\n\tpublic final EnumProperty<SupplyMode> requestMode =\n\t\t\tnew EnumProperty<>(SupplyMode.Bulk50, \"requestmode\", SupplyMode.values());\n\tpublic final BooleanProperty isLimited = new BooleanProperty(true, \"limited\");\n\n\tprivate final List<Property<?>> properties = ImmutableList.<Property<?>>builder()\n\t\t\t.add(slotAssignmentPattern)\n\t\t\t.add(patternMode)\n\t\t\t.add(inventory)\n\t\t\t.add(requestMode)\n\t\t\t.add(isLimited)\n\t\t\t.build();\n\n\tprivate boolean _lastRequestFailed = false;\n\n\tpublic ModuleActiveSupplier() {\n\t\tinventory.addListener(this);\n\t\tslotAssignmentPattern.ensureSize(SUPPLIER_SLOTS);\n\t}\n\n\tpublic static String getName() {\n\t\treturn \"active_supplier\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@NotNull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn properties;\n\t}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Supplied: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(inventory))\n\t\t\t\t\t\t.setModulePos(this),\n\t\t\t\tplayer);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn null;\n\t\t//return HUD;\n\t}\n\n\t@Override\n\tpublic void handleInvContent(@Nonnull Collection<ItemIdentifierStack> list) {\n\t\tinventory.handleItemIdentifierList(list);\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(inventory))\n\t\t\t\t\t\t\t.setModulePos(this),\n\t\t\t\t\tlocalModeWatchers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t/* TRIGGER INTERFACE */\n\tpublic boolean isRequestFailed() {\n\t\treturn _lastRequestFailed;\n\t}\n\n\tpublic void setRequestFailed(boolean value) {\n\t\t_lastRequestFailed = value;\n\t}\n\n\t@Override\n\tpublic void tick() {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tif (!service.isNthTick(100)) {\n\t\t\treturn;\n\t\t}\n\n\t\t_requestedItems.values().stream().filter(amount -> amount > 0)\n\t\t\t\t.forEach(amount -> service.spawnParticle(Particles.VioletParticle, 2));\n\n\t\tAdjacentUtilKt.sneakyInventoryUtils(service.getAvailableAdjacent(), getUpgradeManager()).stream()\n\t\t\t\t.filter(invUtil -> invUtil != null && invUtil.getSizeInventory() > 0)\n\t\t\t\t.forEach(invUtil -> {\n\t\t\t\t\tif (getUpgradeManager().hasPatternUpgrade()) {\n\t\t\t\t\t\tcreatePatternRequest(invUtil);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcreateSupplyRequest(invUtil);\n\t\t\t\t\t}\n\t\t\t\t});\n\t}\n\n\tprivate void createPatternRequest(IInventoryUtil invUtil) {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tservice.getDebug().log(\"Supplier: Start calculating pattern request\");\n\t\tsetRequestFailed(false);\n\n\t\tfor (int i = 0; i < SUPPLIER_SLOTS; i++) {\n\t\t\tItemIdentifierStack needed = inventory.getIDStackInSlot(i);\n\t\t\tif (needed == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfinal Integer slotAssignedTo = slotAssignmentPattern.get(i);\n\t\t\tif (invUtil.getSizeInventory() <= slotAssignedTo) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack stack = invUtil.getStackInSlot(slotAssignedTo);\n\t\t\tItemIdentifierStack have = null;\n\t\t\tif (!stack.isEmpty()) {\n\t\t\t\thave = ItemIdentifierStack.getFromStack(stack);\n\t\t\t}\n\t\t\tint haveCount = 0;\n\t\t\tif (have != null) {\n\t\t\t\tif (!have.getItem().equals(needed.getItem())) {\n\t\t\t\t\tservice.getDebug().log(\"Supplier: Slot for \" + i + \", \" + needed + \" already taken by \" + have);\n\t\t\t\t\tsetRequestFailed(true);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\thaveCount = have.getStackSize();\n\t\t\t}\n\t\t\tif ((patternMode.getValue() == PatternMode.Bulk50 && haveCount > needed.getStackSize() / 2) || (\n\t\t\t\t\tpatternMode.getValue() == PatternMode.Bulk100 && haveCount > 0)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tInteger requestedCount = _requestedItems.get(needed.getItem());\n\t\t\tif (requestedCount != null) {\n\t\t\t\thaveCount += requestedCount;\n\t\t\t}\n\n\t\t\tint neededCount = needed.getStackSize() - haveCount;\n\t\t\tif (neededCount < 1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tItemIdentifierStack toRequest = new ItemIdentifierStack(needed.getItem(), neededCount);\n\n\t\t\tservice.getDebug().log(\"Supplier: Missing for slot \" + i + \": \" + toRequest);\n\n\t\t\tif (!service.useEnergy(10)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tboolean success = false;\n\n\t\t\tIAdditionalTargetInformation targetInformation = new PatternSupplierTargetInformation(slotAssignedTo,\n\t\t\t\t\tneeded.getStackSize());\n\n\t\t\tif (patternMode.getValue() != PatternMode.Full) {\n\t\t\t\tservice.getDebug().log(\"Supplier: Requesting partial: \" + toRequest);\n\t\t\t\tneededCount = RequestTree.requestPartial(toRequest, this, targetInformation);\n\t\t\t\tservice.getDebug().log(\"Supplier: Requested: \" + toRequest.getItem().makeStack(neededCount));\n\t\t\t\tif (neededCount > 0) {\n\t\t\t\t\tsuccess = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tservice.getDebug().log(\"Supplier: Requesting: \" + toRequest);\n\t\t\t\tsuccess = RequestTree.request(toRequest, this, null, targetInformation);\n\t\t\t\tif (success) {\n\t\t\t\t\tservice.getDebug().log(\"Supplier: Request success\");\n\t\t\t\t} else {\n\t\t\t\t\tservice.getDebug().log(\"Supplier: Request failed\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (success) {\n\t\t\t\tInteger currentRequest = _requestedItems.get(toRequest.getItem());\n\t\t\t\tif (currentRequest == null) {\n\t\t\t\t\t_requestedItems.put(toRequest.getItem(), neededCount);\n\t\t\t\t} else {\n\t\t\t\t\t_requestedItems.put(toRequest.getItem(), currentRequest + neededCount);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsetRequestFailed(true);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void createSupplyRequest(IInventoryUtil invUtil) {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tservice.getDebug().log(\"Supplier: Start calculating supply request\");\n\t\t//How many do I want?\n\t\tHashMap<ItemIdentifier, Integer> needed = new HashMap<>(inventory.getItemsAndCount());\n\t\tservice.getDebug().log(\"Supplier: Needed: \" + needed);\n\n\t\t//How many do I have?\n\t\tMap<ItemIdentifier, Integer> have = invUtil.getItemsAndCount();\n\t\tservice.getDebug().log(\"Supplier: Have:   \" + have);\n\n\t\t//How many do I have?\n\t\tHashMap<ItemIdentifier, Integer> haveUndamaged = new HashMap<>();\n\t\tfor (Entry<ItemIdentifier, Integer> item : have.entrySet()) {\n\t\t\thaveUndamaged.merge(item.getKey().getUndamaged(), item.getValue(), Integer::sum);\n\t\t}\n\n\t\t//Reduce what I have and what have been requested already\n\t\tfor (Entry<ItemIdentifier, Integer> item : needed.entrySet()) {\n\t\t\tint haveCount = haveUndamaged.getOrDefault(item.getKey().getUndamaged(), 0);\n\t\t\tint spaceAvailable = invUtil.roomForItem(item.getKey().unsafeMakeNormalStack(Integer.MAX_VALUE));\n\t\t\tif (requestMode.getValue() == SupplyMode.Infinite) {\n\t\t\t\tInteger requestedCount = _requestedItems.get(item.getKey());\n\t\t\t\tif (requestedCount != null) {\n\t\t\t\t\tspaceAvailable -= requestedCount;\n\t\t\t\t}\n\t\t\t\titem.setValue(Math.min(item.getKey().getMaxStackSize(), Math.max(0, spaceAvailable)));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (spaceAvailable < 1\n\t\t\t\t\t|| (requestMode.getValue() == SupplyMode.Bulk50 && haveCount > item.getValue() / 2)\n\t\t\t\t\t|| (requestMode.getValue() == SupplyMode.Bulk100 && haveCount > 0)) {\n\t\t\t\titem.setValue(0);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (haveCount > 0) {\n\t\t\t\titem.setValue(item.getValue() - haveCount);\n\t\t\t\t// so that 1 damaged item can't satisfy a request for 2 other damage values.\n\t\t\t\thaveUndamaged.put(item.getKey().getUndamaged(), haveCount - item.getValue());\n\t\t\t}\n\t\t\tInteger requestedCount = _requestedItems.get(item.getKey());\n\t\t\tif (requestedCount != null) {\n\t\t\t\titem.setValue(item.getValue() - requestedCount);\n\t\t\t}\n\t\t}\n\n\t\tservice.getDebug().log(\"Supplier: Missing:   \" + needed);\n\n\t\tsetRequestFailed(false);\n\n\t\t//Make request\n\t\tfor (Entry<ItemIdentifier, Integer> need : needed.entrySet()) {\n\t\t\tInteger amountRequested = need.getValue();\n\t\t\tif (amountRequested == null || amountRequested < 1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint neededCount = amountRequested;\n\t\t\tif (!service.useEnergy(10)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tboolean success = false;\n\n\t\t\tIAdditionalTargetInformation targetInformation = new SupplierTargetInformation();\n\n\t\t\tif (requestMode.getValue() != SupplyMode.Full) {\n\t\t\t\tservice.getDebug().log(\"Supplier: Requesting partial: \" + need.getKey().makeStack(neededCount));\n\t\t\t\tneededCount = RequestTree.requestPartial(need.getKey().makeStack(neededCount), this, targetInformation);\n\t\t\t\tservice.getDebug().log(\"Supplier: Requested: \" + need.getKey().makeStack(neededCount));\n\t\t\t\tif (neededCount > 0) {\n\t\t\t\t\tsuccess = true;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tservice.getDebug().log(\"Supplier: Requesting: \" + need.getKey().makeStack(neededCount));\n\t\t\t\tsuccess = RequestTree.request(need.getKey().makeStack(neededCount), this, null, targetInformation);\n\t\t\t\tif (success) {\n\t\t\t\t\tservice.getDebug().log(\"Supplier: Request success\");\n\t\t\t\t} else {\n\t\t\t\t\tservice.getDebug().log(\"Supplier: Request failed\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (success) {\n\t\t\t\tInteger currentRequest = _requestedItems.get(need.getKey());\n\t\t\t\tif (currentRequest == null) {\n\t\t\t\t\t_requestedItems.put(need.getKey(), neededCount);\n\t\t\t\t\tservice.getDebug().log(\"Supplier: Inserting Requested Items: \" + neededCount);\n\t\t\t\t} else {\n\t\t\t\t\t_requestedItems.put(need.getKey(), currentRequest + neededCount);\n\t\t\t\t\tservice.getDebug()\n\t\t\t\t\t\t\t.log(\"Supplier: Raising Requested Items from: \" + currentRequest + \" to: \" + currentRequest\n\t\t\t\t\t\t\t\t\t+ neededCount);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsetRequestFailed(true);\n\t\t\t}\n\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\t// deprecated, TODO: remove after 1.12\n\t\tfinal List<Pair<Integer, String>> slotArrayList = IntStream.range(0, SUPPLIER_SLOTS)\n\t\t\t\t.mapToObj((idx) -> new Pair<>(idx, \"slotArray_\" + idx))\n\t\t\t\t.filter((it) -> tag.hasKey(it.getValue2()))\n\t\t\t\t.collect(Collectors.toList());\n\t\tif (!slotArrayList.isEmpty()) {\n\t\t\tfinal int[] slotArray = new int[SUPPLIER_SLOTS];\n\t\t\tslotArrayList.forEach((pair) -> slotArray[pair.getValue1()] = tag.getInteger(pair.getValue2()));\n\t\t\tslotAssignmentPattern.replaceContent(slotArray);\n\t\t}\n\t}\n\n\tprivate void decreaseRequested(ItemIdentifierStack item) {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tint remaining = item.getStackSize();\n\t\t//see if we can get an exact match\n\t\tInteger count = _requestedItems.get(item.getItem());\n\t\tif (count != null) {\n\t\t\tservice.getDebug().log(\"Supplier: Exact match. Still missing: \" + Math.max(0, count - remaining));\n\t\t\tif (count - remaining > 0) {\n\t\t\t\t_requestedItems.put(item.getItem(), count - remaining);\n\t\t\t} else {\n\t\t\t\t_requestedItems.remove(item.getItem());\n\t\t\t}\n\t\t\tremaining -= count;\n\t\t}\n\t\tif (remaining <= 0) {\n\t\t\treturn;\n\t\t}\n\t\t//still remaining... was from fuzzyMatch on a crafter\n\t\tIterator<Entry<ItemIdentifier, Integer>> it = _requestedItems.entrySet().iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tEntry<ItemIdentifier, Integer> e = it.next();\n\t\t\tif (e.getKey().equalsWithoutNBT(item.getItem())) {\n\t\t\t\tint expected = e.getValue();\n\t\t\t\tservice.getDebug().log(\"Supplier: Fuzzy match with\" + e + \". Still missing: \" + Math\n\t\t\t\t\t\t.max(0, expected - remaining));\n\t\t\t\tif (expected - remaining > 0) {\n\t\t\t\t\te.setValue(expected - remaining);\n\t\t\t\t} else {\n\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t\tremaining -= expected;\n\t\t\t}\n\t\t\tif (remaining <= 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t//we have no idea what this is, log it.\n\t\tservice.getDebug().log(\"Supplier: supplier got unexpected item \" + item);\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tservice.getDebug().log(\"Supplier: Registered Item Lost: \" + item);\n\t\tdecreaseRequested(item);\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tservice.getDebug().log(\"Supplier: Registered Item Arrived: \" + item);\n\t\tdecreaseRequested(item);\n\t}\n\n\tpublic void addStatusInformation(List<StatusEntry> status) {\n\t\tStatusEntry entry = new StatusEntry();\n\t\tentry.name = \"Requested Items\";\n\t\tentry.subEntry = new ArrayList<>();\n\t\tfor (Entry<ItemIdentifier, Integer> part : _requestedItems.entrySet()) {\n\t\t\tStatusEntry subEntry = new StatusEntry();\n\t\t\tsubEntry.name = part.toString();\n\t\t\tentry.subEntry.add(subEntry);\n\t\t}\n\t\tstatus.add(entry);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\tfinal boolean hasPatternUpgrade = hasPatternUpgrade();\n\t\treturn NewGuiHandler.getGui(ActiveSupplierSlot.class)\n\t\t\t\t.setPatternUpgarde(hasPatternUpgrade)\n\t\t\t\t.setSlotArray(slotAssignmentPattern.stream().mapToInt(Integer::intValue).toArray())\n\t\t\t\t.setMode((hasPatternUpgrade ? patternMode.getValue() : requestMode.getValue()).ordinal())\n\t\t\t\t.setLimit(isLimited.getValue());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ActiveSupplierInHand.class);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\treturn service.getRouter();\n\t}\n\n\t@Override\n\tpublic void itemCouldNotBeSend(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\titemLost(item, info);\n\t}\n\n\t@Override\n\tpublic int compareTo(@Nonnull IRequestItems other) {\n\t\treturn Integer.compare(getID(), other.getID());\n\t}\n\n\t@Override\n\tpublic int getID() {\n\t\treturn getRouter().getSimpleID();\n\t}\n\n\tpublic boolean hasPatternUpgrade() {\n\t\treturn getUpgradeManager().hasPatternUpgrade();\n\t}\n\n\tpublic enum SupplyMode {\n\t\tPartial,\n\t\tFull,\n\t\tBulk50,\n\t\tBulk100,\n\t\tInfinite\n\t}\n\n\tpublic enum PatternMode {\n\t\tPartial,\n\t\tFull,\n\t\tBulk50,\n\t\tBulk100\n\t}\n\n\tpublic class PatternSupplierTargetInformation extends SupplierTargetInformation implements ITargetSlotInformation {\n\n\t\tprivate final int amount;\n\t\tprivate final int targetSlot;\n\n\t\tpublic PatternSupplierTargetInformation(int targetSlot, int amount) {\n\t\t\tsuper();\n\t\t\tthis.targetSlot = targetSlot;\n\t\t\tthis.amount = amount;\n\n\t\t}\n\n\t\t@Override\n\t\tpublic int getTargetSlot() {\n\t\t\treturn targetSlot;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getAmount() {\n\t\t\treturn amount;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isLimited() {\n\t\t\treturn ModuleActiveSupplier.this.isLimited.getValue();\n\t\t}\n\n\t}\n\n\tpublic class SupplierTargetInformation extends ChassiTargetInformation {\n\n\t\tpublic SupplierTargetInformation() {\n\t\t\tsuper(getPositionInt());\n\t\t}\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleCrafter.java",
    "content": "package logisticspipes.modules;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.UUID;\nimport java.util.concurrent.DelayQueue;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.entity.EntityPlayerSP;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.item.ItemBlock;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\n\nimport net.minecraftforge.common.util.Constants;\n\nimport com.google.common.collect.ImmutableList;\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.interfaces.IWorldProvider;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IItemSpaceControl;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.logistics.LogisticsManager;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.module.inhand.CraftingModuleInHand;\nimport logisticspipes.network.guis.module.inpipe.CraftingModuleSlot;\nimport logisticspipes.network.packets.cpipe.CPipeSatelliteImport;\nimport logisticspipes.network.packets.cpipe.CPipeSatelliteImportBack;\nimport logisticspipes.network.packets.cpipe.CraftingPipeOpenConnectedGuiPacket;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.pipe.CraftingPipeUpdatePacket;\nimport logisticspipes.network.packets.pipe.FluidCraftingAmount;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.PipeFluidSatellite;\nimport logisticspipes.pipes.PipeItemsSatelliteLogistics;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.CoreRoutedPipe.ItemSendMode;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.interfaces.IFuzzyRecipeProvider;\nimport logisticspipes.request.DictCraftingTemplate;\nimport logisticspipes.request.ICraftingTemplate;\nimport logisticspipes.request.IPromise;\nimport logisticspipes.request.IReqCraftingTemplate;\nimport logisticspipes.request.ItemCraftingTemplate;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.FluidResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.LogisticsDictPromise;\nimport logisticspipes.routing.LogisticsExtraDictPromise;\nimport logisticspipes.routing.LogisticsExtraPromise;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.routing.order.LogisticsItemOrder;\nimport logisticspipes.utils.CacheHolder.CacheTypes;\nimport logisticspipes.utils.DelayedGeneric;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.BufferMode;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.AdjacentUtilKt;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.BitSetProperty;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.IBitSet;\nimport network.rs485.logisticspipes.property.IntListProperty;\nimport network.rs485.logisticspipes.property.IntegerProperty;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.UUIDListProperty;\nimport network.rs485.logisticspipes.property.UUIDProperty;\nimport network.rs485.logisticspipes.property.UUIDPropertyKt;\nimport network.rs485.logisticspipes.util.FuzzyUtil;\n\npublic class ModuleCrafter extends LogisticsModule\n\t\timplements ICraftItems, IHUDModuleHandler, IModuleWatchReciver, IGuiOpenControler, Gui {\n\n\t// TODO: after 1.12.2 add a tagKey\n\tpublic final ItemIdentifierInventoryProperty dummyInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(11, \"Requested items\", 127), \"\");\n\tpublic final ItemIdentifierInventoryProperty liquidInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(ItemUpgrade.MAX_LIQUID_CRAFTER, \"Fluid items\", 1, true), \"FluidInv\");\n\tpublic final ItemIdentifierInventoryProperty cleanupInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(ItemUpgrade.MAX_CRAFTING_CLEANUP * 3, \"Cleanup Filter Items\", 1), \"CleanupInv\");\n\tpublic final UUIDProperty satelliteUUID = new UUIDProperty(null, \"satelliteUUID\");\n\tpublic final UUIDListProperty advancedSatelliteUUIDList = new UUIDListProperty(\"advancedSatelliteUUIDList\");\n\tpublic final UUIDProperty liquidSatelliteUUID = new UUIDProperty(null, \"liquidSatelliteId\");\n\tpublic final UUIDListProperty liquidSatelliteUUIDList = new UUIDListProperty(\"liquidSatelliteUUIDList\");\n\tpublic final IntegerProperty priority = new IntegerProperty(0, \"priority\");\n\tpublic final IntListProperty liquidAmounts = new IntListProperty(\"FluidAmount\");\n\tpublic final BooleanProperty cleanupModeIsExclude = new BooleanProperty(true, \"cleanupModeIsExclude\");\n\tpublic final BitSetProperty fuzzyFlags = new BitSetProperty(new BitSet(4 * (9 + 1)), \"fuzzyBitSet\");\n\tprivate final List<Property<?>> properties = ImmutableList.<Property<?>>builder()\n\t\t\t.add(dummyInventory)\n\t\t\t.add(liquidInventory)\n\t\t\t.add(cleanupInventory)\n\t\t\t.add(satelliteUUID)\n\t\t\t.add(advancedSatelliteUUIDList)\n\t\t\t.add(liquidSatelliteUUID)\n\t\t\t.add(liquidSatelliteUUIDList)\n\t\t\t.add(priority)\n\t\t\t.add(liquidAmounts)\n\t\t\t.add(cleanupModeIsExclude)\n\t\t\t.add(fuzzyFlags)\n\t\t\t.build();\n\n\t// for reliable transport\n\tprotected final DelayQueue<DelayedGeneric<Pair<ItemIdentifierStack, IAdditionalTargetInformation>>> _lostItems = new DelayQueue<>();\n\tprotected final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprotected final PlayerCollectionList guiWatcher = new PlayerCollectionList();\n\n\tpublic ClientSideSatelliteNames clientSideSatelliteNames = new ClientSideSatelliteNames();\n\n\tprotected SinkReply _sinkReply;\n\n\t@Nullable\n\tprivate IRequestItems _invRequester;\n\tprivate WeakReference<TileEntity> lastAccessedCrafter = new WeakReference<>(null);\n\tprivate boolean cachedAreAllOrderesToBuffer;\n\tprivate UpgradeSatelliteFromIDs updateSatelliteFromIDs = null;\n\n\tpublic ModuleCrafter() {\n\t\tadvancedSatelliteUUIDList.ensureSize(9);\n\t\tliquidAmounts.ensureSize(ItemUpgrade.MAX_LIQUID_CRAFTER);\n\t\tliquidSatelliteUUIDList.ensureSize(ItemUpgrade.MAX_LIQUID_CRAFTER);\n\t}\n\n\tpublic static String getName() {\n\t\treturn \"crafter\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn properties;\n\t}\n\n\t/**\n\t * assumes that the invProvider is also IRequest items.\n\t */\n\t@Override\n\tpublic void registerHandler(IWorldProvider world, IPipeServiceProvider service) {\n\t\tsuper.registerHandler(world, service);\n\t\t_invRequester = (IRequestItems) service;\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.ItemSink, 0, true, false, 1, 0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal int itemCount = spaceFor(stack, item, includeInTransit);\n\t\tif (itemCount > 0) {\n\t\t\treturn new SinkReply(_sinkReply, itemCount,\n\t\t\t\t\tareAllOrderesToBuffer() ? BufferMode.DESTINATION_BUFFERED : BufferMode.NONE);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprotected int spaceFor(@Nonnull ItemStack stack, ItemIdentifier item, boolean includeInTransit) {\n\t\tPair<String, ItemIdentifier> key = new Pair<>(\"spaceFor\", item);\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return 0;\n\t\tObject cache = service.getCacheHolder().getCacheFor(CacheTypes.Inventory, key);\n\t\tint onRoute = 0;\n\t\tif (includeInTransit) {\n\t\t\tonRoute = service.countOnRoute(item);\n\t\t}\n\t\tif (cache != null) {\n\t\t\treturn ((Integer) cache) - onRoute;\n\t\t}\n\n\t\tif (includeInTransit) {\n\t\t\tstack = stack.copy();\n\t\t\tstack.grow(onRoute);\n\t\t}\n\t\tfinal ISlotUpgradeManager upgradeManager = Objects.requireNonNull(getUpgradeManager());\n\t\tfinal ItemStack finalStack = stack;\n\t\tfinal Integer count = AdjacentUtilKt.sneakyInventoryUtils(service.getAvailableAdjacent(), upgradeManager)\n\t\t\t\t.stream().map(invUtil -> invUtil.roomForItem(finalStack)).reduce(Integer::sum).orElse(0);\n\n\t\tservice.getCacheHolder().setCache(CacheTypes.Inventory, key, count);\n\t\treturn count - onRoute;\n\t}\n\n\tprivate UUID getUUIDForSatelliteName(String name) {\n\t\tfor (PipeItemsSatelliteLogistics pipe : PipeItemsSatelliteLogistics.AllSatellites) {\n\t\t\tif (pipe.getSatellitePipeName().equals(name)) {\n\t\t\t\treturn pipe.getRouter().getId();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate UUID getUUIDForFluidSatelliteName(String name) {\n\t\tfor (PipeFluidSatellite pipe : PipeFluidSatellite.AllSatellites) {\n\t\t\tif (pipe.getSatellitePipeName().equals(name)) {\n\t\t\t\treturn pipe.getRouter().getId();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\tenabledUpdateEntity();\n\t\tif (updateSatelliteFromIDs != null && service.isNthTick(100)) {\n\t\t\tif (updateSatelliteFromIDs.advancedSatelliteIdArray != null) {\n\t\t\t\tboolean canBeRemoved = true;\n\t\t\t\tfor (int i = 0; i < updateSatelliteFromIDs.advancedSatelliteIdArray.length; i++) {\n\t\t\t\t\tif (updateSatelliteFromIDs.advancedSatelliteIdArray[i] != -1) {\n\t\t\t\t\t\tUUID uuid = getUUIDForSatelliteName(\n\t\t\t\t\t\t\t\tInteger.toString(updateSatelliteFromIDs.advancedSatelliteIdArray[i]));\n\t\t\t\t\t\tif (uuid != null) {\n\t\t\t\t\t\t\tupdateSatelliteFromIDs.advancedSatelliteIdArray[i] = -1;\n\t\t\t\t\t\t\tadvancedSatelliteUUIDList.set(i, uuid);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcanBeRemoved = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (canBeRemoved) {\n\t\t\t\t\tupdateSatelliteFromIDs.advancedSatelliteIdArray = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updateSatelliteFromIDs.liquidSatelliteIdArray != null) {\n\t\t\t\tboolean canBeRemoved = true;\n\t\t\t\tfor (int i = 0; i < updateSatelliteFromIDs.liquidSatelliteIdArray.length; i++) {\n\t\t\t\t\tif (updateSatelliteFromIDs.liquidSatelliteIdArray[i] != -1) {\n\t\t\t\t\t\tUUID uuid = getUUIDForFluidSatelliteName(\n\t\t\t\t\t\t\t\tInteger.toString(updateSatelliteFromIDs.liquidSatelliteIdArray[i]));\n\t\t\t\t\t\tif (uuid != null) {\n\t\t\t\t\t\t\tupdateSatelliteFromIDs.liquidSatelliteIdArray[i] = -1;\n\t\t\t\t\t\t\tliquidSatelliteUUIDList.set(i, uuid);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcanBeRemoved = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (canBeRemoved) {\n\t\t\t\t\tupdateSatelliteFromIDs.liquidSatelliteIdArray = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updateSatelliteFromIDs.liquidSatelliteId != -1) {\n\t\t\t\tUUID uuid = getUUIDForFluidSatelliteName(Integer.toString(updateSatelliteFromIDs.liquidSatelliteId));\n\t\t\t\tif (uuid != null) {\n\t\t\t\t\tupdateSatelliteFromIDs.liquidSatelliteId = -1;\n\t\t\t\t\tliquidSatelliteUUID.setValue(uuid);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updateSatelliteFromIDs.satelliteId != -1) {\n\t\t\t\tUUID uuid = getUUIDForFluidSatelliteName(Integer.toString(updateSatelliteFromIDs.satelliteId));\n\t\t\t\tif (uuid != null) {\n\t\t\t\t\tupdateSatelliteFromIDs.satelliteId = -1;\n\t\t\t\t\tsatelliteUUID.setValue(uuid);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (updateSatelliteFromIDs.advancedSatelliteIdArray == null\n\t\t\t\t\t&& updateSatelliteFromIDs.liquidSatelliteId == -1\n\t\t\t\t\t&& updateSatelliteFromIDs.liquidSatelliteIdArray == null\n\t\t\t\t\t&& updateSatelliteFromIDs.satelliteId == -1) {\n\t\t\t\tupdateSatelliteFromIDs = null;\n\t\t\t}\n\t\t}\n\t\tif (_lostItems.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\t// if(true) return;\n\t\tDelayedGeneric<Pair<ItemIdentifierStack, IAdditionalTargetInformation>> lostItem = _lostItems.poll();\n\t\tint reRequested = 0;\n\t\twhile (lostItem != null && reRequested < 100) {\n\t\t\tPair<ItemIdentifierStack, IAdditionalTargetInformation> pair = lostItem.get();\n\t\t\tif (service.getItemOrderManager().hasOrders(ResourceType.CRAFTING)) {\n\t\t\t\tSinkReply reply = LogisticsManager.canSink(pair.getValue1().makeNormalStack(), getRouter(), null, true,\n\t\t\t\t\t\tpair.getValue1().getItem(), null, true, true, false);\n\t\t\t\tif (reply == null || reply.maxNumberOfItems < 1) {\n\t\t\t\t\t_lostItems.add(new DelayedGeneric<>(pair, 9000 + (int) (Math.random() * 2000)));\n\t\t\t\t\tlostItem = _lostItems.poll();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tint received = RequestTree.requestPartial(pair.getValue1(), (CoreRoutedPipe) service, pair.getValue2());\n\t\t\treRequested++;\n\t\t\tif (received < pair.getValue1().getStackSize()) {\n\t\t\t\tpair.getValue1().setStackSize(pair.getValue1().getStackSize() - received);\n\t\t\t\t_lostItems.add(new DelayedGeneric<>(pair, 4500 + (int) (Math.random() * 1000)));\n\t\t\t}\n\t\t\tlostItem = _lostItems.poll();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\t_lostItems.add(new DelayedGeneric<>(new Pair<>(item, info), 5000));\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tList<ItemIdentifierStack> result = getCraftedItems();\n\t\tif (result == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tresult.stream().map(ItemIdentifierStack::getItem).forEach(itemIdentifiers::add);\n\t\t/*\n\t\tfor(int i=0; i<9;i++) {\n\t\t\tItemIdentifierStack stack = getMaterials(i);\n\t\t\tif(stack != null) {\n\t\t\t\titemIdentifiers.add(stack.getItem()); // needed to be interested in things for a chassi to report reliableDelivery failure.\n\t\t\t}\n\t\t}\n\t\t */\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t\t// when we are default we are interested in everything anyway, otherwise we're only interested in our filter.\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filters) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\tif (!service.getItemOrderManager().hasExtras() || tree.hasBeenQueried(service.getItemOrderManager())) {\n\t\t\treturn;\n\t\t}\n\n\t\tIResource requestedItem = tree.getRequestType();\n\n\t\tif (!canCraft(requestedItem)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (IFilter filter : filters) {\n\t\t\tif (filter.isBlocked() == filter.isFilteredItem(requestedItem) || filter.blockProvider()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tint remaining = 0;\n\t\tfor (LogisticsItemOrder extra : service.getItemOrderManager()) {\n\t\t\tif (extra.getType() == ResourceType.EXTRA) {\n\t\t\t\tif (extra.getResource().getItem().equals(requestedItem.getAsItem())) {\n\t\t\t\t\tremaining += extra.getResource().stack.getStackSize();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfinal ItemIdentifierStack craftedItem = getCraftedItem();\n\t\tif (craftedItem == null) return;\n\t\tremaining -= root.getAllPromissesFor(this, craftedItem.getItem());\n\t\tif (remaining < 1) {\n\t\t\treturn;\n\t\t}\n\t\tif (getUpgradeManager().isFuzzyUpgrade() && outputFuzzy().nextSetBit(0) != -1) {\n\t\t\tDictResource dict = new DictResource(craftedItem, null).loadFromBitSet(outputFuzzy().copyValue());\n\t\t\tLogisticsExtraDictPromise promise = new LogisticsExtraDictPromise(dict,\n\t\t\t\t\tMath.min(remaining, tree.getMissingAmount()), this, true);\n\t\t\ttree.addPromise(promise);\n\t\t} else {\n\t\t\tLogisticsExtraPromise promise = new LogisticsExtraPromise(craftedItem.getItem(),\n\t\t\t\t\tMath.min(remaining, tree.getMissingAmount()), this, true);\n\t\t\ttree.addPromise(promise);\n\t\t}\n\t\ttree.setQueried(service.getItemOrderManager());\n\t}\n\n\t@Override\n\tpublic LogisticsItemOrder fullFill(LogisticsPromise promise, IRequestItems destination,\n\t\t\tIAdditionalTargetInformation info) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tif (promise instanceof LogisticsExtraDictPromise) {\n\t\t\tservice.getItemOrderManager().removeExtras(((LogisticsExtraDictPromise) promise).getResource());\n\t\t}\n\t\tif (promise instanceof LogisticsExtraPromise) {\n\t\t\tservice.getItemOrderManager()\n\t\t\t\t\t.removeExtras(new DictResource(new ItemIdentifierStack(promise.item, promise.numberOfItems), null));\n\t\t}\n\t\tif (promise instanceof LogisticsDictPromise) {\n\t\t\tservice.spawnParticle(Particles.WhiteParticle, 2);\n\t\t\treturn service.getItemOrderManager()\n\t\t\t\t\t.addOrder(((LogisticsDictPromise) promise).getResource(), destination, ResourceType.CRAFTING, info);\n\t\t}\n\t\tservice.spawnParticle(Particles.WhiteParticle, 2);\n\t\treturn service.getItemOrderManager()\n\t\t\t\t.addOrder(new ItemIdentifierStack(promise.item, promise.numberOfItems), destination,\n\t\t\t\t\t\tResourceType.CRAFTING, info);\n\t}\n\n\t@Override\n\tpublic void getAllItems(Map<ItemIdentifier, Integer> list, List<IFilter> filter) {\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\treturn Objects.requireNonNull(_service, \"service was null\").getRouter();\n\t}\n\n\t@Override\n\tpublic void itemCouldNotBeSend(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tObjects.requireNonNull(_invRequester).itemCouldNotBeSend(item, info);\n\t}\n\n\t@Override\n\tpublic int compareTo(@Nonnull IRequestItems other) {\n\t\treturn Integer.compare(getID(), other.getID());\n\t}\n\n\t@Override\n\tpublic int getID() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return -1;\n\t\treturn service.getRouter().getSimpleID();\n\t}\n\n\t@Override\n\tpublic void registerExtras(IPromise promise) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\tif (promise instanceof LogisticsDictPromise) {\n\t\t\tservice.getItemOrderManager().addExtra(((LogisticsDictPromise) promise).getResource());\n\t\t} else {\n\t\t\tItemIdentifierStack stack = new ItemIdentifierStack(promise.getItemType(), promise.getAmount());\n\t\t\tservice.getItemOrderManager().addExtra(new DictResource(stack, null));\n\t\t}\n\t}\n\n\t@Override\n\tpublic ICraftingTemplate addCrafting(IResource toCraft) {\n\n\t\tList<ItemIdentifierStack> stack = getCraftedItems();\n\t\tif (stack == null) {\n\t\t\treturn null;\n\t\t}\n\t\tIReqCraftingTemplate template = null;\n\t\tif (getUpgradeManager().isFuzzyUpgrade() && outputFuzzy().nextSetBit(0) != -1) {\n\t\t\tfor (ItemIdentifierStack craftable : stack) {\n\t\t\t\tDictResource dict = new DictResource(craftable, null);\n\t\t\t\tdict.loadFromBitSet(outputFuzzy().copyValue());\n\t\t\t\tif (toCraft.matches(dict, IResource.MatchSettings.NORMAL)) {\n\t\t\t\t\ttemplate = new DictCraftingTemplate(dict, this, priority.getValue());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (ItemIdentifierStack craftable : stack) {\n\t\t\t\tif (toCraft.matches(craftable.getItem(), IResource.MatchSettings.NORMAL)) {\n\t\t\t\t\ttemplate = new ItemCraftingTemplate(craftable, this, priority.getValue());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (template == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tIRequestItems[] target = new IRequestItems[9];\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\ttarget[i] = this;\n\t\t}\n\n\t\tif (!isSatelliteConnected()) {\n\t\t\t// has a satellite configured and that one is unreachable\n\t\t\treturn null;\n\t\t}\n\t\tif (!getUpgradeManager().isAdvancedSatelliteCrafter()) {\n\t\t\tIRouter r = getSatelliteRouter(-1);\n\t\t\tif (r != null) {\n\t\t\t\tIRequestItems sat = r.getPipe();\n\t\t\t\tfor (int i = 6; i < 9; i++) {\n\t\t\t\t\ttarget[i] = sat;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tIRouter r = getSatelliteRouter(i);\n\t\t\t\tif (r != null) {\n\t\t\t\t\ttarget[i] = r.getPipe();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//Check all materials\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tItemIdentifierStack resourceStack = dummyInventory.getIDStackInSlot(i);\n\t\t\tif (resourceStack == null || resourceStack.getStackSize() == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tIResource req;\n\t\t\tif (getUpgradeManager().isFuzzyUpgrade() && inputFuzzy(i).nextSetBit(0) != -1) {\n\t\t\t\tDictResource dict;\n\t\t\t\treq = dict = new DictResource(resourceStack, target[i]);\n\t\t\t\tdict.loadFromBitSet(inputFuzzy(i).copyValue());\n\t\t\t} else {\n\t\t\t\treq = new ItemResource(resourceStack, target[i]);\n\t\t\t}\n\t\t\ttemplate.addRequirement(req, new CraftingChassisInformation(i, getPositionInt()));\n\t\t}\n\n\t\tint liquidCrafter = getUpgradeManager().getFluidCrafter();\n\t\tIRequestFluid[] liquidTarget = new IRequestFluid[liquidCrafter];\n\n\t\tif (!getUpgradeManager().isAdvancedSatelliteCrafter()) {\n\t\t\tIRouter r = getFluidSatelliteRouter(-1);\n\t\t\tif (r != null) {\n\t\t\t\tIRequestFluid sat = (IRequestFluid) r.getPipe();\n\t\t\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\t\t\tliquidTarget[i] = sat;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\t\tIRouter r = getFluidSatelliteRouter(i);\n\t\t\t\tif (r != null) {\n\t\t\t\t\tliquidTarget[i] = (IRequestFluid) r.getPipe();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\tFluidIdentifier liquid = getFluidMaterial(i);\n\t\t\tint amount = liquidAmounts.get(i);\n\t\t\tif (liquid == null || amount <= 0 || liquidTarget[i] == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttemplate.addRequirement(new FluidResource(liquid, amount, liquidTarget[i]), null);\n\t\t}\n\n\t\tif (getUpgradeManager().hasByproductExtractor() && getByproductItem() != null) {\n\t\t\ttemplate.addByproduct(getByproductItem());\n\t\t}\n\n\t\treturn template;\n\t}\n\n\tpublic boolean isSatelliteConnected() {\n\t\t//final List<ExitRoute> routes = getRouter().getIRoutersByCost();\n\t\tif (!getUpgradeManager().isAdvancedSatelliteCrafter()) {\n\t\t\tif (satelliteUUID.isZero()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tint satelliteRouterId = SimpleServiceLocator.routerManager.getIDforUUID(satelliteUUID.getValue());\n\t\t\tif (satelliteRouterId != -1) {\n\t\t\t\tList<ExitRoute> rt = getRouter().getRouteTable().get(satelliteRouterId);\n\t\t\t\treturn rt != null && !rt.isEmpty();\n\t\t\t}\n\t\t} else {\n\t\t\tboolean foundAll = true;\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tboolean foundOne = false;\n\t\t\t\tif (advancedSatelliteUUIDList.isZero(i)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tint satelliteRouterId = SimpleServiceLocator.routerManager\n\t\t\t\t\t\t.getIDforUUID(advancedSatelliteUUIDList.get(i));\n\t\t\t\tif (satelliteRouterId != -1) {\n\t\t\t\t\tList<ExitRoute> rt = getRouter().getRouteTable().get(satelliteRouterId);\n\t\t\t\t\tif (rt != null && !rt.isEmpty()) {\n\t\t\t\t\t\tfoundOne = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfoundAll &= foundOne;\n\t\t\t}\n\t\t\treturn foundAll;\n\t\t}\n\t\t//TODO check for FluidCrafter\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canCraft(IResource toCraft) {\n\t\tif (getCraftedItem() == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (toCraft instanceof ItemResource || toCraft instanceof DictResource) {\n\t\t\treturn toCraft.matches(getCraftedItem().getItem(), IResource.MatchSettings.NORMAL);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Deprecated\n\t@Override\n\tpublic List<ItemIdentifierStack> getCraftedItems() {\n\t\tList<ItemIdentifierStack> list = new ArrayList<>(1);\n\t\tif (getCraftedItem() != null) {\n\t\t\tlist.add(getCraftedItem());\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Nullable\n\tpublic ItemIdentifierStack getCraftedItem() {\n\t\treturn dummyInventory.getIDStackInSlot(9);\n\t}\n\n\t@Override\n\tpublic int getTodo() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return 0;\n\t\treturn service.getItemOrderManager().totalAmountCountInAllOrders();\n\t}\n\n\tprivate IRouter getSatelliteRouter(int x) {\n\t\tfinal UUID satelliteUUID = x == -1 ? this.satelliteUUID.getValue() : advancedSatelliteUUIDList.get(x);\n\t\tfinal int satelliteRouterId = SimpleServiceLocator.routerManager.getIDforUUID(satelliteUUID);\n\t\treturn SimpleServiceLocator.routerManager.getRouter(satelliteRouterId);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\n\t\t// FIXME: remove after 1.12\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tString advancedSatelliteUUIDArrayString = tag.getString(\"advancedSatelliteUUID\" + i);\n\t\t\tif (!advancedSatelliteUUIDArrayString.isEmpty()) {\n\t\t\t\tadvancedSatelliteUUIDList.set(i, UUID.fromString(advancedSatelliteUUIDArrayString));\n\t\t\t}\n\t\t}\n\n\t\t// FIXME: remove after 1.12\n\t\tfor (int i = 0; i < ItemUpgrade.MAX_LIQUID_CRAFTER; i++) {\n\t\t\tString liquidSatelliteUUIDArrayString = tag.getString(\"liquidSatelliteUUIDArray\" + i);\n\t\t\tif (!liquidSatelliteUUIDArrayString.isEmpty()) {\n\t\t\t\tliquidSatelliteUUIDList.set(i, UUID.fromString(liquidSatelliteUUIDArrayString));\n\t\t\t}\n\t\t}\n\n\t\t// FIXME: remove after 1.12\n\t\tif (tag.hasKey(\"fuzzyFlags\")) {\n\t\t\tNBTTagList lst = tag.getTagList(\"fuzzyFlags\", Constants.NBT.TAG_COMPOUND);\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tFuzzyUtil.INSTANCE.readFromNBT(inputFuzzy(i), lst.getCompoundTagAt(i));\n\t\t\t}\n\t\t}\n\t\t// FIXME: remove after 1.12\n\t\tif (tag.hasKey(\"outputFuzzyFlags\")) {\n\t\t\tFuzzyUtil.INSTANCE.readFromNBT(outputFuzzy(), tag.getCompoundTag(\"outputFuzzyFlags\"));\n\t\t}\n\n\t\t// FIXME: remove after 1.12\n\t\tif (tag.hasKey(\"satelliteid\")) {\n\t\t\tupdateSatelliteFromIDs = new UpgradeSatelliteFromIDs();\n\t\t\tupdateSatelliteFromIDs.satelliteId = tag.getInteger(\"satelliteid\");\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tupdateSatelliteFromIDs.advancedSatelliteIdArray[i] = tag.getInteger(\"advancedSatelliteId\" + i);\n\t\t\t}\n\t\t\tfor (int i = 0; i < ItemUpgrade.MAX_LIQUID_CRAFTER; i++) {\n\t\t\t\tupdateSatelliteFromIDs.liquidSatelliteIdArray[i] = tag.getInteger(\"liquidSatelliteIdArray\" + i);\n\t\t\t}\n\t\t\tupdateSatelliteFromIDs.liquidSatelliteId = tag.getInteger(\"liquidSatelliteId\");\n\t\t}\n\t}\n\n\tpublic IBitSet outputFuzzy() {\n\t\tfinal int startIdx = 4 * 9; // after the 9th slot\n\t\treturn fuzzyFlags.get(startIdx, startIdx + 3);\n\t}\n\n\tpublic IBitSet inputFuzzy(int slot) {\n\t\tfinal int startIdx = 4 * slot;\n\t\treturn fuzzyFlags.get(startIdx, startIdx + 3);\n\t}\n\n\tpublic ModernPacket getCPipePacket() {\n\t\treturn PacketHandler.getPacket(CraftingPipeUpdatePacket.class).setAmount(liquidAmounts.getArray())\n\t\t\t\t.setLiquidSatelliteNameArray(getSatelliteNamesForUUIDs(liquidSatelliteUUIDList))\n\t\t\t\t.setLiquidSatelliteName(getSatelliteNameForUUID(liquidSatelliteUUID.getValue()))\n\t\t\t\t.setSatelliteName(getSatelliteNameForUUID(satelliteUUID.getValue()))\n\t\t\t\t.setAdvancedSatelliteNameArray(getSatelliteNamesForUUIDs(advancedSatelliteUUIDList))\n\t\t\t\t.setPriority(priority.getValue()).setModulePos(this);\n\t}\n\n\tprivate String getSatelliteNameForUUID(UUID uuid) {\n\t\tif (UUIDPropertyKt.isZero(uuid)) {\n\t\t\treturn \"\";\n\t\t}\n\t\tint simpleId = SimpleServiceLocator.routerManager.getIDforUUID(uuid);\n\t\tIRouter router = SimpleServiceLocator.routerManager.getRouter(simpleId);\n\t\tif (router != null) {\n\t\t\tCoreRoutedPipe pipe = router.getPipe();\n\t\t\tif (pipe instanceof PipeItemsSatelliteLogistics) {\n\t\t\t\treturn ((PipeItemsSatelliteLogistics) pipe).getSatellitePipeName();\n\t\t\t} else if (pipe instanceof PipeFluidSatellite) {\n\t\t\t\treturn ((PipeFluidSatellite) pipe).getSatellitePipeName();\n\t\t\t}\n\t\t}\n\t\treturn \"UNKNOWN NAME\";\n\t}\n\n\tprivate String[] getSatelliteNamesForUUIDs(UUIDListProperty list) {\n\t\treturn list.stream().map(this::getSatelliteNameForUUID).toArray(String[]::new);\n\t}\n\n\tpublic void handleCraftingUpdatePacket(CraftingPipeUpdatePacket packet) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tliquidAmounts.replaceContent(packet.getAmount());\n\t\t\tclientSideSatelliteNames.liquidSatelliteNameArray = packet.getLiquidSatelliteNameArray();\n\t\t\tclientSideSatelliteNames.liquidSatelliteName = packet.getLiquidSatelliteName();\n\t\t\tclientSideSatelliteNames.satelliteName = packet.getSatelliteName();\n\t\t\tclientSideSatelliteNames.advancedSatelliteNameArray = packet.getAdvancedSatelliteNameArray();\n\t\t\tpriority.setValue(packet.getPriority());\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn NewGuiHandler.getGui(CraftingModuleSlot.class)\n\t\t\t\t.setAdvancedSat(getUpgradeManager().isAdvancedSatelliteCrafter())\n\t\t\t\t.setLiquidCrafter(getUpgradeManager().getFluidCrafter())\n\t\t\t\t.setAmount(liquidAmounts.getArray())\n\t\t\t\t.setHasByproductExtractor(getUpgradeManager().hasByproductExtractor())\n\t\t\t\t.setFuzzy(getUpgradeManager().isFuzzyUpgrade())\n\t\t\t\t.setCleanupSize(getUpgradeManager().getCrafterCleanup())\n\t\t\t\t.setCleanupExclude(cleanupModeIsExclude.getValue());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(CraftingModuleInHand.class).setAmount(liquidAmounts.getArray())\n\t\t\t\t.setCleanupExclude(cleanupModeIsExclude.getValue());\n\t}\n\n\tpublic void importFromCraftingTable(@Nullable EntityPlayer player) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\t// Send packet asking for import\n\t\t\tfinal CoordinatesPacket packet = PacketHandler.getPacket(CPipeSatelliteImport.class).setModulePos(this);\n\t\t\tMainProxy.sendPacketToServer(packet);\n\t\t} else {\n\t\t\tfinal IPipeServiceProvider service = _service;\n\t\t\tif (service == null) return;\n\t\t\tservice.getAvailableAdjacent().neighbors().keySet().stream().flatMap(\n\t\t\t\t\tneighbor -> SimpleServiceLocator.craftingRecipeProviders.stream()\n\t\t\t\t\t\t\t.filter(provider -> provider.importRecipe(neighbor.getTileEntity(), dummyInventory))\n\t\t\t\t\t\t\t.map(provider1 -> new Pair<>(neighbor, provider1))).findFirst()\n\t\t\t\t\t.ifPresent(neighborProviderPair -> {\n\t\t\t\t\t\tif (neighborProviderPair.getValue2() instanceof IFuzzyRecipeProvider) {\n\t\t\t\t\t\t\t((IFuzzyRecipeProvider) neighborProviderPair.getValue2())\n\t\t\t\t\t\t\t\t\t.importFuzzyFlags(neighborProviderPair.getValue1().getTileEntity(),\n\t\t\t\t\t\t\t\t\t\t\tdummyInventory.getSlotAccess(), fuzzyFlags);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t// Send inventory as packet\n\t\t\tfinal CoordinatesPacket packet = PacketHandler.getPacket(CPipeSatelliteImportBack.class)\n\t\t\t\t\t.setInventory(dummyInventory).setModulePos(this);\n\t\t\tif (player != null) {\n\t\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\t}\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(this, packet);\n\t\t}\n\t}\n\n\tpublic ItemIdentifierStack getByproductItem() {\n\t\treturn dummyInventory.getIDStackInSlot(10);\n\t}\n\n\tpublic FluidIdentifier getFluidMaterial(int slotnr) {\n\t\tItemIdentifierStack stack = liquidInventory.getIDStackInSlot(slotnr);\n\t\tif (stack == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn FluidIdentifier.get(stack.getItem());\n\t}\n\n\tpublic void changeFluidAmount(int change, int slot, EntityPlayer player) {\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPacketHandler.getPacket(FluidCraftingAmount.class).setInteger2(slot).setInteger(change)\n\t\t\t\t\t\t\t.setModulePos(this));\n\t\t} else {\n\t\t\tliquidAmounts.increase(slot, change);\n\t\t\tif (liquidAmounts.get(slot) <= 0) {\n\t\t\t\tliquidAmounts.set(slot, 0);\n\t\t\t}\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(FluidCraftingAmount.class).setInteger2(slot)\n\t\t\t\t\t.setInteger(liquidAmounts.get(slot)).setModulePos(this), player);\n\t\t}\n\t}\n\n\tprivate IRouter getFluidSatelliteRouter(int x) {\n\t\tfinal UUID liquidSatelliteUUID = x == -1 ? this.liquidSatelliteUUID.getValue() : liquidSatelliteUUIDList.get(x);\n\t\tfinal int satelliteRouterId = SimpleServiceLocator.routerManager.getIDforUUID(liquidSatelliteUUID);\n\t\treturn SimpleServiceLocator.routerManager.getRouter(satelliteRouterId);\n\t}\n\n\t/**\n\t * Triggers opening the first possible crafting provider or inventory GUI by using onBlockActivated.\n\t *\n\t * @return true, if a GUI was opened (server-side only)\n\t */\n\tpublic boolean openAttachedGui(EntityPlayer player) {\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tif (player instanceof EntityPlayerMP) {\n\t\t\t\tplayer.closeScreen();\n\t\t\t} else if (player instanceof EntityPlayerSP) {\n\t\t\t\tplayer.closeScreen();\n\t\t\t}\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPacketHandler.getPacket(CraftingPipeOpenConnectedGuiPacket.class).setModulePos(this));\n\t\t\treturn false;\n\t\t}\n\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return false;\n\t\tfinal IWorldProvider worldProvider = _world;\n\t\tif (worldProvider == null) return false;\n\n\t\t// hack to avoid wrenching blocks\n\t\tint savedEquipped = player.inventory.currentItem;\n\t\tboolean foundSlot = false;\n\t\t// try to find a empty slot\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tif (player.inventory.getStackInSlot(i).isEmpty()) {\n\t\t\t\tfoundSlot = true;\n\t\t\t\tplayer.inventory.currentItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// okay, anything that's a block?\n\t\tif (!foundSlot) {\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tItemStack is = player.inventory.getStackInSlot(i);\n\t\t\t\tif (is.getItem() instanceof ItemBlock) {\n\t\t\t\t\tfoundSlot = true;\n\t\t\t\t\tplayer.inventory.currentItem = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// give up and select whatever is right of the current slot\n\t\tif (!foundSlot) {\n\t\t\tplayer.inventory.currentItem = (player.inventory.currentItem + 1) % 9;\n\t\t}\n\n\t\tfinal boolean guiOpened = service.getAvailableAdjacent().neighbors().keySet().stream().anyMatch(neighbor -> {\n\t\t\tif (neighbor.canHandleItems() || SimpleServiceLocator.craftingRecipeProviders.stream()\n\t\t\t\t\t.anyMatch(provider -> provider.canOpenGui(neighbor.getTileEntity()))) {\n\t\t\t\tfinal BlockPos pos = neighbor.getTileEntity().getPos();\n\t\t\t\tIBlockState blockState = worldProvider.getWorld().getBlockState(pos);\n\t\t\t\treturn !blockState.getBlock().isAir(blockState, worldProvider.getWorld(), pos) && blockState.getBlock()\n\t\t\t\t\t\t.onBlockActivated(worldProvider.getWorld(), pos,\n\t\t\t\t\t\t\t\tneighbor.getTileEntity().getWorld().getBlockState(pos), player, EnumHand.MAIN_HAND,\n\t\t\t\t\t\t\t\tEnumFacing.UP, 0, 0, 0);\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif (!guiOpened) {\n\t\t\tLogisticsPipes.log.warn(\"Ignored open attached GUI request at \" + player.world + \" @ \" + getBlockPos());\n\t\t}\n\t\tplayer.inventory.currentItem = savedEquipped;\n\t\treturn guiOpened;\n\t}\n\n\tpublic void enabledUpdateEntity() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\n\t\tif (service.getItemOrderManager().hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA)) {\n\t\t\tif (service.isNthTick(6)) {\n\t\t\t\tcacheAreAllOrderesToBuffer();\n\t\t\t}\n\t\t\tif (service.getItemOrderManager().isFirstOrderWatched()) {\n\t\t\t\tTileEntity tile = lastAccessedCrafter.get();\n\t\t\t\tif (tile != null) {\n\t\t\t\t\tservice.getItemOrderManager()\n\t\t\t\t\t\t\t.setMachineProgress(SimpleServiceLocator.machineProgressProvider.getProgressForTile(tile));\n\t\t\t\t} else {\n\t\t\t\t\tservice.getItemOrderManager().setMachineProgress((byte) 0);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tcachedAreAllOrderesToBuffer = false;\n\t\t}\n\n\t\tif (!service.isNthTick(6)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfinal List<NeighborTileEntity<TileEntity>> adjacentInventories = service.getAvailableAdjacent().inventories();\n\n\t\tif (!service.getItemOrderManager().hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA)) {\n\t\t\tfinal ISlotUpgradeManager upgradeManager = Objects.requireNonNull(getUpgradeManager());\n\t\t\tif (upgradeManager.getCrafterCleanup() > 0) {\n\t\t\t\tadjacentInventories.stream()\n\t\t\t\t\t\t.map(neighbor -> extractFiltered(neighbor, cleanupInventory, cleanupModeIsExclude.getValue(),\n\t\t\t\t\t\t\t\tupgradeManager.getCrafterCleanup() * 3)).filter(stack -> !stack.isEmpty()).findFirst()\n\t\t\t\t\t\t.ifPresent(extracted -> {\n\t\t\t\t\t\t\tservice.queueRoutedItem(\n\t\t\t\t\t\t\t\t\tSimpleServiceLocator.routedItemHelper.createNewTravelItem(extracted),\n\t\t\t\t\t\t\t\t\tEnumFacing.UP);\n\t\t\t\t\t\t\tservice.getCacheHolder().trigger(CacheTypes.Inventory);\n\t\t\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (adjacentInventories.size() < 1) {\n\t\t\tif (service.getItemOrderManager().hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA)) {\n\t\t\t\tservice.getItemOrderManager().sendFailed();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tList<ItemIdentifierStack> wantedItem = getCraftedItems();\n\t\tif (wantedItem == null || wantedItem.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\n\t\tservice.spawnParticle(Particles.VioletParticle, 2);\n\n\t\tint itemsLeft = itemsToExtract();\n\t\tint stacksLeft = stacksToExtract();\n\t\twhile (itemsLeft > 0 && stacksLeft > 0 && (service.getItemOrderManager()\n\t\t\t\t.hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA))) {\n\t\t\tLogisticsItemOrder nextOrder = service.getItemOrderManager()\n\t\t\t\t\t.peekAtTopRequest(ResourceType.CRAFTING, ResourceType.EXTRA); // fetch but not remove.\n\t\t\tint maxToSend = Math.min(itemsLeft, nextOrder.getResource().stack.getStackSize());\n\t\t\tmaxToSend = Math.min(nextOrder.getResource().getItem().getMaxStackSize(), maxToSend);\n\t\t\t// retrieve the new crafted items\n\t\t\tItemStack extracted = ItemStack.EMPTY;\n\t\t\tNeighborTileEntity<TileEntity> adjacent = null; // there has to be at least one adjacentCrafter at this point; adjacent wont stay null\n\t\t\tfor (NeighborTileEntity<TileEntity> adjacentCrafter : adjacentInventories) {\n\t\t\t\tadjacent = adjacentCrafter;\n\t\t\t\textracted = extract(adjacent, nextOrder.getResource(), maxToSend);\n\t\t\t\tif (!extracted.isEmpty()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (extracted.isEmpty()) {\n\t\t\t\tservice.getItemOrderManager().deferSend();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tservice.getCacheHolder().trigger(CacheTypes.Inventory);\n\t\t\tObjects.requireNonNull(adjacent);\n\t\t\tlastAccessedCrafter = new WeakReference<>(adjacent.getTileEntity());\n\t\t\t// send the new crafted items to the destination\n\t\t\tItemIdentifier extractedID = ItemIdentifier.get(extracted);\n\t\t\twhile (!extracted.isEmpty()) {\n\t\t\t\tif (isExtractedMismatch(nextOrder, extractedID)) {\n\t\t\t\t\tLogisticsItemOrder startOrder = nextOrder;\n\t\t\t\t\tif (service.getItemOrderManager().hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA)) {\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tservice.getItemOrderManager().deferSend();\n\t\t\t\t\t\t\tnextOrder = service.getItemOrderManager()\n\t\t\t\t\t\t\t\t\t.peekAtTopRequest(ResourceType.CRAFTING, ResourceType.EXTRA);\n\t\t\t\t\t\t} while (isExtractedMismatch(nextOrder, extractedID) && startOrder != nextOrder);\n\t\t\t\t\t}\n\t\t\t\t\tif (startOrder == nextOrder) {\n\t\t\t\t\t\tint numToSend = Math.min(extracted.getCount(), extractedID.getMaxStackSize());\n\t\t\t\t\t\tif (numToSend == 0) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstacksLeft -= 1;\n\t\t\t\t\t\titemsLeft -= numToSend;\n\t\t\t\t\t\tItemStack stackToSend = extracted.splitStack(numToSend);\n\t\t\t\t\t\t//Route the unhandled item\n\n\t\t\t\t\t\tservice.sendStack(stackToSend, -1, ItemSendMode.Normal, null, adjacent.getDirection());\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tint numToSend = Math.min(extracted.getCount(), extractedID.getMaxStackSize());\n\t\t\t\tnumToSend = Math.min(numToSend, nextOrder.getResource().stack.getStackSize());\n\t\t\t\tif (numToSend == 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tstacksLeft -= 1;\n\t\t\t\titemsLeft -= numToSend;\n\t\t\t\tItemStack stackToSend = extracted.splitStack(numToSend);\n\t\t\t\tif (nextOrder.getDestination() != null) {\n\t\t\t\t\tSinkReply reply = LogisticsManager\n\t\t\t\t\t\t\t.canSink(stackToSend, nextOrder.getDestination().getRouter(), null, true,\n\t\t\t\t\t\t\t\t\tItemIdentifier.get(stackToSend), null, true, false);\n\t\t\t\t\tboolean deferSend = (reply == null || reply.bufferMode != BufferMode.NONE\n\t\t\t\t\t\t\t|| reply.maxNumberOfItems < 1);\n\t\t\t\t\tIRoutedItem item = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stackToSend);\n\t\t\t\t\titem.setDestination(nextOrder.getDestination().getRouter().getSimpleID());\n\t\t\t\t\titem.setTransportMode(TransportMode.Active);\n\t\t\t\t\titem.setAdditionalTargetInformation(nextOrder.getInformation());\n\t\t\t\t\tservice.queueRoutedItem(item, adjacent.getDirection());\n\t\t\t\t\tservice.getItemOrderManager().sendSuccessfull(stackToSend.getCount(), deferSend, item);\n\t\t\t\t} else {\n\t\t\t\t\tservice.sendStack(stackToSend, -1, ItemSendMode.Normal, nextOrder.getInformation(),\n\t\t\t\t\t\t\tadjacent.getDirection());\n\t\t\t\t\tservice.getItemOrderManager().sendSuccessfull(stackToSend.getCount(), false, null);\n\t\t\t\t}\n\t\t\t\tif (service.getItemOrderManager().hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA)) {\n\t\t\t\t\tnextOrder = service.getItemOrderManager()\n\t\t\t\t\t\t\t.peekAtTopRequest(ResourceType.CRAFTING, ResourceType.EXTRA); // fetch but not remove.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tprivate boolean isExtractedMismatch(LogisticsItemOrder nextOrder, ItemIdentifier extractedID) {\n\t\treturn !nextOrder.getResource().getItem().equals(extractedID) && (!getUpgradeManager().isFuzzyUpgrade() || (\n\t\t\t\tnextOrder.getResource().getBitSet().nextSetBit(0) == -1) || !nextOrder.getResource()\n\t\t\t\t.matches(extractedID, IResource.MatchSettings.NORMAL));\n\t}\n\n\tpublic boolean areAllOrderesToBuffer() {\n\t\treturn cachedAreAllOrderesToBuffer;\n\t}\n\n\tpublic void cacheAreAllOrderesToBuffer() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\tboolean result = true;\n\t\tfor (LogisticsItemOrder order : service.getItemOrderManager()) {\n\t\t\tif (order.getDestination() instanceof IItemSpaceControl) {\n\t\t\t\tSinkReply reply = LogisticsManager\n\t\t\t\t\t\t.canSink(order.getResource().stack.makeNormalStack(), order.getDestination().getRouter(), null,\n\t\t\t\t\t\t\t\ttrue, order.getResource().getItem(), null, true, false);\n\t\t\t\tif (reply != null && reply.bufferMode == BufferMode.NONE && reply.maxNumberOfItems >= 1) {\n\t\t\t\t\tresult = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else { // No Space control\n\t\t\t\tresult = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tcachedAreAllOrderesToBuffer = result;\n\t}\n\n\t@Nonnull\n\tprivate ItemStack extract(NeighborTileEntity<TileEntity> adjacent, IResource item, int amount) {\n\t\treturn LPNeighborTileEntityKt.optionalIs(adjacent, LogisticsCraftingTableTileEntity.class)\n\t\t\t\t.map(adjacentCraftingTable -> extractFromLogisticsCraftingTable(adjacentCraftingTable, item, amount))\n\t\t\t\t.orElseGet(() -> {\n\t\t\t\t\tfinal IInventoryUtil invUtil = LPNeighborTileEntityKt.getInventoryUtil(adjacent);\n\t\t\t\t\tif (invUtil == null) return ItemStack.EMPTY;\n\t\t\t\t\treturn extractFromInventory(invUtil, item, amount);\n\t\t\t\t});\n\t}\n\n\t@Nonnull\n\tprivate ItemStack extractFiltered(NeighborTileEntity<TileEntity> neighbor, IItemIdentifierInventory inv,\n\t\t\tboolean isExcluded, int filterInvLimit) {\n\t\tfinal IInventoryUtil invUtil = LPNeighborTileEntityKt.getInventoryUtil(neighbor);\n\t\tif (invUtil == null) return ItemStack.EMPTY;\n\t\treturn extractFromInventoryFiltered(invUtil, inv, isExcluded, filterInvLimit);\n\t}\n\n\t@Nonnull\n\tprivate ItemStack extractFromInventory(@Nonnull IInventoryUtil invUtil, IResource wantedItem, int count) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return ItemStack.EMPTY;\n\t\tItemIdentifier itemToExtract = null;\n\t\tif (wantedItem instanceof ItemResource) {\n\t\t\titemToExtract = ((ItemResource) wantedItem).getItem();\n\t\t} else if (wantedItem instanceof DictResource) {\n\t\t\tint max = Integer.MIN_VALUE;\n\t\t\tItemIdentifier toExtract = null;\n\t\t\tfor (Map.Entry<ItemIdentifier, Integer> content : invUtil.getItemsAndCount().entrySet()) {\n\t\t\t\tif (wantedItem.matches(content.getKey(), IResource.MatchSettings.NORMAL)) {\n\t\t\t\t\tif (content.getValue() > max) {\n\t\t\t\t\t\tmax = content.getValue();\n\t\t\t\t\t\ttoExtract = content.getKey();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (toExtract == null) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t\titemToExtract = toExtract;\n\t\t}\n\t\tif (itemToExtract == null) return ItemStack.EMPTY;\n\t\tint available = invUtil.itemCount(itemToExtract);\n\t\tif (available == 0 || !service.canUseEnergy(neededEnergy() * Math.min(count, available))) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tItemStack extracted = invUtil.getMultipleItems(itemToExtract, Math.min(count, available));\n\t\tservice.useEnergy(neededEnergy() * extracted.getCount());\n\t\treturn extracted;\n\t}\n\n\t@Nonnull\n\tprivate ItemStack extractFromInventoryFiltered(@Nonnull IInventoryUtil invUtil, IItemIdentifierInventory filter,\n\t\t\tboolean isExcluded, int filterInvLimit) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return ItemStack.EMPTY;\n\n\t\tItemIdentifier wantedItem = null;\n\t\tboolean found = false;\n\t\tfor (ItemIdentifier item : invUtil.getItemsAndCount().keySet()) {\n\t\t\tfound = isFiltered(filter, filterInvLimit, item, found);\n\t\t\tif (isExcluded != found) {\n\t\t\t\twantedItem = item;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (wantedItem == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tint available = invUtil.itemCount(wantedItem);\n\t\tif (available == 0 || !service.canUseEnergy(neededEnergy() * Math.min(64, available))) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tItemStack extracted = invUtil.getMultipleItems(wantedItem, Math.min(64, available));\n\t\tservice.useEnergy(neededEnergy() * extracted.getCount());\n\t\treturn extracted;\n\t}\n\n\tprivate boolean isFiltered(IItemIdentifierInventory filter, int filterInvLimit, ItemIdentifier item,\n\t\t\tboolean found) {\n\t\tfor (int i = 0; i < filter.getSizeInventory() && i < filterInvLimit; i++) {\n\t\t\tItemIdentifierStack identStack = filter.getIDStackInSlot(i);\n\t\t\tif (identStack == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (identStack.getItem().equalsWithoutNBT(item)) {\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn found;\n\t}\n\n\t@Nonnull\n\tprivate ItemStack extractFromLogisticsCraftingTable(\n\t\t\tNeighborTileEntity<LogisticsCraftingTableTileEntity> adjacentCraftingTable, IResource wantedItem,\n\t\t\tint count) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return ItemStack.EMPTY;\n\t\tItemStack extracted = extractFromInventory(\n\t\t\t\tObjects.requireNonNull(LPNeighborTileEntityKt.getInventoryUtil(adjacentCraftingTable)), wantedItem,\n\t\t\t\tcount);\n\t\tif (!extracted.isEmpty()) {\n\t\t\treturn extracted;\n\t\t}\n\t\tItemStack retStack = ItemStack.EMPTY;\n\t\twhile (count > 0) {\n\t\t\tItemStack stack = adjacentCraftingTable.getTileEntity().getOutput(wantedItem, service);\n\t\t\tif (stack.isEmpty()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (retStack.isEmpty()) {\n\t\t\t\tif (!wantedItem.matches(ItemIdentifier.get(stack), wantedItem instanceof ItemResource ?\n\t\t\t\t\t\tIResource.MatchSettings.WITHOUT_NBT :\n\t\t\t\t\t\tIResource.MatchSettings.NORMAL)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!retStack.isItemEqual(stack)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!ItemStack.areItemStackTagsEqual(retStack, stack)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!service.useEnergy(neededEnergy() * stack.getCount())) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (retStack.isEmpty()) {\n\t\t\t\tretStack = stack;\n\t\t\t} else {\n\t\t\t\tretStack.grow(stack.getCount());\n\t\t\t}\n\t\t\tcount -= stack.getCount();\n\t\t\tif (Objects.requireNonNull(getUpgradeManager()).isFuzzyUpgrade()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn retStack;\n\t}\n\n\tprotected int neededEnergy() {\n\t\treturn (int) (10 * Math.pow(1.1, getUpgradeManager().getItemExtractionUpgrade()) * Math\n\t\t\t\t.pow(1.2, getUpgradeManager().getItemStackExtractionUpgrade()));\n\t}\n\n\tprotected int itemsToExtract() {\n\t\treturn (int) Math.pow(2, getUpgradeManager().getItemExtractionUpgrade());\n\t}\n\n\tprotected int stacksToExtract() {\n\t\treturn 1 + getUpgradeManager().getItemStackExtractionUpgrade();\n\t}\n\n\tpublic void importCleanup() {\n\t\tfor (int i = 0; i < 10; i++) {\n\t\t\tfinal ItemIdentifierStack identStack = dummyInventory.getIDStackInSlot(i);\n\t\t\tif (identStack == null) {\n\t\t\t\tcleanupInventory.clearInventorySlotContents(i);\n\t\t\t} else {\n\t\t\t\tcleanupInventory.setInventorySlotContents(i, new ItemIdentifierStack(identStack));\n\t\t\t}\n\t\t}\n\t\tfor (int i = 10; i < cleanupInventory.getSizeInventory(); i++) {\n\t\t\tcleanupInventory.clearInventorySlotContents(i);\n\t\t}\n\t\tcleanupInventory.getSlotAccess().compactFirst(10);\n\t\tcleanupInventory.recheckStackLimit();\n\t\tcleanupModeIsExclude.setValue(false);\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\t// TODO Auto-generated method stub\n\t\treturn null;\n\t}\n\n\tprivate void updateSatellitesOnClient() {\n\t\tMainProxy.sendToPlayerList(getCPipePacket(), guiWatcher);\n\t}\n\n\tpublic void setSatelliteUUID(@Nullable UUID pipeID) {\n\t\tif (pipeID == null) {\n\t\t\tsatelliteUUID.zero();\n\t\t} else {\n\t\t\tsatelliteUUID.setValue(pipeID);\n\t\t}\n\t\tupdateSatellitesOnClient();\n\t\tupdateSatelliteFromIDs = null;\n\t}\n\n\tpublic void setAdvancedSatelliteUUID(int i, @Nullable UUID pipeID) {\n\t\tif (pipeID == null) {\n\t\t\tadvancedSatelliteUUIDList.zero(i);\n\t\t} else {\n\t\t\tadvancedSatelliteUUIDList.set(i, pipeID);\n\t\t}\n\t\tupdateSatellitesOnClient();\n\t\tupdateSatelliteFromIDs = null;\n\t}\n\n\tpublic void setFluidSatelliteUUID(@Nullable UUID pipeID) {\n\t\tif (pipeID == null) {\n\t\t\tliquidSatelliteUUID.zero();\n\t\t} else {\n\t\t\tliquidSatelliteUUID.setValue(pipeID);\n\t\t}\n\t\tupdateSatellitesOnClient();\n\t\tupdateSatelliteFromIDs = null;\n\t}\n\n\tpublic void setAdvancedFluidSatelliteUUID(int i, @Nullable UUID pipeID) {\n\t\tif (pipeID == null) {\n\t\t\tliquidSatelliteUUIDList.zero(i);\n\t\t} else {\n\t\t\tliquidSatelliteUUIDList.set(i, pipeID);\n\t\t}\n\t\tupdateSatellitesOnClient();\n\t\tupdateSatelliteFromIDs = null;\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tguiWatcher.add(player);\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tguiWatcher.remove(player);\n\t}\n\n\tpublic static class CraftingChassisInformation extends ChassiTargetInformation {\n\n\t\t@Getter\n\t\tprivate final int craftingSlot;\n\n\t\tpublic CraftingChassisInformation(int craftingSlot, int moduleSlot) {\n\t\t\tsuper(moduleSlot);\n\t\t\tthis.craftingSlot = craftingSlot;\n\t\t}\n\t}\n\n\t// FIXME: Remove after 1.12\n\tprivate static class UpgradeSatelliteFromIDs {\n\n\t\tpublic int satelliteId;\n\t\tpublic int[] advancedSatelliteIdArray = new int[9];\n\t\tpublic int[] liquidSatelliteIdArray = new int[ItemUpgrade.MAX_LIQUID_CRAFTER];\n\t\tpublic int liquidSatelliteId;\n\t}\n\n\tpublic static class ClientSideSatelliteNames {\n\n\t\tpublic @Nonnull\n\t\tString satelliteName = \"\";\n\t\tpublic @Nonnull\n\t\tString[] advancedSatelliteNameArray = {};\n\t\tpublic @Nonnull\n\t\tString liquidSatelliteName = \"\";\n\t\tpublic @Nonnull\n\t\tString[] liquidSatelliteNameArray = {};\n\t}\n\n\tpublic boolean hasByproductUpgrade() {\n\t\treturn getUpgradeManager().hasByproductExtractor();\n\t}\n\n\tpublic boolean hasFuzzyUpgrade() { return getUpgradeManager().isFuzzyUpgrade(); }\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleCreativeTabBasedItemSink.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.gui.hud.modules.HUDStringBasedItemSink;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.interfaces.IWorldProvider;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inhand.StringBasedItemSinkModuleGuiInHand;\nimport logisticspipes.network.guis.module.inpipe.StringBasedItemSinkModuleGuiSlot;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleBasedItemSinkList;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.StringListProperty;\n\npublic class ModuleCreativeTabBasedItemSink extends LogisticsModule\n\t\timplements IStringBasedModule, IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver, Gui {\n\n\tpublic final StringListProperty tabList = new StringListProperty(\"\");\n\n\tprivate final IHUDModuleRenderer HUD = new HUDStringBasedItemSink(this);\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\n\tprivate SinkReply _sinkReply;\n\n\tpublic static String getName() {\n\t\treturn \"item_sink_creativetab\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(tabList);\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.ModBasedItemSink, 0, true, false, 5, 0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tif (tabList.contains(item.getCreativeTabName())) {\n\t\t\tif (service.canUseEnergy(5)) {\n\t\t\t\treturn _sinkReply;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\t// deprecated, TODO: remove after 1.12\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tfinal String key = \"Mod\" + i;\n\t\t\tif (tag.hasKey(key)) {\n\t\t\t\tfinal String val = tag.getString(key);\n\t\t\t\tif (!val.isEmpty()) tabList.set(i, val);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Mods: \");\n\t\tlist.addAll(tabList);\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\twriteToNBT(nbt);\n\t\tMainProxy.sendPacketToPlayer(\n\t\t\t\tPacketHandler.getPacket(ModuleBasedItemSinkList.class).setNbt(nbt).setModulePos(this), player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void listChanged() {\n\t\tfinal IWorldProvider worldProvider = _world;\n\t\tif (worldProvider == null) return;\n\t\tif (MainProxy.isServer(worldProvider.getWorld())) {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\twriteToNBT(nbt);\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\tPacketHandler.getPacket(ModuleBasedItemSinkList.class).setNbt(nbt).setModulePos(this),\n\t\t\t\t\tlocalModeWatchers);\n\t\t} else {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\twriteToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPacketHandler.getPacket(ModuleBasedItemSinkList.class).setNbt(nbt).setModulePos(this));\n\t\t}\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic StringListProperty stringListProperty() {\n\t\treturn tabList;\n\t}\n\n\t@Override\n\tpublic String getStringForItem(ItemIdentifier ident) {\n\t\treturn ident.getCreativeTabName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\twriteToNBT(nbt);\n\t\treturn NewGuiHandler.getGui(StringBasedItemSinkModuleGuiSlot.class).setNbt(nbt);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(StringBasedItemSinkModuleGuiInHand.class);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleEnchantmentSink.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.Collections;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.property.Property;\n\npublic class ModuleEnchantmentSink extends LogisticsModule {\n\n\tprivate SinkReply _sinkReply;\n\n\tpublic static String getName() {\n\t\treturn \"enchantment_sink\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@NotNull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.EnchantmentItemSink,\n\t\t\t\t0,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t\t1,\n\t\t\t\t0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\t// check to see if a better route is already found\n\t\t// Note: Higher MKs are higher priority\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\n\t\t//check to see if item is enchanted\n\t\tif (stack.isItemEnchanted()) {\n\t\t\treturn _sinkReply;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\t/*\n\t * We will check every item return true\n\t * @see logisticspipes.modules.LogisticsModule#hasGenericInterests()\n\t */\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean hasEffect() {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleEnchantmentSinkMK2.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.gui.hud.modules.HUDSimpleFilterModule;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleInventory;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SimpleFilter;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\n\n@CCType(name = \"EnchantmentSink Module MK2\")\npublic class ModuleEnchantmentSinkMK2 extends LogisticsModule\n\t\timplements SimpleFilter, IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver,\n\t\tISimpleInventoryEventHandler, IModuleInventoryReceive, Gui {\n\n\tpublic final ItemIdentifierInventoryProperty filterInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(9, \"Requested Enchanted items\", 1), \"\");\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final IHUDModuleRenderer HUD = new HUDSimpleFilterModule(this);\n\tprivate SinkReply _sinkReply;\n\n\tpublic ModuleEnchantmentSinkMK2() {\n\t\tfilterInventory.addListener(this);\n\t}\n\n\tpublic static String getName() {\n\t\treturn \"enchantment_sink_mk2\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(filterInventory);\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the FilterInventory of this Module\")\n\t@Nonnull\n\tpublic IItemIdentifierInventory getFilterInventory() {\n\t\treturn filterInventory;\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.EnchantmentItemSink, 1, true, false, 1, 0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tif (filterInventory.containsExcludeNBTItem(item.getUndamaged().getIgnoringNBT())) {\n\t\t\tif (stack.isItemEnchanted()) {\n\t\t\t\treturn _sinkReply;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Filter: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(filterInventory)).setModulePos(this), player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tMainProxy.runOnServer(getWorld(), () -> () ->\n\t\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\t\tPacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(inventory))\n\t\t\t\t\t\t\t\t.setModulePos(this),\n\t\t\t\t\t\tlocalModeWatchers\n\t\t\t\t)\n\t\t);\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void handleInvContent(@Nonnull Collection<ItemIdentifierStack> list) {\n\t\tfilterInventory.handleItemIdentifierList(list);\n\t}\n\n\t@Override\n\t/*\n\t * (non-Javadoc)\n\t * @see logisticspipes.modules.LogisticsModule#hasGenericInterests()\n\t * Only looking for items in filter\n\t */\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tMap<ItemIdentifier, Integer> mapIC = filterInventory.getItemsAndCount();\n\t\titemIdentifiers.addAll(mapIC.keySet());\n\t\tfor (ItemIdentifier id : mapIC.keySet()) {\n\t\t\titemIdentifiers.add(id.getUndamaged());\n\t\t\titemIdentifiers.add(id.getUndamaged().getIgnoringNBT());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean hasEffect() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn SimpleFilter.getPipeGuiProvider();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn SimpleFilter.getInHandGuiProvider();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleFluidSupplier.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inpipe.FluidSupplierSlot;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\n\npublic class ModuleFluidSupplier extends LogisticsModule implements IClientInformationProvider, Gui {\n\n\tprivate final ItemIdentifierInventoryProperty filterInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(9, \"Requested liquids\", 1), \"\");\n\n\tprivate SinkReply _sinkReply;\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\tthrow new RuntimeException(\"Cannot get LP name for \" + this);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(filterInventory);\n\t}\n\n\t@Nonnull\n\tpublic IInventory getFilterInventory() {\n\t\treturn filterInventory;\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.ItemSink,\n\t\t\t\t0,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal()\n\t\t\t\t|| (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tif (filterInventory.containsItem(item)) {\n\t\t\tservice.spawnParticle(Particles.VioletParticle, 2);\n\t\t\treturn _sinkReply;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Supplied: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn NewGuiHandler.getGui(FluidSupplierSlot.class);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\tthrow new UnsupportedOperationException(\"Fluid Supplier GUI cannot be opened in hand\");\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleItemSink.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport com.google.common.collect.ImmutableList;\nimport org.jetbrains.annotations.NotNull;\n\nimport logisticspipes.gui.hud.modules.HUDItemSink;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inhand.ItemSinkInHand;\nimport logisticspipes.network.guis.module.inpipe.ItemSinkSlot;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleInventory;\nimport logisticspipes.network.packets.modules.ItemSinkDefault;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SimpleFilter;\nimport network.rs485.logisticspipes.property.BitSetProperty;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.IBitSet;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.util.FuzzyFlag;\nimport network.rs485.logisticspipes.util.FuzzyUtil;\n\n@CCType(name = \"ItemSink Module\")\npublic class ModuleItemSink extends LogisticsModule\n\timplements SimpleFilter, IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver,\n\tISimpleInventoryEventHandler, IModuleInventoryReceive, Gui {\n\n\tpublic final ItemIdentifierInventoryProperty filterInventory = new ItemIdentifierInventoryProperty(\n\t\tnew ItemIdentifierInventory(9, \"Requested items\", 1), \"\");\n\tpublic final BooleanProperty defaultRoute = new BooleanProperty(false, \"defaultdestination\");\n\n\tpublic final BitSetProperty fuzzyFlags = new BitSetProperty(\n\t\tnew BitSet(filterInventory.getSizeInventory() * 4), \"fuzzyFlags\");\n\n\tprivate final List<Property<?>> properties = ImmutableList.<Property<?>>builder()\n\t\t.add(filterInventory)\n\t\t.add(defaultRoute)\n\t\t.add(fuzzyFlags)\n\t\t.build();\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final IHUDModuleRenderer HUD = new HUDItemSink(this);\n\tprivate SinkReply _sinkReply;\n\tprivate SinkReply _sinkReplyDefault;\n\n\tpublic ModuleItemSink() {\n\t\tfilterInventory.addListener(this);\n\t}\n\n\tpublic static String getName() {\n\t\treturn \"item_sink\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn properties;\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the FilterInventory of this Module\")\n\t@Nonnull\n\tpublic IItemIdentifierInventory getFilterInventory() {\n\t\treturn filterInventory;\n\t}\n\n\t@CCCommand(description = \"Returns true if the module is a default route\")\n\tpublic boolean isDefaultRoute() {\n\t\treturn defaultRoute.getValue();\n\t}\n\n\t@CCCommand(description = \"Sets the default route status of this module\")\n\tpublic void setDefaultRoute(Boolean isDefaultRoute) {\n\t\tdefaultRoute.setValue(isDefaultRoute);\n\t\tif (!localModeWatchers.isEmpty()) {\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\tPacketHandler.getPacket(ItemSinkDefault.class).setFlag(isDefaultRoute).setModulePos(this),\n\t\t\t\tlocalModeWatchers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.ItemSink, 0, true, false, 1, 0,\n\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t\t_sinkReplyDefault = new SinkReply(FixedPriority.DefaultRoute, 0, true, true, 1, 0,\n\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\tpublic Stream<ItemIdentifier> getAdjacentInventoriesItems() {\n\t\treturn Objects.requireNonNull(_service)\n\t\t\t.getAvailableAdjacent()\n\t\t\t.inventories()\n\t\t\t.stream()\n\t\t\t.map(LPNeighborTileEntityKt::getInventoryUtil)\n\t\t\t.filter(Objects::nonNull)\n\t\t\t.flatMap(invUtil -> invUtil.getItems().stream())\n\t\t\t.distinct();\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (defaultRoute.getValue() && !allowDefault) {\n\t\t\treturn null;\n\t\t}\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tif (filterInventory.containsUndamagedItem(item.getUndamaged())) {\n\t\t\tif (service.canUseEnergy(1)) {\n\t\t\t\treturn _sinkReply;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tfinal ISlotUpgradeManager upgradeManager = getUpgradeManager();\n\t\tif (upgradeManager.isFuzzyUpgrade()) {\n\t\t\tfor (Pair<ItemIdentifierStack, Integer> filter : filterInventory.contents()) {\n\t\t\t\tif (filter == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (filter.getValue1() == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tItemIdentifier ident1 = item;\n\t\t\t\tItemIdentifier ident2 = filter.getValue1().getItem();\n\t\t\t\tIBitSet slotFlags = getSlotFuzzyFlags(filter.getValue2());\n\t\t\t\tif (FuzzyUtil.INSTANCE.get(slotFlags, FuzzyFlag.IGNORE_DAMAGE)) {\n\t\t\t\t\tident1 = ident1.getIgnoringData();\n\t\t\t\t\tident2 = ident2.getIgnoringData();\n\t\t\t\t}\n\t\t\t\tif (FuzzyUtil.INSTANCE.get(slotFlags, FuzzyFlag.IGNORE_NBT)) {\n\t\t\t\t\tident1 = ident1.getIgnoringNBT();\n\t\t\t\t\tident2 = ident2.getIgnoringNBT();\n\t\t\t\t}\n\t\t\t\tif (ident1.equals(ident2)) {\n\t\t\t\t\tif (service.canUseEnergy(5)) {\n\t\t\t\t\t\treturn _sinkReply;\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (defaultRoute.getValue()) {\n\t\t\tif (bestPriority > _sinkReplyDefault.fixedPriority.ordinal() || (\n\t\t\t\tbestPriority == _sinkReplyDefault.fixedPriority.ordinal()\n\t\t\t\t\t&& bestCustomPriority >= _sinkReplyDefault.customPriority)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (service.canUseEnergy(1)) {\n\t\t\t\treturn _sinkReplyDefault;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Default: \" + (isDefaultRoute() ? \"Yes\" : \"No\"));\n\t\tlist.add(\"Filter: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ModuleInventory.class)\n\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(filterInventory)).setModulePos(this), player);\n\t\tMainProxy.sendPacketToPlayer(\n\t\t\tPacketHandler.getPacket(ItemSinkDefault.class).setFlag(defaultRoute.getValue()).setModulePos(this), player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tMainProxy.runOnServer(getWorld(), () -> () ->\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\tPacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(inventory))\n\t\t\t\t\t.setModulePos(this),\n\t\t\t\tlocalModeWatchers\n\t\t\t)\n\t\t);\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void handleInvContent(@Nonnull Collection<ItemIdentifierStack> list) {\n\t\tfilterInventory.handleItemIdentifierList(list);\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn defaultRoute.getValue();\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tif (defaultRoute.getValue()) {\n\t\t\treturn;\n\t\t}\n\t\tMap<ItemIdentifier, Integer> mapIC = filterInventory.getItemsAndCount();\n\t\titemIdentifiers.addAll(mapIC.keySet());\n\t\tmapIC.keySet().stream().map(ItemIdentifier::getUndamaged).forEach(itemIdentifiers::add);\n\t\tif (getUpgradeManager().isFuzzyUpgrade()) {\n\t\t\tfor (Pair<ItemIdentifierStack, Integer> stack : filterInventory.contents()) {\n\t\t\t\tif (stack.getValue1() == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tItemIdentifier ident = stack.getValue1().getItem();\n\t\t\t\tIBitSet slotFlags = getSlotFuzzyFlags(stack.getValue2());\n\t\t\t\tif (FuzzyUtil.INSTANCE.get(slotFlags, FuzzyFlag.IGNORE_DAMAGE)) {\n\t\t\t\t\titemIdentifiers.add(ident.getIgnoringData());\n\t\t\t\t}\n\t\t\t\tif (FuzzyUtil.INSTANCE.get(slotFlags, FuzzyFlag.IGNORE_NBT)) {\n\t\t\t\t\titemIdentifiers.add(ident.getIgnoringNBT());\n\t\t\t\t}\n\t\t\t\tif (FuzzyUtil.INSTANCE.get(slotFlags, FuzzyFlag.IGNORE_DAMAGE) && FuzzyUtil.INSTANCE.get(slotFlags, FuzzyFlag.IGNORE_NBT)) {\n\t\t\t\t\titemIdentifiers.add(ident.getIgnoringData().getIgnoringNBT());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t\t// when we are default we are interested in everything anyway, otherwise we're only interested in our filter.\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\tpublic void setFuzzyFlags(BitSet fuzzyFlags) {\n\t\tthis.fuzzyFlags.replaceWith(fuzzyFlags);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ItemSinkSlot.class).setDefaultRoute(defaultRoute.getValue())\n\t\t\t.setFuzzyFlags(fuzzyFlags.copyValue()).setHasFuzzyUpgrade(getUpgradeManager().isFuzzyUpgrade());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ItemSinkInHand.class);\n\t}\n\n\tpublic IBitSet getSlotFuzzyFlags(int slotId) {\n\t\tfinal int startBit = slotId * 4;\n\t\treturn fuzzyFlags.get(startBit, startBit + 3);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@NotNull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\n\t\t// FIXME: remove after 1.12\n\t\tif (!tag.hasKey(\"fuzzyFlags\") && tag.hasKey(\"ignoreData\") && tag.hasKey(\"ignoreNBT\")) {\n\t\t\tBitSet ignoreData = BitSet.valueOf(tag.getByteArray(\"ignoreData\"));\n\t\t\tBitSet ignoreNBT = BitSet.valueOf(tag.getByteArray(\"ignoreNBT\"));\n\t\t\tfor (int i = 0; i < filterInventory.getSizeInventory(); i++) {\n\t\t\t\tif (i < ignoreData.size()) {\n\t\t\t\t\tfuzzyFlags.set(i * 4 + FuzzyFlag.IGNORE_DAMAGE.getBit(), ignoreData.get(i));\n\t\t\t\t}\n\t\t\t\tif (i < ignoreNBT.size()) {\n\t\t\t\t\tfuzzyFlags.set(i * 4 + FuzzyFlag.IGNORE_NBT.getBit(), ignoreNBT.get(i));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleModBasedItemSink.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.gui.hud.modules.HUDStringBasedItemSink;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.interfaces.IWorldProvider;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inhand.StringBasedItemSinkModuleGuiInHand;\nimport logisticspipes.network.guis.module.inpipe.StringBasedItemSinkModuleGuiSlot;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleBasedItemSinkList;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.StringListProperty;\n\npublic class ModuleModBasedItemSink extends LogisticsModule\n\t\timplements IStringBasedModule, IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver, Gui {\n\n\tpublic final StringListProperty modList = new StringListProperty(\"\");\n\n\tprivate final IHUDModuleRenderer HUD = new HUDStringBasedItemSink(this);\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\n\tprivate SinkReply _sinkReply;\n\n\tpublic static String getName() {\n\t\treturn \"item_sink_mod\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(modList);\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.ModBasedItemSink, 0, true, false, 5, 0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tif (modList.contains(item.getModName())) {\n\t\t\tif (service.canUseEnergy(5)) {\n\t\t\t\treturn _sinkReply;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\t// deprecated, TODO: remove after 1.12\n\t\tfor (int i = 0; i < modList.size(); i++) {\n\t\t\tfinal String key = \"Mod\" + i;\n\t\t\tif (tag.hasKey(key)) {\n\t\t\t\tfinal String val = tag.getString(key);\n\t\t\t\tif (!val.isEmpty()) modList.set(i, val);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Mods: \");\n\t\tlist.addAll(modList);\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\twriteToNBT(nbt);\n\t\tMainProxy.sendPacketToPlayer(\n\t\t\t\tPacketHandler.getPacket(ModuleBasedItemSinkList.class).setNbt(nbt).setModulePos(this), player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void listChanged() {\n\t\tfinal IWorldProvider worldProvider = _world;\n\t\tif (worldProvider == null) return;\n\t\tif (MainProxy.isServer(worldProvider.getWorld())) {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\twriteToNBT(nbt);\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\tPacketHandler.getPacket(ModuleBasedItemSinkList.class).setNbt(nbt).setModulePos(this),\n\t\t\t\t\tlocalModeWatchers);\n\t\t} else {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\twriteToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPacketHandler.getPacket(ModuleBasedItemSinkList.class).setNbt(nbt).setModulePos(this));\n\t\t}\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic StringListProperty stringListProperty() {\n\t\treturn modList;\n\t}\n\n\t@Override\n\tpublic String getStringForItem(ItemIdentifier ident) {\n\t\treturn ident.getModName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\twriteToNBT(nbt);\n\t\treturn NewGuiHandler.getGui(StringBasedItemSinkModuleGuiSlot.class).setNbt(nbt);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(StringBasedItemSinkModuleGuiInHand.class);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleOreDictItemSink.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport logisticspipes.gui.hud.modules.HUDOreDictItemSink;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inhand.OreDictItemSinkModuleInHand;\nimport logisticspipes.network.guis.module.inpipe.OreDictItemSinkModuleSlot;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.OreDictItemSinkList;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.StringListProperty;\n\npublic class ModuleOreDictItemSink extends LogisticsModule\n\t\timplements IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver, Gui {\n\n\tpublic final StringListProperty oreList = new StringListProperty(\"\");\n\n\t//map of Item:<set of damagevalues>, empty set if wildcard damage\n\tprivate Map<Item, Set<Integer>> oreItemIdMap;\n\n\tprivate final IHUDModuleRenderer HUD = new HUDOreDictItemSink(this);\n\tprivate List<ItemIdentifierStack> oreHudList;\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\n\tprivate SinkReply _sinkReply;\n\n\tpublic static String getName() {\n\t\treturn \"item_sink_oredict\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(oreList);\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.OreDictItemSink,\n\t\t\t\t0,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t\t5,\n\t\t\t\t0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority, boolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal() && bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tif (oreItemIdMap == null) {\n\t\t\tbuildOreItemIdMap();\n\t\t}\n\t\tSet<Integer> damageSet = oreItemIdMap.get(item.item);\n\t\tif (damageSet == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (damageSet.isEmpty() || damageSet.contains(item.itemDamage)) {\n\t\t\treturn _sinkReply;\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic List<ItemIdentifierStack> getHudItemList() {\n\t\tif (oreItemIdMap == null) {\n\t\t\tbuildOreItemIdMap();\n\t\t}\n\t\treturn oreHudList;\n\t}\n\n\tprivate void buildOreItemIdMap() {\n\t\toreItemIdMap = new HashMap<>();\n\t\toreHudList = new ArrayList<>(oreList.size());\n\t\tfor (String orename : oreList) {\n\t\t\tList<ItemStack> items = OreDictionary.getOres(orename);\n\t\t\tItemStack stackForHud = ItemStack.EMPTY;\n\t\t\tfor (ItemStack stack : items) {\n\t\t\t\tif (stackForHud.isEmpty()) {\n\t\t\t\t\tstackForHud = stack;\n\t\t\t\t}\n\t\t\t\tif (stack.getItemDamage() == OreDictionary.WILDCARD_VALUE) {\n\t\t\t\t\toreItemIdMap.put(stack.getItem(), new TreeSet<>());\n\t\t\t\t} else {\n\t\t\t\t\tSet<Integer> damageSet = oreItemIdMap.get(stack.getItem());\n\t\t\t\t\tif (damageSet == null) {\n\t\t\t\t\t\tdamageSet = new TreeSet<>();\n\t\t\t\t\t\tdamageSet.add(stack.getItemDamage());\n\t\t\t\t\t\toreItemIdMap.put(stack.getItem(), damageSet);\n\t\t\t\t\t} else if (!damageSet.isEmpty()) {\n\t\t\t\t\t\tdamageSet.add(stack.getItemDamage());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!stackForHud.isEmpty()) {\n\t\t\t\tItemStack t = stackForHud.copy();\n\t\t\t\tif (t.getItemDamage() == OreDictionary.WILDCARD_VALUE) {\n\t\t\t\t\tt.setItemDamage(0);\n\t\t\t\t}\n\t\t\t\toreHudList.add(new ItemIdentifierStack(ItemIdentifier.get(t), 1));\n\t\t\t} else {\n\t\t\t\toreHudList.add(new ItemIdentifierStack(ItemIdentifier.get(Item.getItemFromBlock(Blocks.FIRE), 0, null), 1));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\t// deprecated, TODO: remove after 1.12\n\t\tfor (int i = 0; i < oreList.size(); i++) {\n\t\t\tfinal String key = \"Ore\" + i;\n\t\t\tif (tag.hasKey(key)) {\n\t\t\t\tfinal String val = tag.getString(key);\n\t\t\t\tif (!val.isEmpty()) oreList.set(i, val);\n\t\t\t}\n\t\t}\n\t\toreItemIdMap = null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull List<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Ores: \");\n\t\tlist.addAll(oreList);\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\twriteToNBT(nbt);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OreDictItemSinkList.class).setTag(nbt).setModulePos(this), player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\tpublic void OreListChanged() {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\twriteToNBT(nbt);\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(OreDictItemSinkList.class).setTag(nbt).setModulePos(this), localModeWatchers);\n\t\t} else {\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\twriteToNBT(nbt);\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(OreDictItemSinkList.class).setTag(nbt).setModulePos(this));\n\t\t}\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\twriteToNBT(nbt);\n\t\treturn NewGuiHandler.getGui(OreDictItemSinkModuleSlot.class).setNbt(nbt);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(OreDictItemSinkModuleInHand.class);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModulePassiveSupplier.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.gui.hud.modules.HUDSimpleFilterModule;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleInventory;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.PipeServiceProviderUtilKt;\nimport network.rs485.logisticspipes.module.SimpleFilter;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\n\npublic class ModulePassiveSupplier extends LogisticsModule\n\t\timplements Gui, SimpleFilter, IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver,\n\t\tIModuleInventoryReceive, ISimpleInventoryEventHandler {\n\n\tpublic final ItemIdentifierInventoryProperty filterInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(9, \"Requested items\", 64), \"\");\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final IHUDModuleRenderer HUD = new HUDSimpleFilterModule(this);\n\tprivate SinkReply _sinkReply;\n\n\tpublic ModulePassiveSupplier() {\n\t\tfilterInventory.addListener(this);\n\t}\n\n\tpublic static String getName() {\n\t\treturn \"passive_supplier\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(filterInventory);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IInventory getFilterInventory() {\n\t\treturn filterInventory;\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.PassiveSupplier, 0, true, false, 2, 0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tfinal ISlotUpgradeManager upgradeManager = service.getUpgradeManager(slot, positionInt);\n\t\tIInventoryUtil targetUtil = PipeServiceProviderUtilKt.availableSneakyInventories(service, upgradeManager)\n\t\t\t\t.stream().findFirst().orElse(null);\n\t\tif (targetUtil == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!filterInventory.containsItem(item)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tint targetCount = filterInventory.itemCount(item);\n\t\tint haveCount = targetUtil.itemCount(item);\n\t\tif (targetCount <= haveCount) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (service.canUseEnergy(2)) {\n\t\t\treturn new SinkReply(_sinkReply, targetCount - haveCount);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Supplied: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(filterInventory)).setModulePos(this), player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void handleInvContent(@Nonnull Collection<ItemIdentifierStack> list) {\n\t\tfilterInventory.handleItemIdentifierList(list);\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tMainProxy.runOnServer(getWorld(), () -> () ->\n\t\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\t\tPacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(filterInventory))\n\t\t\t\t\t\t\t\t.setModulePos(this),\n\t\t\t\t\t\tlocalModeWatchers\n\t\t\t\t)\n\t\t);\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\titemIdentifiers.addAll(filterInventory.getItemsAndCount().keySet());\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn SimpleFilter.getPipeGuiProvider();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn SimpleFilter.getInHandGuiProvider();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModulePolymorphicItemSink.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.Collections;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.module.PipeServiceProviderUtilKt;\nimport network.rs485.logisticspipes.property.Property;\n\npublic class ModulePolymorphicItemSink extends LogisticsModule {\n\n\tprivate SinkReply _sinkReply;\n\n\tpublic static String getName() {\n\t\treturn \"item_sink_polymorphic\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t@NotNull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.ItemSink,\n\t\t\t\t0,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t\t3,\n\t\t\t\t0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tfinal ISlotUpgradeManager upgradeManager = service.getUpgradeManager(slot, positionInt);\n\t\tIInventoryUtil targetInventory = PipeServiceProviderUtilKt.availableSneakyInventories(service, upgradeManager)\n\t\t\t\t.stream().findFirst().orElse(null);\n\t\tif (targetInventory == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (!targetInventory.containsUndamagedItem(item.getUndamaged())) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (service.canUseEnergy(3)) {\n\t\t\treturn _sinkReply;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn true; // by definition :)\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleProvider.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.TreeMap;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport com.google.common.collect.ImmutableList;\n\nimport logisticspipes.gui.hud.modules.HUDProviderModule;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.ILegacyActiveModule;\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.logistics.LogisticsManager;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inhand.ProviderModuleInHand;\nimport logisticspipes.network.guis.module.inpipe.ProviderModuleGuiProvider;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleInventory;\nimport logisticspipes.network.packets.modules.SneakyModuleDirectionUpdate;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe.ItemSendMode;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.routing.order.LogisticsItemOrder;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SneakyDirection;\nimport network.rs485.logisticspipes.property.BooleanProperty;\nimport network.rs485.logisticspipes.property.EnumProperty;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.NullableEnumProperty;\nimport network.rs485.logisticspipes.property.Property;\n\n@CCType(name = \"Provider Module\")\npublic class ModuleProvider extends LogisticsModule implements SneakyDirection, ILegacyActiveModule,\n\t\tIClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver, IModuleInventoryReceive, Gui {\n\n\tpublic final ArrayList<ItemIdentifierStack> displayList = new ArrayList<>();\n\tpublic final ItemIdentifierInventoryProperty filterInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(9, \"Items to provide (or empty for all)\", 1), \"\");\n\tpublic final BooleanProperty isActive = new BooleanProperty(false, \"isActive\");\n\tpublic final BooleanProperty isExclusionFilter = new BooleanProperty(false, \"filterisexclude\");\n\tpublic final EnumProperty<ProviderMode> providerMode =\n\t\t\tnew EnumProperty<>(ProviderMode.DEFAULT, \"extractionMode\", ProviderMode.values());\n\tpublic final NullableEnumProperty<EnumFacing> sneakyDirection =\n\t\t\tnew NullableEnumProperty<>(null, \"sneakydirection\", EnumFacing.values());\n\tpublic final ImmutableList<Property<?>> propertyList = ImmutableList.<Property<?>>builder()\n\t\t\t.add(filterInventory)\n\t\t\t.add(isActive)\n\t\t\t.add(isExclusionFilter)\n\t\t\t.add(providerMode)\n\t\t\t.add(sneakyDirection)\n\t\t\t.build();\n\tprivate final Map<ItemIdentifier, Integer> displayMap = new TreeMap<>();\n\tprivate final ArrayList<ItemIdentifierStack> oldList = new ArrayList<>();\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final IHUDModuleRenderer HUD = new HUDProviderModule(this);\n\n\tpublic ModuleProvider() {}\n\n\tpublic static String getName() {\n\t\treturn \"provider\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\treturn getName();\n\t}\n\n\t/**\n\t * Returns a list of all the properties of this module.\n\t */\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn propertyList;\n\t}\n\n\t@Override\n\tpublic EnumFacing getSneakyDirection() {\n\t\treturn sneakyDirection.getValue();\n\t}\n\n\t@Override\n\tpublic void setSneakyDirection(EnumFacing direction) {\n\t\tsneakyDirection.setValue(direction);\n\t\tMainProxy.runOnServer(getWorld(), () -> () ->\n\t\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\t\tPacketHandler.getPacket(SneakyModuleDirectionUpdate.class)\n\t\t\t\t\t\t\t\t.setDirection(sneakyDirection.getValue())\n\t\t\t\t\t\t\t\t.setModulePos(this),\n\t\t\t\t\t\tlocalModeWatchers\n\t\t\t\t)\n\t\t);\n\t}\n\n\tprotected int neededEnergy() {\n\t\treturn (int) (1 * Math.pow(1.1, getUpgradeManager().getItemExtractionUpgrade()) * Math\n\t\t\t\t.pow(1.2, getUpgradeManager().getItemStackExtractionUpgrade()));\n\t}\n\n\tprotected int itemsToExtract() {\n\t\treturn 8 * (int) Math.pow(2, getUpgradeManager().getItemExtractionUpgrade());\n\t}\n\n\tprotected int stacksToExtract() {\n\t\treturn 1 + getUpgradeManager().getItemStackExtractionUpgrade();\n\t}\n\n\tpublic ItemSendMode itemSendMode() {\n\t\treturn getUpgradeManager().getItemExtractionUpgrade() > 0 ? ItemSendMode.Fast : ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\tif (service.isNthTick(6)) {\n\t\t\tcheckUpdate(null);\n\t\t}\n\t\tint itemsLeft = itemsToExtract();\n\t\tint stacksLeft = stacksToExtract();\n\t\tLogisticsItemOrder firstOrder = null;\n\t\tLogisticsItemOrder order = null;\n\t\twhile (itemsLeft > 0 && stacksLeft > 0 && service.getItemOrderManager().hasOrders(ResourceType.PROVIDER) && (\n\t\t\t\tfirstOrder == null || firstOrder != order)) {\n\t\t\tif (firstOrder == null) {\n\t\t\t\tfirstOrder = order;\n\t\t\t}\n\t\t\torder = service.getItemOrderManager().peekAtTopRequest(ResourceType.PROVIDER);\n\t\t\tint sent = sendStack(order.getResource().stack, itemsLeft, order.getDestination().getRouter().getSimpleID(),\n\t\t\t\t\torder.getInformation());\n\t\t\tif (sent < 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tservice.spawnParticle(Particles.VioletParticle, 3);\n\t\t\tstacksLeft -= 1;\n\t\t\titemsLeft -= sent;\n\t\t}\n\t}\n\n\tpublic boolean filterBlocksItem(ItemIdentifier item) {\n\t\tif (filterInventory.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\t\tboolean isFiltered = filterInventory.containsItem(item);\n\t\treturn isExclusionFilter.getValue() == isFiltered;\n\t}\n\n\t@Override\n\tpublic void onBlockRemoval() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\twhile (service.getItemOrderManager().hasOrders(ResourceType.PROVIDER)) {\n\t\t\tservice.getItemOrderManager().sendFailed();\n\t\t}\n\t}\n\n\t@Nonnull\n\tpublic Stream<IInventoryUtil> inventoriesWithMode() {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return Stream.empty();\n\t\treturn service.getAvailableAdjacent().inventories().stream()\n\t\t\t\t.map(this::getInventoryUtilWithMode)\n\t\t\t\t.filter(Objects::nonNull);\n\t}\n\n\t@Override\n\tpublic void canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filters) {\n\t\tList<ItemIdentifier> possible = new ArrayList<>();\n\t\tif (tree.getRequestType() instanceof ItemResource) {\n\t\t\tpossible.add(((ItemResource) tree.getRequestType()).getItem());\n\t\t} else if (tree.getRequestType() instanceof DictResource) {\n\t\t\tpossible.addAll(\n\t\t\t\t\tinventoriesWithMode()\n\t\t\t\t\t\t\t.map(IInventoryUtil::getItemsAndCount)\n\t\t\t\t\t\t\t.flatMap(inventory -> inventory.keySet().stream())\n\t\t\t\t\t\t\t.filter(item -> tree.getRequestType().matches(item, IResource.MatchSettings.NORMAL))\n\t\t\t\t\t\t\t.collect(Collectors.toList())\n\t\t\t);\n\t\t}\n\t\tfor (ItemIdentifier item : possible) {\n\t\t\tint canProvide = getAvailableItemCount(item);\n\t\t\tcanProvide -= root.getAllPromissesFor((IProvideItems) _service, item);\n\t\t\tcanProvide = Math.min(canProvide, tree.getMissingAmount());\n\t\t\tif (canProvide < 1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tLogisticsPromise promise = new LogisticsPromise(item, canProvide, (IProvideItems) _service,\n\t\t\t\t\tResourceType.PROVIDER);\n\t\t\ttree.addPromise(promise);\n\t\t}\n\t}\n\n\t@Override\n\tpublic LogisticsOrder fullFill(LogisticsPromise promise, IRequestItems destination,\n\t\t\tIAdditionalTargetInformation info) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tservice.spawnParticle(Particles.WhiteParticle, 2);\n\t\treturn service.getItemOrderManager()\n\t\t\t\t.addOrder(new ItemIdentifierStack(promise.item, promise.numberOfItems), destination,\n\t\t\t\t\t\tResourceType.PROVIDER, info);\n\t}\n\n\tprivate int getAvailableItemCount(ItemIdentifier item) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return 0;\n\t\treturn getTotalItemCount(item) - service.getItemOrderManager().totalItemsCountInOrders(item);\n\t}\n\n\t@Override\n\tpublic void getAllItems(Map<ItemIdentifier, Integer> items, List<IFilter> filters) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return;\n\t\titems.putAll(\n\t\t\t\tinventoriesWithMode()\n\t\t\t\t\t\t.map(IInventoryUtil::getItemsAndCount)\n\t\t\t\t\t\t.flatMap(inventory -> inventory.entrySet().stream())\n\t\t\t\t\t\t.filter(item -> {\n\t\t\t\t\t\t\tif (items.containsKey(item.getKey()))\n\t\t\t\t\t\t\t\treturn false; // already provided by any previous module. No comparison of the amount\n\t\t\t\t\t\t\tif (filterBlocksItem(item.getKey())) return false; // skip provider-filtered items\n\t\t\t\t\t\t\tfinal boolean blockedInFilters = filters.stream().anyMatch(\n\t\t\t\t\t\t\t\t\tfilter -> filter.isBlocked() == filter.isFilteredItem(item.getKey().getUndamaged())\n\t\t\t\t\t\t\t\t\t\t\t|| filter.blockProvider()\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn !blockedInFilters; // skip filters-parameter-filtered items\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.map(item ->\n\t\t\t\t\t\t\t\tnew Pair<>(item.getKey(), item.getValue() - service.getItemOrderManager()\n\t\t\t\t\t\t\t\t\t\t.totalItemsCountInOrders(item.getKey()))\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.filter(itemIdentAndRemaining -> itemIdentAndRemaining.getValue2()\n\t\t\t\t\t\t\t\t> 0) // reduce what has been reserved\n\t\t\t\t\t\t.collect(Pair.toMap(Integer::sum)) // sum up the provided amount by the inventories\n\t\t);\n\t}\n\n\t// returns -1 on permanently failed, don't try another stack this tick\n\t// returns 0 on \"unable to do this delivery\"\n\tpublic int sendStack(ItemIdentifierStack stack, int maxCount, int destination, IAdditionalTargetInformation info) {\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return -1;\n\n\t\tItemIdentifier item = stack.getItem();\n\n\t\tIterator<Pair<IInventoryUtil, EnumFacing>> iterator = service.getAvailableAdjacent().inventories().stream()\n\t\t\t\t.flatMap(neighbor -> {\n\t\t\t\t\tfinal IInventoryUtil invUtil = getInventoryUtilWithMode(neighbor);\n\t\t\t\t\tif (invUtil == null) return Stream.empty();\n\t\t\t\t\treturn Stream.of(new Pair<>(invUtil, neighbor.getDirection()));\n\t\t\t\t}).iterator();\n\n\t\twhile (iterator.hasNext()) {\n\t\t\tfinal Pair<IInventoryUtil, EnumFacing> current = iterator.next();\n\t\t\tint available = current.getValue1().itemCount(item);\n\t\t\tif (available == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tint wanted = Math.min(available, stack.getStackSize());\n\t\t\twanted = Math.min(wanted, maxCount);\n\t\t\twanted = Math.min(wanted, item.getMaxStackSize());\n\t\t\tIRouter dRtr = SimpleServiceLocator.routerManager.getServerRouter(destination);\n\t\t\tif (dRtr == null) {\n\t\t\t\tservice.getItemOrderManager().sendFailed();\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tSinkReply reply = LogisticsManager\n\t\t\t\t\t.canSink(stack.makeNormalStack(), dRtr, null, true, stack.getItem(), null, true, false);\n\t\t\tboolean deferSend = false;\n\t\t\tif (reply != null) {// some pipes are not aware of the space in the adjacent inventory, so they return null\n\t\t\t\tif (reply.maxNumberOfItems < wanted) {\n\t\t\t\t\twanted = reply.maxNumberOfItems;\n\t\t\t\t\tif (wanted <= 0) {\n\t\t\t\t\t\tservice.getItemOrderManager().deferSend();\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\t\t\t\t\tdeferSend = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!service.canUseEnergy(wanted * neededEnergy())) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tItemStack removed = current.getValue1().getMultipleItems(item, wanted);\n\t\t\tif (removed.isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint sent = removed.getCount();\n\t\t\tservice.useEnergy(sent * neededEnergy());\n\n\t\t\tfinal IRoutedItem routedItem = service\n\t\t\t\t\t.sendStack(removed, destination, itemSendMode(), info, current.getValue2());\n\t\t\tservice.getItemOrderManager().sendSuccessfull(sent, deferSend, routedItem);\n\t\t\treturn sent;\n\t\t}\n\n\t\tservice.getItemOrderManager().sendFailed();\n\t\treturn 0;\n\t}\n\n\tpublic int getTotalItemCount(final ItemIdentifier item) {\n\t\tif (filterBlocksItem(item)) return 0;\n\t\treturn inventoriesWithMode().map(invUtil -> invUtil.itemCount(item)).reduce(Integer::sum).orElse(0);\n\t}\n\n\t/*** GUI STUFF ***/\n\n\t@CCCommand(description = \"Returns the FilterInventory of this Module\")\n\tpublic IItemIdentifierInventory getFilterInventory() {\n\t\treturn filterInventory;\n\t}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(!(boolean) isExclusionFilter.getValue() ? \"Included\" : \"Excluded\");\n\t\tlist.add(\"Mode: \" + providerMode.getValue().name());\n\t\tlist.add(\"Filter: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\tprivate void checkUpdate(EntityPlayer player) {\n\t\tif (localModeWatchers.size() == 0 && player == null) {\n\t\t\treturn;\n\t\t}\n\t\tdisplayList.clear();\n\t\tdisplayMap.clear();\n\t\tgetAllItems(displayMap, new ArrayList<>(0));\n\t\tdisplayList.ensureCapacity(displayMap.size());\n\t\tdisplayList.addAll(displayMap.entrySet().stream()\n\t\t\t\t.map(item -> new ItemIdentifierStack(item.getKey(), item.getValue()))\n\t\t\t\t.collect(Collectors.toList()));\n\t\tif (!oldList.equals(displayList)) {\n\t\t\toldList.clear();\n\t\t\toldList.ensureCapacity(displayList.size());\n\t\t\toldList.addAll(displayList);\n\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\tPacketHandler.getPacket(ModuleInventory.class).setIdentList(displayList).setModulePos(this)\n\t\t\t\t\t\t\t.setCompressable(true), localModeWatchers);\n\t\t} else if (player != null) {\n\t\t\tMainProxy.sendPacketToPlayer(\n\t\t\t\t\tPacketHandler.getPacket(ModuleInventory.class).setIdentList(displayList).setModulePos(this)\n\t\t\t\t\t\t\t.setCompressable(true), player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tcheckUpdate(player);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void handleInvContent(@Nonnull Collection<ItemIdentifierStack> list) {\n\t\tdisplayList.clear();\n\t\tdisplayList.addAll(list);\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\t//when filter is empty or in exclude mode, this is interested in attached inventory already\n\t\tif (!isExclusionFilter.getValue() && !filterInventory.isEmpty()) {\n\t\t\t// when items included this is only interested in items in the filter\n\t\t\titemIdentifiers.addAll(filterInventory.getItemsAndCount().keySet());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\t// when items included this is only interested in items in the filter\n\t\treturn isExclusionFilter.getValue() || filterInventory.isEmpty();\n\t\t// when items not included, we can only serve those items in the filter.\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ProviderModuleGuiProvider.class).setExtractorMode(providerMode.getValue().ordinal())\n\t\t\t\t.setExclude(isExclusionFilter.getValue());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn NewGuiHandler.getGui(ProviderModuleInHand.class);\n\t}\n\n\tprivate IInventoryUtil getInventoryUtilWithMode(NeighborTileEntity<TileEntity> neighbor) {\n\t\treturn SimpleServiceLocator.inventoryUtilFactory\n\t\t\t\t.getHidingInventoryUtil(neighbor.getTileEntity(), neighbor.getOurDirection(), providerMode.getValue());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleSatellite.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.property.Property;\n\npublic class ModuleSatellite extends LogisticsModule {\n\n\tprivate final SinkReply _sinkReply = new SinkReply(FixedPriority.ItemSink, 0, true, false, 1, 0, null);\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() {\n\t\tthrow new RuntimeException(\"Cannot get LP name for \" + this);\n\t}\n\n\t@NotNull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal int itemCount = spaceFor(stack, item, includeInTransit);\n\t\tif (itemCount > 0) {\n\t\t\treturn new SinkReply(_sinkReply, itemCount);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate int spaceFor(@Nonnull ItemStack stack, ItemIdentifier item, boolean includeInTransit) {\n\t\tfinal IPipeServiceProvider service = Objects.requireNonNull(_service);\n\t\tint count = service.getAvailableAdjacent().inventories().stream()\n\t\t\t\t.map(neighbor -> LPNeighborTileEntityKt.sneakyInsertion(neighbor).from(getUpgradeManager()))\n\t\t\t\t.map(LPNeighborTileEntityKt::getInventoryUtil)\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.map(util -> util.roomForItem(stack))\n\t\t\t\t.reduce(Integer::sum).orElse(0);\n\t\tif (includeInTransit) {\n\t\t\tcount -= service.countOnRoute(item);\n\t\t}\n\t\treturn count;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t\t// when we are default we are interested in everything anyway, otherwise we're only interested in our filter.\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/modules/ModuleTerminus.java",
    "content": "package logisticspipes.modules;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.gui.hud.modules.HUDSimpleFilterModule;\nimport logisticspipes.interfaces.IClientInformationProvider;\nimport logisticspipes.interfaces.IHUDModuleHandler;\nimport logisticspipes.interfaces.IHUDModuleRenderer;\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.interfaces.IPipeServiceProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket;\nimport logisticspipes.network.packets.module.ModuleInventory;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.SinkReply;\nimport logisticspipes.utils.SinkReply.FixedPriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SimpleFilter;\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty;\nimport network.rs485.logisticspipes.property.Property;\n\n@CCType(name = \"Terminus Module\")\npublic class ModuleTerminus extends LogisticsModule\n\t\timplements SimpleFilter, IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver,\n\t\tISimpleInventoryEventHandler, IModuleInventoryReceive, Gui {\n\n\tpublic final ItemIdentifierInventoryProperty filterInventory = new ItemIdentifierInventoryProperty(\n\t\t\tnew ItemIdentifierInventory(9, \"Terminated items\", 1), \"\");\n\n\tprivate final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final IHUDModuleRenderer HUD = new HUDSimpleFilterModule(this);\n\tprivate SinkReply _sinkReply;\n\n\tpublic ModuleTerminus() {\n\t\tfilterInventory.addListener(this);\n\t}\n\n\tpublic static String getName() {\n\t\treturn \"terminus\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getLPName() { return getName(); }\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn Collections.singletonList(filterInventory);\n\t}\n\n\t@Override\n\t@CCCommand(description = \"Returns the FilterInventory of this Module\")\n\t@Nonnull\n\tpublic IItemIdentifierInventory getFilterInventory() {\n\t\treturn filterInventory;\n\t}\n\n\t@Override\n\tpublic void registerPosition(@Nonnull ModulePositionType slot, int positionInt) {\n\t\tsuper.registerPosition(slot, positionInt);\n\t\t_sinkReply = new SinkReply(FixedPriority.Terminus, 0, true, false, 2, 0,\n\t\t\t\tnew ChassiTargetInformation(getPositionInt()));\n\t}\n\n\t@Override\n\tpublic SinkReply sinksItem(@Nonnull ItemStack stack, ItemIdentifier item, int bestPriority, int bestCustomPriority,\n\t\t\tboolean allowDefault, boolean includeInTransit, boolean forcePassive) {\n\t\tif (bestPriority > _sinkReply.fixedPriority.ordinal() || (bestPriority == _sinkReply.fixedPriority.ordinal()\n\t\t\t\t&& bestCustomPriority >= _sinkReply.customPriority)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal IPipeServiceProvider service = _service;\n\t\tif (service == null) return null;\n\t\tif (filterInventory.containsUndamagedItem(item.getUndamaged())) {\n\t\t\tif (service.canUseEnergy(2)) {\n\t\t\t\treturn _sinkReply;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void tick() {}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\tList<String> list = new ArrayList<>();\n\t\tlist.add(\"Terminated: \");\n\t\tlist.add(\"<inventory>\");\n\t\tlist.add(\"<that>\");\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void startHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic void stopHUDWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopModuleWatchingPacket.class).setModulePos(this));\n\t}\n\n\t@Override\n\tpublic IHUDModuleRenderer getHUDRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void startWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.add(player);\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(filterInventory)).setModulePos(this),\n\t\t\t\tlocalModeWatchers);\n\t}\n\n\t@Override\n\tpublic void stopWatching(EntityPlayer player) {\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tMainProxy.runOnServer(getWorld(), () -> () ->\n\t\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\t\tPacketHandler.getPacket(ModuleInventory.class)\n\t\t\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(inventory))\n\t\t\t\t\t\t\t\t.setModulePos(this),\n\t\t\t\t\t\tlocalModeWatchers\n\t\t\t\t)\n\t\t);\n\t}\n\n\t@Override\n\tpublic void handleInvContent(@Nonnull Collection<ItemIdentifierStack> list) {\n\t\tfilterInventory.handleItemIdentifierList(list);\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tSet<ItemIdentifier> filterItemIds = filterInventory.getItemsAndCount().keySet();\n\t\titemIdentifiers.addAll(filterItemIds);\n\t\tfilterItemIds.stream().map(ItemIdentifier::getUndamaged).forEach(itemIdentifiers::add);\n\t}\n\n\t@Override\n\tpublic boolean interestedInAttachedInventory() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean interestedInUndamagedID() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean receivePassive() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleCoordinatesGuiProvider getPipeGuiProvider() {\n\t\treturn SimpleFilter.getPipeGuiProvider();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ModuleInHandGuiProvider getInHandGuiProvider() {\n\t\treturn SimpleFilter.getInHandGuiProvider();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/GuiHandler.java",
    "content": "package logisticspipes.network;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.common.network.IGuiHandler;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.gui.GuiFirewall;\nimport logisticspipes.gui.GuiFluidBasic;\nimport logisticspipes.gui.GuiFluidSupplierMk2Pipe;\nimport logisticspipes.gui.GuiFluidSupplierPipe;\nimport logisticspipes.gui.GuiFluidTerminus;\nimport logisticspipes.gui.GuiFreqCardContent;\nimport logisticspipes.gui.GuiSatellitePipe;\nimport logisticspipes.gui.hud.GuiHUDSettings;\nimport logisticspipes.gui.orderer.FluidGuiOrderer;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.gui.orderer.NormalGuiOrderer;\nimport logisticspipes.gui.orderer.NormalMk2GuiOrderer;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.network.packets.pipe.FluidSupplierMinMode;\nimport logisticspipes.network.packets.pipe.FluidSupplierMode;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.PipeFluidBasic;\nimport logisticspipes.pipes.PipeFluidRequestLogistics;\nimport logisticspipes.pipes.PipeFluidSatellite;\nimport logisticspipes.pipes.PipeFluidSupplierMk2;\nimport logisticspipes.pipes.PipeFluidTerminus;\nimport logisticspipes.pipes.PipeItemsFirewall;\nimport logisticspipes.pipes.PipeItemsFluidSupplier;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.PipeItemsSatelliteLogistics;\nimport logisticspipes.pipes.PipeItemsSystemDestinationLogistics;\nimport logisticspipes.pipes.PipeItemsSystemEntranceLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.SatellitePipe;\n\npublic class GuiHandler implements IGuiHandler {\n\n\t@Override\n\tpublic Object getServerGuiElement(int ID, EntityPlayer player, World world, final int x, final int y, final int z) {\n\n\t\tTileEntity tile = null;\n\t\tif (y != -1) {\n\t\t\ttile = world.getTileEntity(new BlockPos(x, y, z));\n\t\t}\n\t\tLogisticsTileGenericPipe pipe = null;\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tpipe = (LogisticsTileGenericPipe) tile;\n\t\t}\n\t\tfinal LogisticsTileGenericPipe fpipe = pipe;\n\n\t\tDummyContainer dummy;\n\t\tint xOffset;\n\t\tint yOffset;\n\n\t\tif (ID > 10000) {\n\t\t\tID -= 10000;\n\t\t}\n\n\t\t//Handle Module Configuration\n\t\tif (ID == -1) {\n\t\t\treturn getServerGuiElement(100 * -20 + x, player, world, 0, -1, z);\n\t\t}\n\n\t\tif (ID < 110 && ID > 0) {\n\t\t\tswitch (ID) {\n\n\t\t\t\tcase GuiIDs.GUI_FluidSupplier_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeItemsFluidSupplier)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tdummy = new DummyContainer(player.inventory, ((PipeItemsFluidSupplier) pipe.pipe).getDummyInventory());\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\n\t\t\t\t\txOffset = 72;\n\t\t\t\t\tyOffset = 18;\n\n\t\t\t\t\tfor (int row = 0; row < 3; row++) {\n\t\t\t\t\t\tfor (int column = 0; column < 3; column++) {\n\t\t\t\t\t\t\tdummy.addDummySlot(column + row * 3, xOffset + column * 18, yOffset + row * 18);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(FluidSupplierMode.class).setInteger((((PipeItemsFluidSupplier) pipe.pipe).isRequestingPartials() ? 1 : 0)).setBlockPos(pipe.getPos()), player);\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_FluidSupplier_MK2_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeFluidSupplierMk2)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tdummy = new DummyContainer(player.inventory, ((PipeFluidSupplierMk2) pipe.pipe).getDummyInventory());\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\t\t\t\t\tdummy.addFluidSlot(0, ((PipeFluidSupplierMk2) pipe.pipe).getDummyInventory(), 0, 0);\n\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(FluidSupplierMode.class).setInteger((((PipeFluidSupplierMk2) pipe.pipe).isRequestingPartials() ? 1 : 0)).setBlockPos(pipe.getPos()), player);\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(FluidSupplierMinMode.class).setInteger(((PipeFluidSupplierMk2) pipe.pipe).getMinMode().ordinal()).setBlockPos(pipe.getPos()), player);\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_SatellitePipe_ID:\n\t\t\t\t\tif (pipe != null && pipe.pipe instanceof PipeItemsSatelliteLogistics) {\n\t\t\t\t\t\treturn new DummyContainer(player.inventory, null);\n\t\t\t\t\t}\n\t\t\t\t\tif (pipe != null && pipe.pipe instanceof PipeFluidSatellite) {\n\t\t\t\t\t\treturn new DummyContainer(player.inventory, null);\n\t\t\t\t\t}\n\n\t\t\t\tcase GuiIDs.GUI_Normal_Orderer_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new DummyContainer(player.inventory, null);\n\n\t\t\t\tcase GuiIDs.GUI_Normal_Mk2_Orderer_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeItemsRequestLogisticsMk2)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new DummyContainer(player.inventory, null);\n\n\t\t\t\tcase GuiIDs.GUI_Fluid_Orderer_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeFluidRequestLogistics)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new DummyContainer(player.inventory, null);\n\n\t\t\t\tcase GuiIDs.GUI_Freq_Card_ID:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeItemsSystemEntranceLogistics) || (pipe.pipe instanceof PipeItemsSystemDestinationLogistics))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tIInventory inv = null;\n\t\t\t\t\tif (pipe.pipe instanceof PipeItemsSystemEntranceLogistics) {\n\t\t\t\t\t\tinv = ((PipeItemsSystemEntranceLogistics) pipe.pipe).inv;\n\t\t\t\t\t} else if (pipe.pipe instanceof PipeItemsSystemDestinationLogistics) {\n\t\t\t\t\t\tinv = ((PipeItemsSystemDestinationLogistics) pipe.pipe).inv;\n\t\t\t\t\t}\n\n\t\t\t\t\tdummy = new DummyContainer(player.inventory, inv);\n\n\t\t\t\t\tdummy.addRestrictedSlot(0, inv, 40, 40, itemStack -> {\n\t\t\t\t\t\tif (itemStack.isEmpty()) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (itemStack.getItem() != LPItems.itemCard) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn itemStack.getItemDamage() == LogisticsItemCard.FREQ_CARD;\n\t\t\t\t\t});\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_HUD_Settings:\n\t\t\t\t\tdummy = new DummyContainer(player.inventory, null);\n\t\t\t\t\tdummy.addRestrictedHotbarForPlayerInventory(10, 160);\n\t\t\t\t\tdummy.addRestrictedArmorForPlayerInventory(10, 60);\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_Fluid_Basic_ID:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeFluidBasic))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tdummy = new DummyContainer(player, ((PipeFluidBasic) pipe.pipe).getSinkInv(), new IGuiOpenControler() {\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\t\t\t\t\t\t((PipeFluidBasic) fpipe.pipe).guiOpenedByPlayer(player);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\t\t\t\t\t\t((PipeFluidBasic) fpipe.pipe).guiClosedByPlayer(player);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tdummy.addFluidSlot(0, ((PipeFluidBasic) pipe.pipe).getSinkInv(), 28, 15);\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(10, 45);\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_Fluid_Terminus_ID:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeFluidTerminus))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tdummy = new DummyContainer(player, ((PipeFluidTerminus) pipe.pipe).getSinkInv(), new IGuiOpenControler() {\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\t\t\t\t\t\t((PipeFluidTerminus) fpipe.pipe).guiOpenedByPlayer(player);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\t\t\t\t\t\t((PipeFluidTerminus) fpipe.pipe).guiClosedByPlayer(player);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\t\t\tdummy.addFluidSlot(i, ((PipeFluidTerminus) pipe.pipe).getSinkInv(), 8 + i * 18, 13);\n\t\t\t\t\t}\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(10, 45);\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_FIREWALL:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeItemsFirewall))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tdummy = new DummyContainer(player.inventory, ((PipeItemsFirewall) pipe.pipe).inv);\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(33, 147);\n\t\t\t\t\tfor (int i = 0; i < 6; i++) {\n\t\t\t\t\t\tfor (int j = 0; j < 6; j++) {\n\t\t\t\t\t\t\tdummy.addDummySlot(i * 6 + j, 0, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tcase GuiIDs.GUI_Request_Table_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeBlockRequestTable)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tdummy = new DummyContainer(player, ((PipeBlockRequestTable) pipe.pipe).matrix, (PipeBlockRequestTable) pipe.pipe);\n\t\t\t\t\tint i = 0;\n\t\t\t\t\tfor (int Y = 0; Y < 3; Y++) {\n\t\t\t\t\t\tfor (int X = 0; X < 9; X++) {\n\t\t\t\t\t\t\tdummy.addNormalSlot(i++, ((PipeBlockRequestTable) pipe.pipe).inv, 0, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\ti = 0;\n\t\t\t\t\tfor (int Y = 0; Y < 3; Y++) {\n\t\t\t\t\t\tfor (int X = 0; X < 3; X++) {\n\t\t\t\t\t\t\tdummy.addDummySlot(i++, 0, 0);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdummy.addCallableSlotHandler(0, ((PipeBlockRequestTable) pipe.pipe).resultInv, 0, 0, () -> ((PipeBlockRequestTable) fpipe.pipe).getResultForClick());\n\t\t\t\t\tdummy.addNormalSlot(0, ((PipeBlockRequestTable) pipe.pipe).toSortInv, 0, 0);\n\t\t\t\t\tdummy.addNormalSlot(0, ((PipeBlockRequestTable) pipe.pipe).diskInv, 0, 0);\n\t\t\t\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\t\t\t\treturn dummy;\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Object getClientGuiElement(int ID, EntityPlayer player, final World world, int x, int y, int z) {\n\t\tif (ID == -1) {\n\t\t\treturn getClientGuiElement(-100 * 20 + x, player, world, 0, -1, z);\n\t\t}\n\n\t\tTileEntity tile = world.getTileEntity(new BlockPos(x, y, z));\n\t\tLogisticsTileGenericPipe pipe = null;\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tpipe = (LogisticsTileGenericPipe) tile;\n\t\t}\n\n\t\tif (ID < 110 && ID > 0) {\n\t\t\tswitch (ID) {\n\n\t\t\t\tcase GuiIDs.GUI_FluidSupplier_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeItemsFluidSupplier)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiFluidSupplierPipe(player.inventory, ((PipeItemsFluidSupplier) pipe.pipe).getDummyInventory(), (PipeItemsFluidSupplier) pipe.pipe);\n\n\t\t\t\tcase GuiIDs.GUI_FluidSupplier_MK2_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeFluidSupplierMk2)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiFluidSupplierMk2Pipe(player.inventory, ((PipeFluidSupplierMk2) pipe.pipe).getDummyInventory(), (PipeFluidSupplierMk2) pipe.pipe);\n\n\t\t\t\tcase GuiIDs.GUI_SatellitePipe_ID:\n\t\t\t\t\tif (pipe != null && pipe.pipe instanceof SatellitePipe) {\n\t\t\t\t\t\treturn new GuiSatellitePipe(((SatellitePipe) pipe.pipe));\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\n\t\t\t\tcase GuiIDs.GUI_Normal_Orderer_ID:\n\t\t\t\t\treturn new NormalGuiOrderer(x, y, z, world.provider.getDimension(), player);\n\n\t\t\t\tcase GuiIDs.GUI_Normal_Mk2_Orderer_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeItemsRequestLogisticsMk2)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new NormalMk2GuiOrderer(((PipeItemsRequestLogisticsMk2) pipe.pipe), player);\n\n\t\t\t\tcase GuiIDs.GUI_Fluid_Orderer_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeFluidRequestLogistics)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new FluidGuiOrderer(((PipeFluidRequestLogistics) pipe.pipe), player);\n\n\t\t\t\tcase GuiIDs.GUI_Freq_Card_ID:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeItemsSystemEntranceLogistics) || (pipe.pipe instanceof PipeItemsSystemDestinationLogistics))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tIInventory inv = null;\n\t\t\t\t\tif (pipe.pipe instanceof PipeItemsSystemEntranceLogistics) {\n\t\t\t\t\t\tinv = ((PipeItemsSystemEntranceLogistics) pipe.pipe).inv;\n\t\t\t\t\t} else if (pipe.pipe instanceof PipeItemsSystemDestinationLogistics) {\n\t\t\t\t\t\tinv = ((PipeItemsSystemDestinationLogistics) pipe.pipe).inv;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiFreqCardContent(player, inv);\n\n\t\t\t\tcase GuiIDs.GUI_HUD_Settings:\n\t\t\t\t\treturn new GuiHUDSettings(player, x);\n\n\t\t\t\tcase GuiIDs.GUI_Fluid_Basic_ID:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeFluidBasic))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiFluidBasic(player, ((PipeFluidBasic) pipe.pipe).getSinkInv());\n\n\t\t\t\tcase GuiIDs.GUI_Fluid_Terminus_ID:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeFluidTerminus))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiFluidTerminus(player, ((PipeFluidTerminus) pipe.pipe));\n\n\t\t\t\tcase GuiIDs.GUI_FIREWALL:\n\t\t\t\t\tif (pipe == null || !((pipe.pipe instanceof PipeItemsFirewall))) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiFirewall((PipeItemsFirewall) pipe.pipe, player);\n\n\t\t\t\tcase GuiIDs.GUI_Request_Table_ID:\n\t\t\t\t\tif (pipe == null || !(pipe.pipe instanceof PipeBlockRequestTable)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn new GuiRequestTable(player, ((PipeBlockRequestTable) pipe.pipe));\n\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/GuiIDs.java",
    "content": "package logisticspipes.network;\n\npublic class GuiIDs {\n\n\t//Pipes\n\tpublic static final int GUI_FluidSupplier_ID = 11;\n\tpublic static final int GUI_SatellitePipe_ID = 13;\n\tpublic static final int GUI_Freq_Card_ID = 15;\n\tpublic static final int GUI_FIREWALL = 17;\n\tpublic static final int GUI_FluidSupplier_MK2_ID = 18;\n\n\t//Devices\n\tpublic static final int GUI_Normal_Orderer_ID = 31;\n\tpublic static final int GUI_Normal_Mk2_Orderer_ID = 34;\n\tpublic static final int GUI_HUD_Settings = 35;\n\tpublic static final int GUI_Fluid_Orderer_ID = 36;\n\tpublic static final int GUI_Fluid_Basic_ID = 37;\n\tpublic static final int GUI_Request_Table_ID = 38;\n\tpublic static final int GUI_Fluid_Terminus_ID = 39;\n\n\t//SubModules\n\t//All IDS above 120 and so on...\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/IReadListObject.java",
    "content": "package logisticspipes.network;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\n\npublic interface IReadListObject<T> {\n\n\tT readObject(LPDataInput input);\n}\n"
  },
  {
    "path": "common/logisticspipes/network/IWriteListObject.java",
    "content": "package logisticspipes.network;\n\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic interface IWriteListObject<T> {\n\n\tvoid writeObject(LPDataOutput output, T object);\n}\n"
  },
  {
    "path": "common/logisticspipes/network/NewGuiHandler.java",
    "content": "package logisticspipes.network;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.inventory.Container;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.common.FMLCommonHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.PopupGuiProvider;\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.network.packets.gui.OpenGUIPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolverUtil;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport network.rs485.logisticspipes.util.LPDataIOWrapper;\n\npublic class NewGuiHandler {\n\n\tpublic static List<GuiProvider> guilist;\n\tpublic static Map<Class<? extends GuiProvider>, GuiProvider> guimap;\n\n\tprivate NewGuiHandler() { }\n\n\t@SuppressWarnings(\"unchecked\") // Suppressed because this cast should never fail.\n\tpublic static <T extends GuiProvider> T getGui(Class<T> clazz) {\n\t\treturn (T) NewGuiHandler.guimap.get(clazz).template();\n\t}\n\n\tpublic static void initialize() {\n\t\tSet<Class<? extends GuiProvider>> classes = StaticResolverUtil.findClassesByType(GuiProvider.class);\n\n\t\tloadGuiProviders(classes);\n\n\t\tif (NewGuiHandler.guilist == null || NewGuiHandler.guilist.isEmpty()) {\n\t\t\tthrow new RuntimeException(\"Cannot load GuiProvider Classes\");\n\t\t}\n\t}\n\n\tprivate static void loadGuiProviders(Set<Class<? extends GuiProvider>> classesIn) {\n\t\tList<Class<? extends GuiProvider>> classes = classesIn.stream()\n\t\t\t\t.sorted(Comparator.comparing(Class::getCanonicalName))\n\t\t\t\t.collect(Collectors.toList());\n\n\t\tNewGuiHandler.guilist = new ArrayList<>(classes.size());\n\t\tNewGuiHandler.guimap = new HashMap<>(classes.size());\n\n\t\tint currentId = 0;\n\t\tfor (Class<? extends GuiProvider> cls : classes) {\n\t\t\ttry {\n\t\t\t\tfinal GuiProvider instance = (GuiProvider) cls.getConstructors()[0].newInstance(currentId);\n\t\t\t\tNewGuiHandler.guilist.add(instance);\n\t\t\t\tNewGuiHandler.guimap.put(cls, instance);\n\t\t\t\tcurrentId++;\n\t\t\t} catch (Throwable ignoredButPrinted) {\n\t\t\t\tignoredButPrinted.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void openGui(GuiProvider guiProvider, EntityPlayer oPlayer) {\n\t\tif (!(oPlayer instanceof EntityPlayerMP)) {\n\t\t\tthrow new UnsupportedOperationException(\"Gui can only be opened on the server side\");\n\t\t}\n\t\tEntityPlayerMP player = (EntityPlayerMP) oPlayer;\n\t\tContainer container = guiProvider.getContainer(player);\n\t\tif (container == null) {\n\t\t\tif (guiProvider instanceof PopupGuiProvider) {\n\t\t\t\tOpenGUIPacket packet = PacketHandler.getPacket(OpenGUIPacket.class);\n\t\t\t\tpacket.setGuiID(guiProvider.getId());\n\t\t\t\tpacket.setWindowID(-2);\n\t\t\t\tpacket.setGuiData(LPDataIOWrapper.collectData(guiProvider::writeData));\n\t\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tplayer.getNextWindowId();\n\t\tplayer.closeContainer();\n\t\tint windowId = player.currentWindowId;\n\n\t\tOpenGUIPacket packet = PacketHandler.getPacket(OpenGUIPacket.class);\n\t\tpacket.setGuiID(guiProvider.getId());\n\t\tpacket.setWindowID(windowId);\n\t\tpacket.setGuiData(LPDataIOWrapper.collectData(guiProvider::writeData));\n\t\tMainProxy.sendPacketToPlayer(packet, player);\n\n\t\tplayer.openContainer = container;\n\t\tplayer.openContainer.windowId = windowId;\n\t\tplayer.openContainer.addListener(player);\n\t\tnet.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.player.PlayerContainerEvent.Open(player, player.openContainer));\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic static void openGui(OpenGUIPacket packet, EntityPlayer player) {\n\t\tint guiID = packet.getGuiID();\n\t\tGuiProvider provider = NewGuiHandler.guilist.get(guiID).template();\n\t\tLPDataIOWrapper.provideData(packet.getGuiData(), provider::readData);\n\n\t\tif (provider instanceof PopupGuiProvider && packet.getWindowID() == -2) {\n\t\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof LogisticsBaseGuiScreen) {\n\t\t\t\tLogisticsBaseGuiScreen baseGUI = (LogisticsBaseGuiScreen) FMLClientHandler.instance().getClient().currentScreen;\n\t\t\t\tSubGuiScreen newSub;\n\t\t\t\ttry {\n\t\t\t\t\tnewSub = (SubGuiScreen) provider.getClientGui(player);\n\t\t\t\t} catch (TargetNotFoundException e) {\n\t\t\t\t\tthrow e;\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tLogisticsPipes.log.error(packet.getClass().getName());\n\t\t\t\t\tLogisticsPipes.log.error(packet.toString());\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\t\t\t\tif (newSub != null) {\n\t\t\t\t\tif (!baseGUI.hasSubGui()) {\n\t\t\t\t\t\tbaseGUI.setSubGui(newSub);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tSubGuiScreen canidate = baseGUI.getSubGui();\n\t\t\t\t\t\twhile (canidate.hasSubGui()) {\n\t\t\t\t\t\t\tcanidate = canidate.getSubGui();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcanidate.setSubGui(newSub);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tGuiContainer screen;\n\t\t\ttry {\n\t\t\t\tscreen = (GuiContainer) provider.getClientGui(player);\n\t\t\t} catch (TargetNotFoundException e) {\n\t\t\t\tthrow e;\n\t\t\t} catch (Exception e) {\n\t\t\t\tLogisticsPipes.log.error(packet.getClass().getName());\n\t\t\t\tLogisticsPipes.log.error(packet.toString());\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t\tscreen.inventorySlots.windowId = packet.getWindowID();\n\t\t\tFMLCommonHandler.instance().showGuiScreen(screen);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/PacketHandler.java",
    "content": "package logisticspipes.network;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.network.PacketBuffer;\n\nimport net.minecraftforge.fml.common.network.NetworkRegistry;\nimport net.minecraftforge.fml.common.network.internal.FMLProxyPacket;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport io.netty.buffer.ByteBuf;\nimport io.netty.buffer.Unpooled;\nimport static io.netty.buffer.Unpooled.buffer;\nimport io.netty.channel.ChannelHandler.Sharable;\nimport io.netty.channel.ChannelHandlerContext;\nimport io.netty.handler.codec.MessageToMessageCodec;\nimport io.netty.util.AttributeKey;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.exception.DelayPacketException;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolverUtil;\nimport network.rs485.logisticspipes.util.LPDataIOWrapper;\nimport network.rs485.logisticspipes.util.LPDataInput;\n\n/*\n *  Basically FML SimpleIndexedCodec, except with static registration of LP ModernPackets and short instead of byte discriminator\n */\n@Sharable\npublic class PacketHandler extends MessageToMessageCodec<FMLProxyPacket, ModernPacket> {\n\n\tpublic static final Map<Integer, StackTraceElement[]> debugMap = new HashMap<>();\n\tprotected static final AttributeKey<ThreadLocal<WeakReference<FMLProxyPacket>>> INBOUNDPACKETTRACKER = AttributeKey.valueOf(\"lp:inboundpacket\");\n\tpublic static List<ModernPacket> packetlist;\n\tpublic static Map<Class<? extends ModernPacket>, ModernPacket> packetmap;\n\tprivate static int packetDebugID = 1;\n\n\t@SuppressWarnings(\"unchecked\") // Suppressed because this cast should never fail.\n\tpublic static <T extends ModernPacket> T getPacket(Class<T> clazz) {\n\t\tT packet = (T) PacketHandler.packetmap.get(clazz).template();\n\t\tif (LogisticsPipes.isDEBUG() && MainProxy.proxy.getSide().equals(\"Client\")) {\n\t\t\tStackTraceElement[] trace = Thread.currentThread().getStackTrace();\n\t\t\tsynchronized (PacketHandler.debugMap) { //Unique id\n\t\t\t\tint id = PacketHandler.packetDebugID++;\n\t\t\t\tPacketHandler.debugMap.put(id, trace);\n\t\t\t\tpacket.setDebugId(id);\n\t\t\t}\n\t\t}\n\t\treturn packet;\n\t}\n\n\t/*\n\t * enumerates all ModernPackets, sets their IDs and populate packetlist/packetmap\n\t */\n\tpublic static void initialize() {\n\t\tSet<Class<? extends ModernPacket>> classes = StaticResolverUtil.findClassesByType(ModernPacket.class);\n\n\t\tloadPackets(classes);\n\n\t\tif (PacketHandler.packetlist.isEmpty()) {\n\t\t\tthrow new RuntimeException(\"Cannot load Packet Classes\");\n\t\t}\n\t}\n\n\tprivate static void loadPackets(Set<Class<? extends ModernPacket>> classesIn) {\n\t\tList<Class<? extends ModernPacket>> classes = classesIn.stream()\n\t\t\t\t.sorted(Comparator.comparing(Class::getCanonicalName))\n\t\t\t\t.collect(Collectors.toList());\n\n\t\tPacketHandler.packetlist = new ArrayList<>(classes.size());\n\t\tPacketHandler.packetmap = new HashMap<>(classes.size());\n\n\t\tint currentId = 0;\n\t\tfor (Class<? extends ModernPacket> cls : classes) {\n\t\t\ttry {\n\t\t\t\tfinal ModernPacket instance = cls.getConstructor(int.class).newInstance(currentId);\n\t\t\t\tPacketHandler.packetlist.add(instance);\n\t\t\t\tPacketHandler.packetmap.put(cls, instance);\n\t\t\t\tcurrentId++;\n\t\t\t} catch (Throwable ignoredButPrinted) {\n\t\t\t\tignoredButPrinted.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t//Used to provide the Description packet\n\tpublic static FMLProxyPacket toFMLPacket(ModernPacket msg) {\n\t\treturn toFMLPacket(msg, MainProxy.networkChannelName);\n\t}\n\n\tprivate static FMLProxyPacket toFMLPacket(ModernPacket msg, String channel) {\n\t\tByteBuf buffer = Unpooled.buffer();\n\t\tfillByteBuf(msg, buffer);\n\n\t\treturn new FMLProxyPacket(new PacketBuffer(buffer), channel);\n\t}\n\n\tpublic static void fillByteBuf(ModernPacket msg, ByteBuf buffer) {\n\t\tbuffer.writeShort(msg.getId());\n\t\tbuffer.writeInt(msg.getDebugId());\n\n\t\tLPDataIOWrapper.writeData(buffer, msg::writeData);\n\t}\n\n\tpublic static void addPacketToNBT(ModernPacket packet, NBTTagCompound nbt) {\n\t\tByteBuf dataBuffer = buffer();\n\t\tPacketHandler.fillByteBuf(packet, dataBuffer);\n\n\t\tbyte[] data = new byte[dataBuffer.readableBytes()];\n\t\tdataBuffer.getBytes(0, data);\n\t\tdataBuffer.release();\n\n\t\tnbt.setByteArray(\"LogisticsPipes:PacketData\", data);\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic static void queueAndRemovePacketFromNBT(NBTTagCompound nbt) {\n\t\tbyte[] data = nbt.getByteArray(\"LogisticsPipes:PacketData\");\n\t\tif (data.length > 0) {\n\t\t\tLPDataIOWrapper.provideData(data, dataInput -> {\n\t\t\t\tfinal int packetID = dataInput.readShort();\n\t\t\t\tfinal ModernPacket packet = PacketHandler.packetlist.get(packetID).template();\n\t\t\t\tpacket.setDebugId(dataInput.readInt());\n\t\t\t\tpacket.readData(dataInput);\n\t\t\t\tSimpleServiceLocator.clientBufferHandler.queuePacket(packet, MainProxy.proxy.getClientPlayer());\n\t\t\t});\n\t\t}\n\t\tnbt.removeTag(\"LogisticsPipes:PacketData\");\n\t}\n\n\t//hacky callback to process packets coming from by the packetbufferhandler decompressors\n\t//TODO replace with proper netty implementation\n\tpublic static void onPacketData(final LPDataInput data, final EntityPlayer player) {\n\t\tif (player == null) {\n\t\t\treturn;\n\t\t}\n\t\tfinal int packetID = data.readShort();\n\t\tfinal ModernPacket packet = PacketHandler.packetlist.get(packetID).template();\n\t\tpacket.setDebugId(data.readInt());\n\t\tpacket.readData(data);\n\t\tPacketHandler.onPacketData(packet, player);\n\t}\n\n\tpublic static void onPacketData(ModernPacket packet, final EntityPlayer player) {\n\t\ttry {\n\t\t\tpacket.processPacket(player);\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tPacketHandler.debugMap.remove(packet.getDebugId());\n\t\t\t}\n\t\t} catch (DelayPacketException e) {\n\t\t\tif (packet.retry() && MainProxy.isClient(player.getEntityWorld())) {\n\t\t\t\tSimpleServiceLocator.clientBufferHandler.queuePacket(packet, player);\n\t\t\t} else if (LogisticsPipes.isDEBUG()) {\n\t\t\t\tLogisticsPipes.log.error(packet.getClass().getName());\n\t\t\t\tLogisticsPipes.log.error(packet.toString());\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {\n\t\tsuper.handlerAdded(ctx);\n\t\tctx.channel().attr(INBOUNDPACKETTRACKER).set(new ThreadLocal<>());\n\t}\n\n\t@Override\n\tprotected final void encode(ChannelHandlerContext ctx, ModernPacket msg, List<Object> out) {\n\t\tFMLProxyPacket proxy = PacketHandler.toFMLPacket(msg, ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get());\n\t\tWeakReference<FMLProxyPacket> ref = ctx.channel().attr(INBOUNDPACKETTRACKER).get().get();\n\t\tFMLProxyPacket old = ref == null ? null : ref.get();\n\t\tif (old != null) {\n\t\t\tproxy.setDispatcher(old.getDispatcher());\n\t\t}\n\t\tout.add(proxy);\n\t}\n\n\t@Override\n\tprotected final void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List<Object> out) {\n\t\tByteBuf payload = msg.payload();\n\t\tint packetID = payload.readShort();\n\t\tfinal ModernPacket packet = PacketHandler.packetlist.get(packetID).template();\n\t\tpacket.setDebugId(payload.readInt());\n\t\tctx.channel().attr(INBOUNDPACKETTRACKER).get().set(new WeakReference<>(msg));\n\n\t\tLPDataIOWrapper.provideData(payload.slice(), packet::readData);\n\t\tpayload.release();\n\n\t\tEntityPlayer player = MainProxy.proxy.getEntityPlayerFromNetHandler(msg.handler());\n\n\t\tif (player != null) {\n\t\t\tout.add(new InboundModernPacketWrapper(packet, player));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {\n\t\tLogisticsPipes.log.error(\"LogisticsPipes PacketHandler exception caught\", cause);\n\t\tsuper.exceptionCaught(ctx, cause);\n\t}\n\n\t//horrible hack to carry the proper player for the side along...\n\tstatic class InboundModernPacketWrapper {\n\n\t\tfinal ModernPacket packet;\n\t\tfinal EntityPlayer player;\n\n\t\tInboundModernPacketWrapper(ModernPacket p, EntityPlayer e) {\n\t\t\tpacket = p;\n\t\t\tplayer = e;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/PacketInboundHandler.java",
    "content": "package logisticspipes.network;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.IThreadListener;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\nimport net.minecraftforge.fml.common.FMLLog;\nimport net.minecraftforge.fml.common.network.NetworkRegistry;\n\nimport io.netty.channel.ChannelHandlerContext;\nimport io.netty.channel.SimpleChannelInboundHandler;\nimport org.apache.logging.log4j.Level;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.PacketHandler.InboundModernPacketWrapper;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\n\npublic class PacketInboundHandler extends SimpleChannelInboundHandler<InboundModernPacketWrapper> {\n\n\t@Override\n\tprotected void channelRead0(ChannelHandlerContext ctx, InboundModernPacketWrapper msg) {\n\t\tIThreadListener thread = FMLCommonHandler.instance().getWorldThread(ctx.channel().attr(NetworkRegistry.NET_HANDLER).get());\n\t\tif (thread.isCallingFromMinecraftThread()) {\n\t\t\tinThreadProcessPacket(msg.packet, msg.player);\n\t\t} else {\n\t\t\tthread.addScheduledTask(() -> inThreadProcessPacket(msg.packet, msg.player));\n\t\t}\n\t}\n\n\tprivate void inThreadProcessPacket(ModernPacket packet, EntityPlayer player) {\n\t\ttry {\n\t\t\tpacket.processPacket(player);\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tPacketHandler.debugMap.remove(packet.getDebugId());\n\t\t\t}\n\t\t} catch (TargetNotFoundException e) {\n\t\t\tif (packet.retry() && MainProxy.isClient(player.getEntityWorld())) {\n\t\t\t\tSimpleServiceLocator.clientBufferHandler.queuePacket(packet, player);\n\t\t\t} else if (LogisticsPipes.isDEBUG()) {\n\t\t\t\tLogisticsPipes.log.error(packet.getClass().getName());\n\t\t\t\tLogisticsPipes.log.error(packet.toString());\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {\n\t\tFMLLog.log(Level.ERROR, cause, \"PacketInboundHandler exception\");\n\t\tsuper.exceptionCaught(ctx, cause);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/BooleanModuleCoordinatesGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class BooleanModuleCoordinatesGuiProvider extends ModuleCoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate boolean flag;\n\n\tpublic BooleanModuleCoordinatesGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(flag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tflag = input.readBoolean();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/CoordinatesGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@ToString\npublic abstract class CoordinatesGuiProvider extends GuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate int posX;\n\t@Getter\n\t@Setter\n\tprivate int posY;\n\t@Getter\n\t@Setter\n\tprivate int posZ;\n\n\tpublic CoordinatesGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\n\t\toutput.writeInt(posX);\n\t\toutput.writeInt(posY);\n\t\toutput.writeInt(posZ);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\n\t\tposX = input.readInt();\n\t\tposY = input.readInt();\n\t\tposZ = input.readInt();\n\n\t}\n\n\tpublic CoordinatesGuiProvider setTilePos(TileEntity tile) {\n\t\tsetPosX(tile.getPos().getX());\n\t\tsetPosY(tile.getPos().getY());\n\t\tsetPosZ(tile.getPos().getZ());\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\tpublic <T> T getTileAs(World world, Class<T> clazz) {\n\t\treturn CoordinatesPacket.getTileAs(this, world, new BlockPos(getPosX(), getPosY(), getPosZ()), clazz);\n\t}\n\n}\n\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/CoordinatesPopupGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@ToString\npublic abstract class CoordinatesPopupGuiProvider extends PopupGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate int posX;\n\t@Getter\n\t@Setter\n\tprivate int posY;\n\t@Getter\n\t@Setter\n\tprivate int posZ;\n\n\tpublic CoordinatesPopupGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\n\t\toutput.writeInt(posX);\n\t\toutput.writeInt(posY);\n\t\toutput.writeInt(posZ);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\n\t\tposX = input.readInt();\n\t\tposY = input.readInt();\n\t\tposZ = input.readInt();\n\n\t}\n\n\tpublic CoordinatesPopupGuiProvider setTilePos(TileEntity tile) {\n\t\tsetPosX(tile.getPos().getX());\n\t\tsetPosY(tile.getPos().getY());\n\t\tsetPosZ(tile.getPos().getZ());\n\t\treturn this;\n\t}\n\n\tpublic CoordinatesPopupGuiProvider setLPPos(DoubleCoordinates pos) {\n\t\tsetPosX(pos.getXInt());\n\t\tsetPosY(pos.getYInt());\n\t\tsetPosZ(pos.getZInt());\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\tpublic <T> T getTileAs(World world, Class<T> clazz) {\n\t\treturn CoordinatesPacket.getTileAs(this, world, new BlockPos(getPosX(), getPosY(), getPosZ()), clazz);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/GuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\n\nimport net.minecraftforge.common.util.FakePlayer;\n\nimport lombok.Getter;\n\nimport logisticspipes.network.NewGuiHandler;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class GuiProvider {\n\n\t@Getter\n\tprivate final int id;\n\n\tpublic GuiProvider(int id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic void writeData(LPDataOutput output) {}\n\n\tpublic void readData(LPDataInput input) {}\n\n\t/**\n\t * @return LogisticsBaseGuiScreen\n\t */\n\tpublic abstract Object getClientGui(EntityPlayer player);\n\n\tpublic abstract Container getContainer(EntityPlayer player);\n\n\tpublic abstract GuiProvider template();\n\n\tpublic final void open(EntityPlayer player) {\n\t\tif (player instanceof FakePlayer) return;\n\t\tNewGuiHandler.openGui(this, player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/ModuleCoordinatesGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport net.minecraft.world.World;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ModuleCoordinatesGuiProvider extends CoordinatesGuiProvider {\n\n\tprivate ModulePositionType slot;\n\tprivate int positionInt;\n\n\tpublic ModuleCoordinatesGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeEnum(slot);\n\t\toutput.writeInt(positionInt);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tslot = input.readEnum(ModulePositionType.class);\n\t\tpositionInt = input.readInt();\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic <T> T getLogisticsModule(World world, Class<T> clazz) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\tif (LogisticsPipes.isDEBUG() && pipe.isInitialized()) {\n\t\t\t\tLogisticsPipes.log.fatal(toString());\n\t\t\t\tnew RuntimeException(\"Couldn't find \" + clazz.getName() + \", pipe didn't exsist\").printStackTrace();\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tLogisticsModule module;\n\t\tif (slot == ModulePositionType.IN_PIPE) {\n\t\t\tmodule = ((CoreRoutedPipe) pipe.pipe).getLogisticsModule();\n\t\t} else if (slot == ModulePositionType.IN_HAND) {\n\t\t\tthrow new UnsupportedOperationException(\"NO IN_HAND FOR THIS PACKET TYPE\");\n\t\t} else {\n\t\t\tif (!(pipe.pipe instanceof PipeLogisticsChassis)) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tLogisticsPipes.log.fatal(toString());\n\t\t\t\t\tnew RuntimeException(\"Couldn't find \" + clazz.getName() + \", pipe wasn't a chassi pipe\").printStackTrace();\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tmodule = ((PipeLogisticsChassis) pipe.pipe).getSubModule(positionInt);\n\t\t}\n\t\tif (module != null) {\n\t\t\tif (!(clazz.isAssignableFrom(module.getClass()))) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tLogisticsPipes.log.fatal(toString());\n\t\t\t\t\tnew RuntimeException(\"Couldn't find \" + clazz.getName() + \", found \" + module.getClass()).printStackTrace();\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tLogisticsPipes.log.fatal(toString());\n\t\t\t\tnew RuntimeException(\"Couldn't find \" + clazz.getName()).printStackTrace();\n\t\t\t}\n\t\t}\n\t\treturn (T) module;\n\t}\n\n\tpublic ModulePositionType getSlot() {\n\t\treturn this.slot;\n\t}\n\n\tpublic ModuleCoordinatesGuiProvider setSlot(ModulePositionType slot) {\n\t\tthis.slot = slot;\n\t\treturn this;\n\t}\n\n\tpublic int getPositionInt() {\n\t\treturn this.positionInt;\n\t}\n\n\tpublic ModuleCoordinatesGuiProvider setPositionInt(int positionInt) {\n\t\tthis.positionInt = positionInt;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/ModuleInHandGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ModuleInHandGuiProvider extends GuiProvider {\n\n\tprivate int invSlot;\n\n\tpublic ModuleInHandGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(invSlot);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tinvSlot = input.readInt();\n\t}\n\n\tpublic int getInvSlot() {\n\t\treturn this.invSlot;\n\t}\n\n\tpublic ModuleInHandGuiProvider setInvSlot(int invSlot) {\n\t\tthis.invSlot = invSlot;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/NBTModuleCoordinatesGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class NBTModuleCoordinatesGuiProvider extends ModuleCoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate NBTTagCompound nbt;\n\n\tpublic NBTModuleCoordinatesGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeNBTTagCompound(nbt);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tnbt = input.readNBTTagCompound();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/PopupGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\n\npublic abstract class PopupGuiProvider extends GuiProvider {\n\n\tpublic PopupGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic final Container getContainer(EntityPlayer player) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractguis/UpgradeCoordinatesGuiProvider.java",
    "content": "package logisticspipes.network.abstractguis;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Slot;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class UpgradeCoordinatesGuiProvider extends CoordinatesPopupGuiProvider {\n\n\t@Getter(AccessLevel.PROTECTED)\n\t@Setter(AccessLevel.PRIVATE)\n\tprivate int positionInt;\n\n\tpublic UpgradeCoordinatesGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(positionInt);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tpositionInt = input.readInt();\n\t}\n\n\tpublic UpgradeCoordinatesGuiProvider setSlot(Slot slot) {\n\t\tthis.setPositionInt(slot.slotNumber);\n\t\treturn this;\n\t}\n\n\tpublic <T extends Slot> T getSlot(EntityPlayer player, Class<T> clazz) {\n\t\tif (player.openContainer instanceof DummyContainer) {\n\t\t\tif (positionInt >= player.openContainer.inventorySlots.size()) {\n\t\t\t\tthrow new TargetNotFoundException(\"The requested Slot was out of range\", this);\n\t\t\t} else {\n\t\t\t\tSlot slot = player.openContainer.getSlot(positionInt);\n\t\t\t\tif (slot == null) {\n\t\t\t\t\tthrow new TargetNotFoundException(\"The requested Slot was null\", this);\n\t\t\t\t} else if (!clazz.isAssignableFrom(slot.getClass())) {\n\t\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", found slot with \" + slot.getClass(), this);\n\t\t\t\t} else {\n\t\t\t\t\treturn (T) slot;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/BitSetCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.BitSet;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class BitSetCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate BitSet flags;\n\n\tpublic BitSetCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBitSet(getFlags());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetFlags(input.readBitSet());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/BooleanCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class BooleanCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tboolean flag;\n\n\tpublic BooleanCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(flag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tflag = input.readBoolean();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/BooleanModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class BooleanModuleCoordinatesPacket extends ModuleCoordinatesPacket {\n\n\tboolean flag;\n\n\tpublic BooleanModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(flag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tflag = input.readBoolean();\n\t}\n\n\tpublic boolean isFlag() {\n\t\treturn this.flag;\n\t}\n\n\tpublic BooleanModuleCoordinatesPacket setFlag(boolean flag) {\n\t\tthis.flag = flag;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/ChannelInformationListCoordinatesPopupGuiProvider.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractguis.CoordinatesPopupGuiProvider;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ChannelInformationListCoordinatesPopupGuiProvider extends CoordinatesPopupGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate List<ChannelInformation> channelInformations = new ArrayList<>();\n\n\tpublic ChannelInformationListCoordinatesPopupGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(channelInformations, LPDataOutput::writeChannelInformation);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tchannelInformations = input.readArrayList(LPDataInput::readChannelInformation);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/CoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.function.Function;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.ToString;\n\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@ToString\npublic abstract class CoordinatesPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int posX;\n\t@Getter\n\t@Setter\n\tprivate int posY;\n\t@Getter\n\t@Setter\n\tprivate int posZ;\n\n\tpublic CoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Nonnull\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static <T> T getTileAs(Object whosAsking, World world, BlockPos blockPos, Class<T> clazz) {\n\t\tfinal TileEntity tile = getWorldTile(whosAsking, world, blockPos);\n\t\tif (tile != null) {\n\t\t\tif (clazz.isAssignableFrom(tile.getClass())) {\n\t\t\t\treturn (T) tile;\n\t\t\t}\n\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", found \" + tile.getClass() + \" at: \" + blockPos, whosAsking);\n\t\t} else {\n\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \" at: \" + blockPos, whosAsking);\n\t\t}\n\t}\n\n\tprivate static TileEntity getWorldTile(Object whosAsking, World world, BlockPos blockPos) {\n\t\tif (world == null) {\n\t\t\tthrow new TargetNotFoundException(\"World was null\", whosAsking);\n\t\t}\n\t\tif (world.isAirBlock(blockPos)) {\n\t\t\tthrow new TargetNotFoundException(\"Only found air at: \" + blockPos, whosAsking);\n\t\t}\n\n\t\treturn world.getTileEntity(blockPos);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(posX);\n\t\toutput.writeInt(posY);\n\t\toutput.writeInt(posZ);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tposX = input.readInt();\n\t\tposY = input.readInt();\n\t\tposZ = input.readInt();\n\n\t}\n\n\tpublic CoordinatesPacket setTilePos(TileEntity tile) {\n\t\tsetDimension(tile.getWorld());\n\t\tsetPosX(tile.getPos().getX());\n\t\tsetPosY(tile.getPos().getY());\n\t\tsetPosZ(tile.getPos().getZ());\n\t\treturn this;\n\t}\n\n\tpublic CoordinatesPacket setLPPos(DoubleCoordinates pos) {\n\t\tsetPosX(pos.getXInt());\n\t\tsetPosY(pos.getYInt());\n\t\tsetPosZ(pos.getZInt());\n\t\treturn this;\n\t}\n\n\tpublic CoordinatesPacket setPacketPos(CoordinatesPacket packet) {\n\t\tposX = packet.posX;\n\t\tposY = packet.posY;\n\t\tposZ = packet.posZ;\n\t\treturn this;\n\t}\n\n\tpublic CoordinatesPacket setBlockPos(BlockPos pos) {\n\t\tposX = pos.getX();\n\t\tposY = pos.getY();\n\t\tposZ = pos.getZ();\n\t\treturn this;\n\t}\n\n\tpublic TileEntity getTileAs(World world, Function<TileEntity, Boolean> validateResult) {\n\t\tTileEntity tile = getTileAs(world, TileEntity.class);\n\t\tif (!validateResult.apply(tile)) {\n\t\t\tthrow new TargetNotFoundException(\"TileEntity condition not met\", this);\n\t\t}\n\t\treturn tile;\n\t}\n\n\t/**\n\t * Retrieves tileEntity at packet coordinates if any.\n\t */\n\tpublic <T> T getTileAs(World world, Class<T> clazz) {\n\t\treturn getTileAs(this, world, new BlockPos(getPosX(), getPosY(), getPosZ()), clazz);\n\t}\n\n\t/**\n\t * Retrieves tileEntity or CoreUnroutedPipe at packet coordinates if any.\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tpublic <T> T getTileOrPipe(World world, Class<T> clazz) {\n\t\tfinal TileEntity tile = getWorldTile(this, world, new BlockPos(getPosX(), getPosY(), getPosZ()));\n\t\tif (tile != null) {\n\t\t\tif (clazz.isAssignableFrom(tile.getClass())) {\n\t\t\t\treturn (T) tile;\n\t\t\t}\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\tif (((LogisticsTileGenericPipe) tile).pipe != null && clazz.isAssignableFrom(((LogisticsTileGenericPipe) tile).pipe.getClass())) {\n\t\t\t\t\treturn (T) ((LogisticsTileGenericPipe) tile).pipe;\n\t\t\t\t}\n\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", found pipe with \" + tile.getClass() + \" at: \" + new BlockPos(getPosX(), getPosY(), getPosZ()), this);\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \" at: \" + new BlockPos(getPosX(), getPosY(), getPosZ()), this);\n\t\t}\n\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", found \" + tile.getClass() + \" at: \" + new BlockPos(getPosX(), getPosY(), getPosZ()), this);\n\t}\n\n\t/**\n\t * Retrieves pipe at packet coordinates if any.\n\t */\n\t@Deprecated\n\tpublic LogisticsTileGenericPipe getPipe(World world) {\n\t\treturn getPipe(world, LTGPCompletionCheck.NONE);\n\t}\n\n\t@Nonnull\n\tpublic LogisticsTileGenericPipe getPipe(World world, LTGPCompletionCheck check) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(world, LogisticsTileGenericPipe.class);\n\t\tif (check == LTGPCompletionCheck.PIPE || check == LTGPCompletionCheck.TRANSPORT) {\n\t\t\tif (pipe.pipe == null) {\n\t\t\t\tthrow new TargetNotFoundException(\"The found pipe didn't have a loaded pipe field\", this);\n\t\t\t}\n\t\t}\n\t\tif (check == LTGPCompletionCheck.TRANSPORT) {\n\t\t\tif (pipe.pipe.transport == null) {\n\t\t\t\tthrow new TargetNotFoundException(\"The found pipe didn't have a loaded transport field\", this);\n\t\t\t}\n\t\t}\n\t\treturn pipe;\n\t}\n\n\tpublic enum LTGPCompletionCheck {\n\t\tNONE,\n\t\tPIPE,\n\t\tTRANSPORT\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/DirectionModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport net.minecraft.util.EnumFacing;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class DirectionModuleCoordinatesPacket extends ModuleCoordinatesPacket {\n\tprivate EnumFacing direction;\n\n\tpublic DirectionModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\tpublic DirectionModuleCoordinatesPacket setDirection(EnumFacing newDirection) {\n\t\tdirection = newDirection;\n\t\treturn this;\n\t}\n\n\tpublic EnumFacing getDirection() {\n\t\treturn direction;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeFacing(direction);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tdirection = input.readFacing();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/GuiPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiScreen;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SubGuiScreen;\n\npublic abstract class GuiPacket extends ModernPacket {\n\n\tpublic GuiPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprotected <T> T getGui(Class<T> guiClass) {\n\t\tGuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;\n\t\tif (currentScreen == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (guiClass.isAssignableFrom(currentScreen.getClass())) {\n\t\t\treturn (T) currentScreen;\n\t\t}\n\t\tSubGuiScreen subScreen = null;\n\t\tif (currentScreen instanceof LogisticsBaseGuiScreen) {\n\t\t\tsubScreen = ((LogisticsBaseGuiScreen) currentScreen).getSubGui();\n\t\t}\n\t\twhile (subScreen != null) {\n\t\t\tif (guiClass.isAssignableFrom(subScreen.getClass())) {\n\t\t\t\treturn (T) subScreen;\n\t\t\t}\n\t\t\tsubScreen = subScreen.getSubGui();\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/Integer2CoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class Integer2CoordinatesPacket extends IntegerCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int integer2;\n\n\tpublic Integer2CoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetInteger2(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getInteger2());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/Integer2ModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class Integer2ModuleCoordinatesPacket extends IntegerModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int integer2;\n\n\tpublic Integer2ModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetInteger2(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getInteger2());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/IntegerCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class IntegerCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int integer;\n\n\tpublic IntegerCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetInteger(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getInteger());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/IntegerModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class IntegerModuleCoordinatesPacket extends ModuleCoordinatesPacket {\n\n\tprivate int integer;\n\n\tpublic IntegerModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetInteger(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getInteger());\n\t}\n\n\tpublic int getInteger() {\n\t\treturn this.integer;\n\t}\n\n\tpublic IntegerModuleCoordinatesPacket setInteger(int integer) {\n\t\tthis.integer = integer;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/IntegerPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class IntegerPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int integer;\n\n\tpublic IntegerPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetInteger(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getInteger());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/InventoryModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.NonNullList;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class InventoryModuleCoordinatesPacket extends ModuleCoordinatesPacket {\n\n\tprivate static final byte STACK_MARKER = 0;\n\tprivate static final byte IDENT_MARKER = 1;\n\n\tprivate IInventory inventory;\n\n\tprivate NonNullList<ItemStack> stackList;\n\n\tprivate List<ItemIdentifierStack> identList;\n\n\tprivate Set<ItemIdentifierStack> identSet;\n\n\tpublic InventoryModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\n\t\tif (inventory != null) {\n\t\t\toutput.writeByte(STACK_MARKER);\n\t\t\toutput.writeInt(inventory.getSizeInventory());\n\t\t\tfor (int i = 0; i < inventory.getSizeInventory(); i++) {\n\t\t\t\toutput.writeItemStack(inventory.getStackInSlot(i));\n\t\t\t}\n\t\t} else if (stackList != null) {\n\t\t\toutput.writeByte(STACK_MARKER);\n\t\t\toutput.writeCollection(stackList, LPDataOutput::writeItemStack);\n\t\t} else if (identList != null) {\n\t\t\toutput.writeByte(IDENT_MARKER);\n\t\t\toutput.writeCollection(identList, LPDataOutput::writeItemIdentifierStack);\n\t\t} else if (identSet != null) {\n\t\t\toutput.writeByte(IDENT_MARKER);\n\t\t\toutput.writeCollection(identSet, LPDataOutput::writeItemIdentifierStack);\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\"Wont send packet without content\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\n\t\tbyte marker = input.readByte();\n\t\tif (marker == STACK_MARKER) {\n\t\t\tstackList = input.readNonNullList(LPDataInput::readItemStack, ItemStack.EMPTY);\n\t\t} else if (marker == IDENT_MARKER) {\n\t\t\tidentList = input.readLinkedList(LPDataInput::readItemIdentifierStack);\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(\"Unknown marker: \" + marker);\n\t\t}\n\t}\n\n\tpublic NonNullList<ItemStack> getStackList() {\n\t\treturn this.stackList;\n\t}\n\n\tpublic InventoryModuleCoordinatesPacket setStackList(NonNullList<ItemStack> stackList) {\n\t\tthis.stackList = stackList;\n\t\treturn this;\n\t}\n\n\tpublic List<ItemIdentifierStack> getIdentList() {\n\t\treturn this.identList;\n\t}\n\n\tpublic InventoryModuleCoordinatesPacket setIdentList(List<ItemIdentifierStack> identList) {\n\t\tthis.identList = identList;\n\t\treturn this;\n\t}\n\n\tpublic InventoryModuleCoordinatesPacket setInventory(IInventory inventory) {\n\t\tthis.inventory = inventory;\n\t\treturn this;\n\t}\n\n\tpublic InventoryModuleCoordinatesPacket setIdentSet(Set<ItemIdentifierStack> identSet) {\n\t\tthis.identSet = identSet;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/ItemPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ItemPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\t@Nonnull\n\tprivate ItemStack stack = ItemStack.EMPTY;\n\n\tpublic ItemPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\tif (getStack().isEmpty()) {\n\t\t\toutput.writeInt(0);\n\t\t} else {\n\t\t\toutput.writeInt(Item.getIdFromItem(getStack().getItem()));\n\t\t\toutput.writeInt(getStack().getCount());\n\t\t\toutput.writeInt(getStack().getItemDamage());\n\t\t\toutput.writeNBTTagCompound(getStack().getTagCompound());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\n\t\tfinal int itemID = input.readInt();\n\t\tif (itemID == 0) {\n\t\t\tsetStack(ItemStack.EMPTY);\n\t\t} else {\n\t\t\tint stackSize = input.readInt();\n\t\t\tint damage = input.readInt();\n\t\t\tsetStack(new ItemStack(Item.getItemById(itemID), stackSize, damage));\n\t\t\tgetStack().setTagCompound(input.readNBTTagCompound());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/ListSyncPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.List;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.IReadListObject;\nimport logisticspipes.network.IWriteListObject;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ListSyncPacket<E> extends CoordinatesPacket implements IWriteListObject<E>, IReadListObject<E> {\n\n\t@Setter\n\t@Getter(value = AccessLevel.PROTECTED)\n\tprivate List<E> list;\n\n\tpublic ListSyncPacket(int id, int x, int y, int z) {\n\t\tsuper(id);\n\t\tsetPosX(x);\n\t\tsetPosY(y);\n\t\tsetPosZ(z);\n\t}\n\n\tpublic ListSyncPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(list, this);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tlist = input.readArrayList(this);\n\t}\n\n\t@Override\n\tpublic abstract ListSyncPacket<E> template();\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/ModernPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.packetcontent.IPacketContent;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ModernPacket {\n\n\t/*\n\t@Getter\n\tprotected String channel;\n\t */\n\t@Getter\n\tprivate final int id;\n\tprotected int leftRetries = 5;\n\t@Getter\n\t@Setter\n\tprivate boolean isChunkDataPacket;\n\t@Getter\n\t@Setter\n\tprivate boolean compressable;\n\t//@Getter\n\t//private byte[] data = null;\n\t@Getter\n\t@Setter\n\tprivate int debugId = 0;\n\t@Getter\n\tprivate int dimension = 0; // If the dimension is not set the packet will be handled in the main overworld\n\n\tpublic List<IPacketContent<?>> content = Collections.emptyList();\n\n\tpublic ModernPacket(int id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic ModernPacket setDimension(int dimension) {\n\t\tthis.dimension = dimension;\n\t\treturn this;\n\t}\n\n\tpublic ModernPacket setDimension(World world) {\n\t\tthis.dimension = world.provider.getDimension();\n\t\treturn this;\n\t}\n\n\tpublic void readData(LPDataInput input) {\n\t\tdimension = input.readInt();\n\t\tcontent.forEach(it -> it.readData(input));\n\t}\n\n\tpublic abstract void processPacket(EntityPlayer player);\n\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(dimension);\n\t\tcontent.forEach(it -> it.writeData(output));\n\t}\n\n\tpublic abstract ModernPacket template();\n\n\tpublic boolean retry() {\n\t\treturn leftRetries-- > 0;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/ModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.ContainerPlayer;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class ModuleCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ModulePositionType type;\n\n\t@Getter\n\t@Setter\n\tprivate int positionInt;\n\tprivate boolean moduleBased = false;\n\n\tpublic ModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(type != null);\n\t\tif (type != null) {\n\t\t\toutput.writeEnum(type);\n\t\t\toutput.writeInt(positionInt);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tif (input.readBoolean()) {\n\t\t\ttype = input.readEnum(ModulePositionType.class);\n\t\t\tpositionInt = input.readInt();\n\t\t}\n\t}\n\n\tpublic ModuleCoordinatesPacket setModulePos(LogisticsModule module) {\n\t\ttype = module.getSlot();\n\t\tpositionInt = module.getPositionInt();\n\t\tif (type.isInWorld()) {\n\t\t\tsetBlockPos(module.getBlockPos());\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic ModuleCoordinatesPacket setPacketPos(ModuleCoordinatesPacket packet) {\n\t\ttype = packet.type;\n\t\tpositionInt = packet.positionInt;\n\t\tsuper.setPacketPos(packet);\n\t\treturn this;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic <T> T getLogisticsModule(EntityPlayer player, Class<T> clazz) {\n\t\tLogisticsModule module;\n\t\tif (type == ModulePositionType.IN_PIPE) {\n\t\t\tmoduleBased = true;\n\t\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.NONE);\n\t\t\tmoduleBased = false;\n\t\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", pipe didn't exsist\", this);\n\t\t\t}\n\t\t\tmodule = ((CoreRoutedPipe) pipe.pipe).getLogisticsModule();\n\t\t} else if (type == ModulePositionType.IN_HAND) {\n\t\t\tif (MainProxy.isServer(player.getEntityWorld())) {\n\t\t\t\tif (player.openContainer instanceof DummyModuleContainer) {\n\t\t\t\t\tDummyModuleContainer dummy = (DummyModuleContainer) player.openContainer;\n\t\t\t\t\tmodule = dummy.getModule();\n\t\t\t\t} else if (player.openContainer instanceof ContainerPlayer) {\n\t\t\t\t\tmodule = ItemModule.getLogisticsModule(player, getPositionInt());\n\t\t\t\t\tif (module == null) {\n\t\t\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", module not found at slot \" + getPositionInt(), this);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", no DummyModuleContainer open and the player is in another GUI\", this);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tmodule = MainProxy.proxy.getModuleFromGui();\n\t\t\t\tif (module == null) {\n\t\t\t\t\tmodule = ItemModule.getLogisticsModule(player, getPositionInt());\n\t\t\t\t}\n\t\t\t\tif (module == null) {\n\t\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", GUI didn't provide the module and module not found at slot \" + getPositionInt(), this);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tmoduleBased = true;\n\t\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.NONE);\n\t\t\tmoduleBased = false;\n\t\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", pipe didn't exsist\", this);\n\t\t\t} else if (!pipe.isInitialized()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!(pipe.pipe instanceof PipeLogisticsChassis)) {\n\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", pipe wasn't a chassi pipe\", this);\n\t\t\t}\n\t\t\tmodule = ((PipeLogisticsChassis) pipe.pipe).getSubModule(positionInt);\n\t\t}\n\t\tif (module != null) {\n\t\t\tif (!(clazz.isAssignableFrom(module.getClass()))) {\n\t\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName() + \", found \" + module.getClass(), this);\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new TargetNotFoundException(\"Couldn't find \" + clazz.getName(), this);\n\t\t}\n\t\treturn (T) module;\n\t}\n\n\t@Override\n\tpublic <T> T getTileAs(World world, Class<T> clazz) {\n\t\tif (LogisticsPipes.isDEBUG() && !moduleBased && type != null) {\n\t\t\tnew Exception(\"ModulePacket was asked for a pipe\").printStackTrace();\n\t\t}\n\t\treturn super.getTileAs(world, clazz);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/NBTCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class NBTCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate NBTTagCompound tag;\n\n\tpublic NBTCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeNBTTagCompound(tag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttag = input.readNBTTagCompound();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/NBTModuleCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class NBTModuleCoordinatesPacket extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate NBTTagCompound tag;\n\n\tpublic NBTModuleCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeNBTTagCompound(tag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttag = input.readNBTTagCompound();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/RequestPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.packets.orderer.RequestSubmitPacket;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class RequestPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifierStack stack;\n\n\tpublic RequestPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestSubmitPacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeItemIdentifierStack(stack);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tstack = input.readItemIdentifierStack();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/SlotPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Slot;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class SlotPacket extends ModernPacket {\n\n\t@Setter(AccessLevel.PRIVATE)\n\t@Getter(AccessLevel.PROTECTED)\n\tprivate int integer;\n\n\tpublic SlotPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\tpublic <T extends Slot> T getSlot(EntityPlayer player, Class<T> clazz) {\n\t\tif (player.openContainer instanceof DummyContainer) {\n\t\t\tif (getInteger() >= player.openContainer.inventorySlots.size()) {\n\t\t\t\ttargetNotFound(\"The requested Slot was out of range\");\n\t\t\t} else {\n\t\t\t\tSlot slot = player.openContainer.getSlot(getInteger());\n\t\t\t\tif (slot == null) {\n\t\t\t\t\ttargetNotFound(\"The requested Slot was null\");\n\t\t\t\t} else if (!clazz.isAssignableFrom(slot.getClass())) {\n\t\t\t\t\ttargetNotFound(\"Couldn't find \" + clazz.getName() + \", found slot with \" + slot.getClass());\n\t\t\t\t} else {\n\t\t\t\t\treturn (T) slot;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic SlotPacket setSlot(Slot slot) {\n\t\tsetInteger(slot.slotNumber);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetInteger(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getInteger());\n\t}\n\n\tprotected void targetNotFound(String message) {\n\t\tthrow new TargetNotFoundException(message, this);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/StringCoordinatesPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class StringCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate String string;\n\n\tpublic StringCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUTF(getString());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetString(input.readUTF());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/abstractpackets/StringListPacket.java",
    "content": "package logisticspipes.network.abstractpackets;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic abstract class StringListPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate List<String> stringList = new ArrayList<>();\n\n\tpublic StringListPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tint size = input.readInt();\n\t\tfor (int i = 0; i < size; i++) {\n\t\t\tgetStringList().add(input.readUTF());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getStringList().size());\n\t\tfor (int i = 0; i < getStringList().size(); i++) {\n\t\t\toutput.writeUTF(getStringList().get(i));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/exception/DelayPacketException.java",
    "content": "package logisticspipes.network.exception;\n\npublic class DelayPacketException extends RuntimeException {\n\n\tpublic DelayPacketException(String message) {\n\t\tsuper(message);\n\t}\n\n\tpublic DelayPacketException() {\n\t\tsuper();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/exception/TargetNotFoundException.java",
    "content": "package logisticspipes.network.exception;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\n\npublic class TargetNotFoundException extends DelayPacketException {\n\n\tprivate static final long serialVersionUID = 8830733712757259675L;\n\n\tpublic TargetNotFoundException(String message, Object causedIn) {\n\t\tsuper(message);\n\t\tif (!LogisticsPipes.isDEBUG()) {\n\t\t\treturn;\n\t\t}\n\t\tif (causedIn instanceof ModernPacket) {\n\t\t\tStackTraceElement[] astacktraceelement = PacketHandler.debugMap.get(((ModernPacket) causedIn).getDebugId());\n\t\t\tif (astacktraceelement != null) {\n\t\t\t\tList<StackTraceElement> list = new ArrayList<>();\n\t\t\t\tfor (StackTraceElement element : getStackTrace()) {\n\t\t\t\t\tlist.add(element);\n\t\t\t\t\tif (element.getClassName().equals(\"logisticspipes.network.PacketHandler\")) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlist.remove(0);\n\t\t\t\tsetStackTrace(list.toArray(new StackTraceElement[0]));\n\t\t\t\tlist = new ArrayList<>(Arrays.asList(astacktraceelement));\n\t\t\t\tif (list.size() > 2) {\n\t\t\t\t\tlist.remove(0);\n\t\t\t\t\tlist.remove(0);\n\t\t\t\t}\n\t\t\t\tRuntimeException runtime = new RuntimeException(\"Packet was send from: \");\n\t\t\t\truntime.setStackTrace(list.toArray(new StackTraceElement[0]));\n\t\t\t\tinitCause(runtime);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/AddChannelGuiProvider.java",
    "content": "package logisticspipes.network.guis;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.popup.GuiAddChannelPopup;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.PopupGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class AddChannelGuiProvider extends PopupGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate UUID securityStationID;\n\n\tpublic AddChannelGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUUID(securityStationID);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsecurityStationID = input.readUUID();\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiAddChannelPopup(securityStationID);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new AddChannelGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/EditChannelGuiProvider.java",
    "content": "package logisticspipes.network.guis;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.popup.GuiEditChannelPopup;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.PopupGuiProvider;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class EditChannelGuiProvider extends PopupGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate ChannelInformation channel;\n\n\t@Getter\n\t@Setter\n\tprivate UUID responsibleSecurityID;\n\n\tpublic EditChannelGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeChannelInformation(channel);\n\t\toutput.writeUUID(responsibleSecurityID);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tchannel = input.readChannelInformation();\n\t\tresponsibleSecurityID = input.readUUID();\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiEditChannelPopup(responsibleSecurityID, channel);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new EditChannelGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/LogisticsPlayerSettingsGuiProvider.java",
    "content": "package logisticspipes.network.guis;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\n\nimport logisticspipes.gui.GuiLogisticsSettings;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class LogisticsPlayerSettingsGuiProvider extends GuiProvider {\n\n\tpublic LogisticsPlayerSettingsGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiLogisticsSettings(player);\n\t}\n\n\t@Override\n\tpublic Container getContainer(EntityPlayer player) {\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, null);\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0); // server does not care where the slots are\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new LogisticsPlayerSettingsGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/OpenGuideBook.java",
    "content": "package logisticspipes.network.guis;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumHand;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.guidebook.ItemGuideBook;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class OpenGuideBook extends ModernPacket {\n\n\tprivate EnumHand hand;\n\tprivate ItemStack stack;\n\n\tpublic OpenGuideBook(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\thand = input.readEnum(EnumHand.class);\n\t\tstack = input.readItemStack();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeEnum(hand);\n\t\toutput.writeItemStack(stack);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tItemGuideBook.openGuideBook(hand, stack);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenGuideBook(getId());\n\t}\n\n\t@Nonnull\n\tpublic OpenGuideBook setHand(@Nonnull EnumHand hand) {\n\t\tthis.hand = hand;\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\tpublic OpenGuideBook setStack(@Nonnull ItemStack stack) {\n\t\tthis.stack = stack;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/AutoCraftingGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport java.util.BitSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.gui.GuiLogisticsCraftingTable;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class AutoCraftingGui extends CoordinatesGuiProvider {\n\n\tboolean isFuzzy;\n\tBitSet fuzzyFlags = new BitSet(9 * 4);\n\tItemIdentifier targetType;\n\n\tpublic AutoCraftingGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsCraftingTableTileEntity tile = getTileAs(player.world, LogisticsCraftingTableTileEntity.class);\n\t\tif (tile.isFuzzy()) {\n\t\t\ttile.fuzzyFlags.replaceWith(fuzzyFlags);\n\t\t}\n\t\ttile.targetType = targetType;\n\t\treturn new GuiLogisticsCraftingTable(player, tile);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsCraftingTableTileEntity tile = getTileAs(player.world, LogisticsCraftingTableTileEntity.class);\n\t\tDummyContainer dummy = new DummyContainer(player, tile.matrix, tile);\n\n\t\tfor (int X = 0; X < 3; X++) {\n\t\t\tfor (int Y = 0; Y < 3; Y++) {\n\t\t\t\tdummy.addFuzzyDummySlot(Y * 3 + X, 35 + X * 18, 10 + Y * 18, tile.inputFuzzy(Y * 3 + X));\n\t\t\t}\n\t\t}\n\t\tdummy.addFuzzyUnmodifiableSlot(0, tile.resultInv, 125, 28, tile.outputFuzzy());\n\t\tfor (int Y = 0; Y < 2; Y++) {\n\t\t\tfor (int X = 0; X < 9; X++) {\n\t\t\t\tdummy.addNormalSlot(Y * 9 + X, tile.inv, 8 + X * 18, 80 + Y * 18);\n\t\t\t}\n\t\t}\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 135);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeItemIdentifier(targetType);\n\t\toutput.writeBoolean(isFuzzy);\n\t\tif (isFuzzy) {\n\t\t\toutput.writeBitSet(fuzzyFlags);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttargetType = input.readItemIdentifier();\n\t\tif (input.readBoolean()) {\n\t\t\tfuzzyFlags = input.readBitSet();\n\t\t}\n\t}\n\n\tpublic AutoCraftingGui setCraftingTable(LogisticsCraftingTableTileEntity tile) {\n\t\tsetTilePos(tile);\n\t\tif (tile.isFuzzy()) {\n\t\t\tisFuzzy = true;\n\t\t\tfuzzyFlags = tile.fuzzyFlags.copyValue(0, (9 * 4) - 1);\n\t\t}\n\t\ttargetType = tile.targetType;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new AutoCraftingGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/PowerJunctionGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.gui.GuiPowerJunction;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class PowerJunctionGui extends CoordinatesGuiProvider {\n\n\tpublic PowerJunctionGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiPowerJunction(player, getTileAs(player.world, LogisticsPowerJunctionTileEntity.class));\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyContainer dummy = new DummyContainer(player, null, getTileAs(player.world, LogisticsPowerJunctionTileEntity.class));\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 80);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new PowerJunctionGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/PowerProviderGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerProviderTileEntity;\nimport logisticspipes.gui.GuiPowerProvider;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class PowerProviderGui extends CoordinatesGuiProvider {\n\n\tpublic PowerProviderGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiPowerProvider(player, getTileAs(player.world, LogisticsPowerProviderTileEntity.class));\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyContainer dummy = new DummyContainer(player, null, getTileAs(player.world, LogisticsPowerProviderTileEntity.class));\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 80);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new PowerProviderGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/ProgramCompilerGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.gui.GuiProgramCompiler;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class ProgramCompilerGui extends CoordinatesGuiProvider {\n\n\tpublic ProgramCompilerGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiProgramCompiler(player, getTileAs(player.world, LogisticsProgramCompilerTileEntity.class));\n\t}\n\n\t@Override\n\tpublic Container getContainer(EntityPlayer player) {\n\t\tLogisticsProgramCompilerTileEntity compilerBlock = getTileAs(player.world, LogisticsProgramCompilerTileEntity.class);\n\t\tDummyContainer dummy = new DummyContainer(player, null, compilerBlock);\n\n\t\tdummy.addRestrictedSlot(0, compilerBlock.getInventory(), 10, 10, LPItems.disk);\n\t\tdummy.addRestrictedSlot(1, compilerBlock.getInventory(), 154, 10, LPItems.logisticsProgrammer);\n\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 45);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ProgramCompilerGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/SecurityChannelManagerGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.gui.popup.GuiManageChannelPopup;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractpackets.ChannelInformationListCoordinatesPopupGuiProvider;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityChannelManagerGui extends ChannelInformationListCoordinatesPopupGuiProvider {\n\n\tpublic SecurityChannelManagerGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiManageChannelPopup(getChannelInformations(), getTileAs(player.world, LogisticsSecurityTileEntity.class).getPos());\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SecurityChannelManagerGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/SecurityStationGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.gui.GuiSecurityStation;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class SecurityStationGui extends CoordinatesGuiProvider {\n\n\tpublic SecurityStationGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiSecurityStation(getTileAs(player.world, LogisticsSecurityTileEntity.class), player);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity securityStation = getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tDummyContainer dummy = new DummyContainer(player, null, securityStation);\n\t\tdummy.addRestrictedSlot(0, securityStation.inv, 50, 50, (Item) null);\n\t\tdummy.addNormalSlotsForPlayerInventory(10, 210);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SecurityStationGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/block/StatisticsGui.java",
    "content": "package logisticspipes.network.guis.block;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.blocks.stats.TrackingTask;\nimport logisticspipes.gui.GuiStatistics;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class StatisticsGui extends CoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate List<TrackingTask> trackingList;\n\n\tpublic StatisticsGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsStatisticsTileEntity statisticsTable = getTileAs(player.world, LogisticsStatisticsTileEntity.class);\n\t\tstatisticsTable.tasks = trackingList;\n\t\tGuiStatistics gui = new GuiStatistics(statisticsTable);\n\t\tgui.inventorySlots = new DummyContainer(player.inventory, null);\n\t\treturn gui;\n\t}\n\n\t@Override\n\tpublic Container getContainer(EntityPlayer player) {\n\t\t// ensures tile at position is a statistics table\n\t\tgetTileAs(player.world, LogisticsStatisticsTileEntity.class);\n\t\treturn new DummyContainer(player, null);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new StatisticsGui(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(trackingList, (output1, object) -> object.writeToLPData(output1));\n\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttrackingList = input.readArrayList(data1 -> {\n\t\t\tTrackingTask object = new TrackingTask();\n\t\t\tobject.readFromLPData(data1);\n\t\t\treturn object;\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/item/ItemAmountSignGui.java",
    "content": "package logisticspipes.network.guis.item;\n\nimport java.util.Objects;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.ItemAmountSignCreationGui;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.signs.ItemAmountPipeSign;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ItemAmountSignGui extends CoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate EnumFacing dir;\n\n\tpublic ItemAmountSignGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new ItemAmountSignCreationGui(player, (CoreRoutedPipe) pipe.pipe, dir);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\tItemAmountPipeSign sign = ((ItemAmountPipeSign) ((CoreRoutedPipe) pipe.pipe).getPipeSign(dir));\n\t\tObjects.requireNonNull(sign);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, sign.itemTypeInv);\n\t\tdummy.addDummySlot(0, 0, 0);\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeFacing(dir);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tdir = input.readFacing();\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ItemAmountSignGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/item/ItemMangerGui.java",
    "content": "package logisticspipes.network.guis.item;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.gui.GuiCardManager;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.CardManagementInventory;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class ItemMangerGui extends GuiProvider {\n\n\tpublic ItemMangerGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\treturn new GuiCardManager(player);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tfinal CardManagementInventory Cinv = new CardManagementInventory();\n\t\tDummyContainer dummy = new DummyContainer(player, Cinv, new IGuiOpenControler() {\n\n\t\t\t@Override\n\t\t\tpublic void guiOpenedByPlayer(EntityPlayer player) {}\n\n\t\t\t@Override\n\t\t\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\t\t\tCinv.close(player, (int) player.posX, (int) player.posY, (int) player.posZ);\n\t\t\t}\n\t\t});\n\t\tfor (int i = 0; i < 2; i++) {\n\t\t\tdummy.addRestrictedSlot(i, Cinv, 0, 0, ItemModule.class);\n\t\t}\n\t\tdummy.addRestrictedSlot(2, Cinv, 0, 0, itemStack -> false);\n\t\tdummy.addRestrictedSlot(3, Cinv, 0, 0, LPItems.itemCard);\n\t\tfor (int i = 4; i < 10; i++) {\n\t\t\tdummy.addColorSlot(i, Cinv, 0, 0);\n\t\t}\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ItemMangerGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/logic/LogicControllerGuiProvider.java",
    "content": "package logisticspipes.network.guis.logic;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.logic.gui.LogicLayoutGui;\nimport logisticspipes.logic.interfaces.ILogicControllerTile;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class LogicControllerGuiProvider extends CoordinatesGuiProvider {\n\n\tpublic LogicControllerGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tTileEntity pipe = getTileAs(player.world, TileEntity.class);\n\t\tif (pipe instanceof ILogicControllerTile) {\n\t\t\treturn new LogicLayoutGui(((ILogicControllerTile) pipe).getLogicController(), player);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Container getContainer(EntityPlayer player) {\n\t\tTileEntity pipe = getTileAs(player.world, TileEntity.class);\n\t\tif (pipe instanceof ILogicControllerTile) {\n\t\t\tDummyContainer dummy = new DummyContainer(player.inventory, null);\n\t\t\tdummy.addNormalSlotsForPlayerInventory(50, 190);\n\t\t\treturn dummy;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new LogicControllerGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/ActiveSupplierInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.GuiSupplierPipe;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\n\n@StaticResolve\npublic class ActiveSupplierInHand extends ModuleInHandGuiProvider {\n\n\tpublic ActiveSupplierInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof ModuleActiveSupplier)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiSupplierPipe(player.inventory,\n\t\t\t\t((ModuleActiveSupplier) module).inventory,\n\t\t\t\t(ModuleActiveSupplier) module,\n\t\t\t\tfalse,\n\t\t\t\tnew int[9]);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof ModuleActiveSupplier)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(((ModuleActiveSupplier) dummy.getModule()).inventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ActiveSupplierInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/AdvancedExtractorModuleInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiAdvancedExtractor;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\n\n@StaticResolve\npublic class AdvancedExtractorModuleInHand extends ModuleInHandGuiProvider {\n\n\tpublic AdvancedExtractorModuleInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof AsyncAdvancedExtractor)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiAdvancedExtractor(player.inventory, (AsyncAdvancedExtractor) module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof AsyncAdvancedExtractor)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(((AsyncAdvancedExtractor) dummy.getModule()).getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new AdvancedExtractorModuleInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/CraftingModuleInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.GuiCraftingPipe;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CraftingModuleInHand extends ModuleInHandGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate int[] amount;\n\n\t@Getter\n\t@Setter\n\tprivate boolean cleanupExclude;\n\n\tpublic CraftingModuleInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof ModuleCrafter)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiCraftingPipe(player, ((ModuleCrafter) module), false, 0, amount, false, false, 0,\n\t\t\t\tcleanupExclude);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof ModuleCrafter)) {\n\t\t\treturn null;\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(((ModuleCrafter) dummy.getModule()).getCPipePacket(), player);\n\t\tdummy.setInventory(((ModuleCrafter) dummy.getModule()).dummyInventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\t\t//Input slots\n\t\tfor (int l = 0; l < 9; l++) {\n\t\t\tdummy.addFuzzyDummySlot(l, 18 + l * 18, 18, ((ModuleCrafter) dummy.getModule()).inputFuzzy(l));\n\t\t}\n\n\t\t//Output slot\n\t\tdummy.addFuzzyDummySlot(9, 90, 64, ((ModuleCrafter) dummy.getModule()).outputFuzzy());\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new CraftingModuleInHand(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeIntArray(amount);\n\t\toutput.writeBoolean(cleanupExclude);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tamount = input.readIntArray();\n\t\tcleanupExclude = input.readBoolean();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/ItemSinkInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.gui.module.ItemSinkGui;\n\n@StaticResolve\npublic class ItemSinkInHand extends ModuleInHandGuiProvider {\n\n\tpublic ItemSinkInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof ModuleItemSink)) {\n\t\t\treturn null;\n\t\t}\n\t\tItemStack usedItemStack = (player.getHeldItemMainhand().getItem() instanceof ItemModule) ?\n\t\t\t\tplayer.getHeldItemMainhand() : (player.getHeldItemOffhand().getItem() instanceof ItemModule) ?\n\t\t\t\tplayer.getHeldItemOffhand() : ItemStack.EMPTY;\n\t\treturn ItemSinkGui.create(player.inventory, (ModuleItemSink) module, usedItemStack, false, true);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof ModuleItemSink)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(((ModuleItemSink) dummy.getModule()).getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ItemSinkInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/OreDictItemSinkModuleInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiOreDictItemSink;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\n@StaticResolve\npublic class OreDictItemSinkModuleInHand extends ModuleInHandGuiProvider {\n\n\tpublic OreDictItemSinkModuleInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof ModuleOreDictItemSink)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiOreDictItemSink(player.inventory, (ModuleOreDictItemSink) module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof ModuleOreDictItemSink)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(new ItemIdentifierInventory(1, \"TMP\", 1));\n\t\tdummy.addDummySlot(0, 0, 0);\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new OreDictItemSinkModuleInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/ProviderModuleInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport network.rs485.logisticspipes.gui.module.ProviderGui;\n\n@StaticResolve\npublic class ProviderModuleInHand extends ModuleInHandGuiProvider {\n\n\tpublic ProviderModuleInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tfinal LogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof ModuleProvider)) {\n\t\t\treturn null;\n\t\t}\n\t\tItemStack usedItemStack = (player.getHeldItemMainhand().getItem() instanceof ItemModule) ?\n\t\t\t\tplayer.getHeldItemMainhand() : (player.getHeldItemOffhand().getItem() instanceof ItemModule) ?\n\t\t\t\tplayer.getHeldItemOffhand() : ItemStack.EMPTY;\n\t\treturn ProviderGui.create(player.inventory, (ModuleProvider) module, usedItemStack);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof ModuleProvider)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(((ModuleProvider) dummy.getModule()).filterInventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\n\t\tint xOffset = 72;\n\t\tint yOffset = 18;\n\n\t\tfor (int row = 0; row < 3; row++) {\n\t\t\tfor (int column = 0; column < 3; column++) {\n\t\t\t\tdummy.addDummySlot(column + row * 3, xOffset + column * 18, yOffset + row * 18);\n\t\t\t}\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ProviderModuleInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/SimpleFilterInventoryInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiSimpleFilter;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SimpleFilter;\n\n@StaticResolve\npublic class SimpleFilterInventoryInHand extends ModuleInHandGuiProvider {\n\n\tpublic SimpleFilterInventoryInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof Gui && module instanceof SimpleFilter)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiSimpleFilter(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof SimpleFilter)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(((SimpleFilter) dummy.getModule()).getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SimpleFilterInventoryInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/SneakyModuleInHandGuiProvider.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiSneakyConfigurator;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SneakyDirection;\n\n@StaticResolve\npublic class SneakyModuleInHandGuiProvider extends ModuleInHandGuiProvider {\n\n\tpublic SneakyModuleInHandGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof Gui && module instanceof SneakyDirection)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiSneakyConfigurator(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof SneakyDirection)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SneakyModuleInHandGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inhand/StringBasedItemSinkModuleGuiInHand.java",
    "content": "package logisticspipes.network.guis.module.inhand;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiStringBasedItemSink;\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\n@StaticResolve\npublic class StringBasedItemSinkModuleGuiInHand extends ModuleInHandGuiProvider {\n\n\tpublic StringBasedItemSinkModuleGuiInHand(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = ItemModule.getLogisticsModule(player, getInvSlot());\n\t\tif (!(module instanceof IStringBasedModule)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiStringBasedItemSink(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tDummyModuleContainer dummy = new DummyModuleContainer(player, getInvSlot());\n\t\tif (!(dummy.getModule() instanceof IStringBasedModule)) {\n\t\t\treturn null;\n\t\t}\n\t\tdummy.setInventory(new ItemIdentifierInventory(1, \"TMP\", 1));\n\t\tdummy.addDummySlot(0, 0, 0);\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new StringBasedItemSinkModuleGuiInHand(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/ActiveSupplierSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.GuiSupplierPipe;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.modules.ModuleActiveSupplier.PatternMode;\nimport logisticspipes.modules.ModuleActiveSupplier.SupplyMode;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ActiveSupplierSlot extends ModuleCoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate boolean patternUpgarde;\n\n\t@Getter\n\t@Setter\n\tprivate int[] slotArray;\n\n\t@Getter\n\t@Setter\n\tprivate boolean isLimit;\n\n\t@Getter\n\t@Setter\n\tprivate int mode;\n\n\tpublic ActiveSupplierSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(patternUpgarde);\n\t\toutput.writeIntArray(slotArray);\n\t\toutput.writeBoolean(isLimit);\n\t\toutput.writeInt(mode);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tpatternUpgarde = input.readBoolean();\n\t\tslotArray = input.readIntArray();\n\t\tisLimit = input.readBoolean();\n\t\tmode = input.readInt();\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tModuleActiveSupplier module = this.getLogisticsModule(player.getEntityWorld(), ModuleActiveSupplier.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tmodule.isLimited.setValue(isLimit);\n\t\tif (patternUpgarde) {\n\t\t\tmodule.patternMode.setValue(PatternMode.values()[mode]);\n\t\t} else {\n\t\t\tmodule.requestMode.setValue(SupplyMode.values()[mode]);\n\t\t}\n\t\tmodule.slotAssignmentPattern.replaceContent(slotArray);\n\t\treturn new GuiSupplierPipe(player.inventory, module.inventory, module, patternUpgarde, slotArray);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tModuleActiveSupplier module = this.getLogisticsModule(player.getEntityWorld(), ModuleActiveSupplier.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, module.inventory);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\n\t\tfor (int row = 0; row < 3; row++) {\n\t\t\tfor (int column = 0; column < 3; column++) {\n\t\t\t\tdummy.addDummySlot(column + row * 3, 72 + column * 18, 18 + row * 18);\n\t\t\t}\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ActiveSupplierSlot(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/AdvancedExtractorModuleSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiAdvancedExtractor;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class AdvancedExtractorModuleSlot extends ModuleCoordinatesGuiProvider {\n\n\tprivate boolean areItemsIncluded;\n\n\tpublic AdvancedExtractorModuleSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tAsyncAdvancedExtractor module = this.getLogisticsModule(player.getEntityWorld(), AsyncAdvancedExtractor.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tmodule.getItemsIncluded().setValue(areItemsIncluded);\n\t\treturn new GuiAdvancedExtractor(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\treturn SimpleFilterInventorySlot.getContainerFromFilterModule(this, player);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new AdvancedExtractorModuleSlot(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(areItemsIncluded);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tareItemsIncluded = input.readBoolean();\n\t}\n\n\tpublic boolean isAreItemsIncluded() {\n\t\treturn this.areItemsIncluded;\n\t}\n\n\tpublic AdvancedExtractorModuleSlot setAreItemsIncluded(boolean areItemsIncluded) {\n\t\tthis.areItemsIncluded = areItemsIncluded;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/CraftingModuleSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.GuiCraftingPipe;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CraftingModuleSlot extends ModuleCoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate boolean isAdvancedSat;\n\n\t@Getter\n\t@Setter\n\tprivate int liquidCrafter;\n\n\t@Getter\n\t@Setter\n\tprivate int[] amount;\n\n\t@Getter\n\t@Setter\n\tprivate boolean hasByproductExtractor;\n\n\t@Getter\n\t@Setter\n\tprivate boolean isFuzzy;\n\n\t@Getter\n\t@Setter\n\tprivate int cleanupSize;\n\n\t@Getter\n\t@Setter\n\tprivate boolean cleanupExclude;\n\n\tpublic CraftingModuleSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player.getEntityWorld(), ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiCraftingPipe(player, module, isAdvancedSat, liquidCrafter, amount, hasByproductExtractor, isFuzzy,\n\t\t\t\tcleanupSize, cleanupExclude);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player.getEntityWorld(), ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(module.getCPipePacket(), player);\n\t\tDummyContainer dummy = new DummyContainer(player, module.dummyInventory, module);\n\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\t\t//Input slots\n\t\tfor (int l = 0; l < 9; l++) {\n\t\t\tdummy.addFuzzyDummySlot(l, 18 + l * 18, 18, module.inputFuzzy(l));\n\t\t}\n\n\t\t//Output slot\n\t\tdummy.addFuzzyDummySlot(9, 90, 64, module.outputFuzzy());\n\n\t\tfor (int i = 0; i < liquidCrafter; i++) {\n\t\t\tint liquidLeft = -(i * 40) - 40;\n\t\t\tdummy.addFluidSlot(i, module.liquidInventory, liquidLeft + 13, 42);\n\t\t}\n\n\t\tif (hasByproductExtractor) {\n\t\t\tdummy.addDummySlot(10, 197, 104);\n\t\t}\n\n\t\tfor (int Y = 0; Y < cleanupSize; Y++) {\n\t\t\tfor (int X = 0; X < 3; X++) {\n\t\t\t\tdummy.addDummySlot(Y * 3 + X, module.cleanupInventory, X * 18 - 57, Y * 18 + 13);\n\t\t\t}\n\t\t}\n\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new CraftingModuleSlot(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(isAdvancedSat);\n\t\toutput.writeInt(liquidCrafter);\n\t\toutput.writeIntArray(amount);\n\t\toutput.writeBoolean(hasByproductExtractor);\n\t\toutput.writeBoolean(isFuzzy);\n\t\toutput.writeInt(cleanupSize);\n\t\toutput.writeBoolean(cleanupExclude);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tisAdvancedSat = input.readBoolean();\n\t\tliquidCrafter = input.readInt();\n\t\tamount = input.readIntArray();\n\t\thasByproductExtractor = input.readBoolean();\n\t\tisFuzzy = input.readBoolean();\n\t\tcleanupSize = input.readInt();\n\t\tcleanupExclude = input.readBoolean();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/FluidSupplierSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiFluidSupplier;\nimport logisticspipes.modules.ModuleFluidSupplier;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class FluidSupplierSlot extends ModuleCoordinatesGuiProvider {\n\n\tpublic FluidSupplierSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tModuleFluidSupplier module = this.getLogisticsModule(player.getEntityWorld(), ModuleFluidSupplier.class);\n\t\treturn new GuiFluidSupplier(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tModuleFluidSupplier module = this.getLogisticsModule(player.getEntityWorld(), ModuleFluidSupplier.class);\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, module.getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new FluidSupplierSlot(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/ItemSinkSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport java.util.BitSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.gui.module.ItemSinkGui;\nimport network.rs485.logisticspipes.inventory.container.ItemSinkContainer;\nimport network.rs485.logisticspipes.property.layer.PropertyLayer;\nimport network.rs485.logisticspipes.property.layer.SimplePropertyOverlay;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ItemSinkSlot extends ModuleCoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate boolean isDefaultRoute;\n\n\t@Getter\n\t@Setter\n\tprivate boolean hasFuzzyUpgrade;\n\n\t@Getter\n\t@Setter\n\tprivate BitSet fuzzyFlags;\n\n\tpublic ItemSinkSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(isDefaultRoute);\n\t\toutput.writeBoolean(hasFuzzyUpgrade);\n\t\toutput.writeBitSet(fuzzyFlags);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tisDefaultRoute = input.readBoolean();\n\t\thasFuzzyUpgrade = input.readBoolean();\n\t\tfuzzyFlags = input.readBitSet();\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tModuleItemSink module = this.getLogisticsModule(player.getEntityWorld(), ModuleItemSink.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tmodule.setDefaultRoute(isDefaultRoute);\n\t\tmodule.setFuzzyFlags(fuzzyFlags);\n\n\t\treturn ItemSinkGui.create(player.inventory, module, ItemStack.EMPTY, hasFuzzyUpgrade, false);\n\t}\n\n\t@Override\n\tpublic ItemSinkContainer getContainer(EntityPlayer player) {\n\t\tModuleItemSink module = this.getLogisticsModule(player.getEntityWorld(), ModuleItemSink.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new ItemSinkContainer(\n\t\t\tplayer.inventory,\n\t\t\tnew SimplePropertyOverlay<>(module.filterInventory),\n\t\t\tmodule,\n\t\t\tnew PropertyLayer(module.getProperties()),\n\t\t\thasFuzzyUpgrade,\n\t\t\tItemStack.EMPTY\n\t\t);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ItemSinkSlot(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/OreDictItemSinkModuleSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiOreDictItemSink;\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.NBTModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\n@StaticResolve\npublic class OreDictItemSinkModuleSlot extends NBTModuleCoordinatesGuiProvider {\n\n\tpublic OreDictItemSinkModuleSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tModuleOreDictItemSink module = this.getLogisticsModule(player.getEntityWorld(), ModuleOreDictItemSink.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tmodule.readFromNBT(getNbt());\n\t\treturn new GuiOreDictItemSink(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tModuleOreDictItemSink module = this.getLogisticsModule(player.getEntityWorld(), ModuleOreDictItemSink.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, new ItemIdentifierInventory(1, \"TMP\", 1));\n\t\tdummy.addDummySlot(0, 0, 0);\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new OreDictItemSinkModuleSlot(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/ProviderModuleGuiProvider.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.gui.module.ProviderGui;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\nimport network.rs485.logisticspipes.inventory.container.ProviderContainer;\nimport network.rs485.logisticspipes.property.layer.SimplePropertyOverlay;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ProviderModuleGuiProvider extends ModuleCoordinatesGuiProvider {\n\n\t@Getter\n\t@Setter\n\tprivate boolean exclude;\n\n\t@Getter\n\t@Setter\n\tprivate int extractorMode;\n\n\t@Getter\n\t@Setter\n\tprivate boolean isActive;\n\n\t@Getter\n\t@Setter\n\tprivate EnumFacing sneakyOrientation;\n\n\tpublic ProviderModuleGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tModuleProvider module = this.getLogisticsModule(player.getEntityWorld(), ModuleProvider.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tmodule.isExclusionFilter.setValue(exclude);\n\t\tmodule.providerMode.setValue(ProviderMode.modeFromIntSafe(extractorMode));\n\t\tmodule.setSneakyDirection(sneakyOrientation);\n\t\tmodule.isActive.setValue(isActive);\n\t\treturn ProviderGui.create(player.inventory, module, ItemStack.EMPTY);\n\t}\n\n\t@Override\n\tpublic ProviderContainer getContainer(EntityPlayer player) {\n\t\tModuleProvider module = this.getLogisticsModule(player.getEntityWorld(), ModuleProvider.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new ProviderContainer(module, player.inventory, new SimplePropertyOverlay<>(module.filterInventory), ItemStack.EMPTY);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ProviderModuleGuiProvider(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(exclude);\n\t\toutput.writeInt(extractorMode);\n\t\toutput.writeBoolean(isActive);\n\t\toutput.writeFacing(sneakyOrientation);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\texclude = input.readBoolean();\n\t\textractorMode = input.readInt();\n\t\tisActive = input.readBoolean();\n\t\tsneakyOrientation = input.readFacing();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/SimpleFilterInventorySlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiSimpleFilter;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.module.SimpleFilter;\n\n@StaticResolve\npublic class SimpleFilterInventorySlot extends ModuleCoordinatesGuiProvider {\n\n\tpublic SimpleFilterInventorySlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = this.getLogisticsModule(player.getEntityWorld(), LogisticsModule.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiSimpleFilter(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\treturn getContainerFromFilterModule(this, player);\n\t}\n\n\t@Nullable\n\tpublic static DummyContainer getContainerFromFilterModule(ModuleCoordinatesGuiProvider guiProvider, EntityPlayer player) {\n\t\tSimpleFilter filter = guiProvider.getLogisticsModule(player.getEntityWorld(), SimpleFilter.class);\n\t\tif (filter == null) {\n\t\t\treturn null;\n\t\t}\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, filter.getFilterInventory());\n\t\tdummy.addNormalSlotsForPlayerInventory(8, 60);\n\n\t\t//Pipe slots\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addDummySlot(pipeSlot, 8 + pipeSlot * 18, 18);\n\t\t}\n\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SimpleFilterInventorySlot(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/SneakyModuleInSlotGuiProvider.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.gui.modules.GuiSneakyConfigurator;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.module.SneakyDirection;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SneakyModuleInSlotGuiProvider extends ModuleCoordinatesGuiProvider {\n\n\tprivate EnumFacing sneakyOrientation;\n\n\tpublic SneakyModuleInSlotGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\tpublic SneakyModuleInSlotGuiProvider setSneakyOrientation(EnumFacing sneakyOrientation) {\n\t\tthis.sneakyOrientation = sneakyOrientation;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeFacing(sneakyOrientation);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsneakyOrientation = input.readFacing();\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = this.getLogisticsModule(player.getEntityWorld(), LogisticsModule.class);\n\t\tif (!(module instanceof SneakyDirection && module instanceof Gui)) {\n\t\t\treturn null;\n\t\t}\n\t\t((SneakyDirection) module).setSneakyDirection(sneakyOrientation);\n\t\treturn new GuiSneakyConfigurator(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsModule module = this.getLogisticsModule(player.getEntityWorld(), LogisticsModule.class);\n\t\tif (!(module instanceof SneakyDirection && module instanceof Gui)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new DummyContainer(player.inventory, null);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SneakyModuleInSlotGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/module/inpipe/StringBasedItemSinkModuleGuiSlot.java",
    "content": "package logisticspipes.network.guis.module.inpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.modules.GuiStringBasedItemSink;\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.NBTModuleCoordinatesGuiProvider;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\n@StaticResolve\npublic class StringBasedItemSinkModuleGuiSlot extends NBTModuleCoordinatesGuiProvider {\n\n\tpublic StringBasedItemSinkModuleGuiSlot(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsModule module = this.getLogisticsModule(player.getEntityWorld(), LogisticsModule.class);\n\t\tif (!(module instanceof IStringBasedModule)) {\n\t\t\treturn null;\n\t\t}\n\t\tmodule.readFromNBT(getNbt());\n\t\treturn new GuiStringBasedItemSink(player.inventory, module);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tIStringBasedModule module = this.getLogisticsModule(player.getEntityWorld(), IStringBasedModule.class);\n\t\tif (module == null) {\n\t\t\treturn null;\n\t\t}\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, new ItemIdentifierInventory(1, \"TMP\", 1));\n\t\tdummy.addDummySlot(0, 0, 0);\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new StringBasedItemSinkModuleGuiSlot(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/pipe/ChassisGuiProvider.java",
    "content": "package logisticspipes.network.guis.pipe;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.gui.GuiChassisPipe;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractguis.BooleanModuleCoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.upgrades.ModuleUpgradeManager;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class ChassisGuiProvider extends BooleanModuleCoordinatesGuiProvider {\n\n\tpublic ChassisGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof PipeLogisticsChassis)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiChassisPipe(player, (PipeLogisticsChassis) pipe.pipe, isFlag());\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof PipeLogisticsChassis)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal PipeLogisticsChassis _chassiPipe = (PipeLogisticsChassis) pipe.pipe;\n\t\tIInventory _moduleInventory = _chassiPipe.getModuleInventory();\n\t\tDummyContainer dummy = new DummyContainer(player.inventory, _moduleInventory);\n\t\tif (_chassiPipe.getChassisSize() < 5) {\n\t\t\tdummy.addNormalSlotsForPlayerInventory(18, 97);\n\t\t} else {\n\t\t\tdummy.addNormalSlotsForPlayerInventory(18, 174);\n\t\t}\n\t\tfor (int i = 0; i < _chassiPipe.getChassisSize(); i++) {\n\t\t\tdummy.addModuleSlot(i, _moduleInventory, 19, 9 + 20 * i, _chassiPipe);\n\t\t}\n\n\t\tif (_chassiPipe.getUpgradeManager().hasUpgradeModuleUpgrade()) {\n\t\t\tfor (int i = 0; i < _chassiPipe.getChassisSize(); i++) {\n\t\t\t\tfinal int fI = i;\n\t\t\t\tModuleUpgradeManager upgradeManager = _chassiPipe.getModuleUpgradeManager(i);\n\t\t\t\tdummy.addUpgradeSlot(0, upgradeManager, 0, 145, 9 + i * 20, itemStack -> ChassisGuiProvider.checkStack(itemStack, _chassiPipe, fI));\n\t\t\t\tdummy.addUpgradeSlot(1, upgradeManager, 1, 165, 9 + i * 20, itemStack -> ChassisGuiProvider.checkStack(itemStack, _chassiPipe, fI));\n\t\t\t}\n\t\t}\n\t\treturn dummy;\n\t}\n\n\tpublic static boolean checkStack(@Nonnull ItemStack stack, PipeLogisticsChassis chassiPipe, int moduleSlot) {\n\t\tif (stack.isEmpty() || !(stack.getItem() instanceof ItemUpgrade)) {\n\t\t\treturn false;\n\t\t}\n\t\tLogisticsModule module = chassiPipe.getModules().getModule(moduleSlot);\n\t\tif (module == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn ((ItemUpgrade) stack.getItem()).getUpgradeForItem(stack, null).isAllowedForModule(module);\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new ChassisGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/pipe/InvSysConGuiProvider.java",
    "content": "package logisticspipes.network.guis.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.GuiInvSysConnector;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class InvSysConGuiProvider extends CoordinatesGuiProvider {\n\n\tpublic InvSysConGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof PipeItemsInvSysConnector)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiInvSysConnector(player, (PipeItemsInvSysConnector) pipe.pipe);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof PipeItemsInvSysConnector)) {\n\t\t\treturn null;\n\t\t}\n\t\tDummyContainer dummy = new DummyContainer(player, null, (PipeItemsInvSysConnector) pipe.pipe);\n\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 50);\n\n\t\treturn dummy;\n\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new InvSysConGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/pipe/InvSysConSelectChannelPopupGUIProvider.java",
    "content": "package logisticspipes.network.guis.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.popup.GuiSelectChannelPopup;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractpackets.ChannelInformationListCoordinatesPopupGuiProvider;\nimport logisticspipes.network.packets.pipe.InvSysConSetChannelOnPipePacket;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class InvSysConSelectChannelPopupGUIProvider extends ChannelInformationListCoordinatesPopupGuiProvider {\n\n\tpublic InvSysConSelectChannelPopupGUIProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe bPipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(bPipe.pipe instanceof PipeItemsInvSysConnector)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn new GuiSelectChannelPopup(getChannelInformations(), bPipe.getBlockPos(), sel -> {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(InvSysConSetChannelOnPipePacket.class)\n\t\t\t\t\t.setString(sel.getChannelIdentifier().toString())\n\t\t\t\t\t.setTilePos(bPipe));\n\t\t});\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new InvSysConSelectChannelPopupGUIProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/pipe/PipeController.java",
    "content": "package logisticspipes.network.guis.pipe;\n\nimport java.util.Objects;\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.gui.GuiPipeController;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.network.abstractguis.CoordinatesGuiProvider;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\nimport logisticspipes.pipes.upgrades.SneakyUpgradeConfig;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyContainer;\n\n@StaticResolve\npublic class PipeController extends CoordinatesGuiProvider {\n\n\tpublic PipeController(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new GuiPipeController(player, (CoreRoutedPipe) pipe.pipe);\n\t}\n\n\t@Override\n\tpublic DummyContainer getContainer(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(tile.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal CoreRoutedPipe pipe = (CoreRoutedPipe) tile.pipe;\n\t\tDummyContainer dummy = new DummyContainer(player, null, pipe.getOriginalUpgradeManager().getGuiController(), new IGuiOpenControler() {\n\n\t\t\t//Network Statistics\n\t\t\t@Override\n\t\t\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\t\t\tpipe.playerStartWatching(player, 0);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\t\t\tpipe.playerStopWatching(player, 0);\n\t\t\t}\n\t\t});\n\t\tdummy.addNormalSlotsForPlayerInventory(0, 0);\n\t\t// TAB_1 SLOTS\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addUpgradeSlot(pipeSlot, pipe.getOriginalUpgradeManager(), pipeSlot, 8 + pipeSlot * 18, 18, itemStack ->\n\t\t\t\t\t!itemStack.isEmpty() && itemStack.getItem() instanceof ItemUpgrade && ((ItemUpgrade) itemStack.getItem()).getUpgradeForItem(itemStack, null).isAllowedForPipe(pipe));\n\t\t}\n\t\tfor (int pipeSlot = 0; pipeSlot < 9; pipeSlot++) {\n\t\t\tdummy.addSneakyUpgradeSlot(pipeSlot, pipe.getOriginalUpgradeManager(), pipeSlot + 9, 8 + pipeSlot * 18, 48, itemStack -> {\n\t\t\t\tif (itemStack.isEmpty()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (itemStack.getItem() instanceof ItemUpgrade) {\n\t\t\t\t\tIPipeUpgrade upgrade = ((ItemUpgrade) itemStack.getItem()).getUpgradeForItem(itemStack, null);\n\t\t\t\t\treturn upgrade instanceof SneakyUpgradeConfig && upgrade.isAllowedForPipe(pipe);\n\t\t\t\t} else {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t// TAB_2 SLOTS\n\t\tdummy.addStaticRestrictedSlot(0, pipe.getOriginalUpgradeManager().secInv, 8 + 8 * 18, 18, itemStack -> {\n\t\t\tif (itemStack.isEmpty()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (itemStack.getItem() != LPItems.itemCard) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (itemStack.getItemDamage() != LogisticsItemCard.SEC_CARD) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfinal NBTTagCompound tag = Objects.requireNonNull(itemStack.getTagCompound());\n\t\t\treturn SimpleServiceLocator.securityStationManager.isAuthorized(UUID.fromString(tag.getString(\"UUID\")));\n\t\t}, 1);\n\t\tdummy.addRestrictedSlot(0, tile.logicController.diskInv, 14, 36, LPItems.disk);\n\t\treturn dummy;\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new PipeController(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/upgrade/DisconnectionUpgradeConfigGuiProvider.java",
    "content": "package logisticspipes.network.guis.upgrade;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.popup.DisconnectionConfigurationPopup;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.UpgradeCoordinatesGuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.UpgradeSlot;\n\n@StaticResolve\npublic class DisconnectionUpgradeConfigGuiProvider extends UpgradeCoordinatesGuiProvider {\n\n\tpublic DisconnectionUpgradeConfigGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe bPipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(bPipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn new DisconnectionConfigurationPopup((CoreRoutedPipe) bPipe.pipe, getSlot(player, UpgradeSlot.class));\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new DisconnectionUpgradeConfigGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/guis/upgrade/SneakyUpgradeConfigGuiProvider.java",
    "content": "package logisticspipes.network.guis.upgrade;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.gui.popup.SneakyConfigurationPopup;\nimport logisticspipes.network.abstractguis.GuiProvider;\nimport logisticspipes.network.abstractguis.UpgradeCoordinatesGuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.UpgradeSlot;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\n@StaticResolve\npublic class SneakyUpgradeConfigGuiProvider extends UpgradeCoordinatesGuiProvider {\n\n\tpublic SneakyUpgradeConfigGuiProvider(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic Object getClientGui(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe bPipe = getTileAs(player.world, LogisticsTileGenericPipe.class);\n\t\tif (!(bPipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tList<DoubleCoordinates> list = new WorldCoordinatesWrapper(bPipe).connectedTileEntities().stream()\n\t\t\t\t.filter(in -> SimpleServiceLocator.pipeInformationManager.isNotAPipe(in.getTileEntity()))\n\t\t\t\t.map(in -> new DoubleCoordinates(in.getTileEntity()))\n\t\t\t\t.collect(Collectors.toList());\n\n\t\tif (list.isEmpty()) {\n\t\t\tlist = new WorldCoordinatesWrapper(bPipe).connectedTileEntities().stream()\n\t\t\t\t\t.map(in -> new DoubleCoordinates(in.getTileEntity()))\n\t\t\t\t\t.collect(Collectors.toList());\n\t\t}\n\n\t\treturn new SneakyConfigurationPopup(list, getSlot(player, UpgradeSlot.class));\n\t}\n\n\t@Override\n\tpublic GuiProvider template() {\n\t\treturn new SneakyUpgradeConfigGuiProvider(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packetcontent/IPacketContent.java",
    "content": "package logisticspipes.network.packetcontent;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic interface IPacketContent<T> {\n\n\tT getValue();\n\n\tvoid setValue(T value);\n\n\tvoid readData(LPDataInput input);\n\n\tvoid writeData(LPDataOutput output);\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packetcontent/IntegerContent.java",
    "content": "package logisticspipes.network.packetcontent;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class IntegerContent implements IPacketContent<Integer> {\n\n\tprivate int integer;\n\n\t@Override\n\tpublic Integer getValue() {\n\t\treturn integer;\n\t}\n\n\t@Override\n\tpublic void setValue(Integer value) {\n\t\tinteger = value;\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tinteger = input.readInt();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(integer);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packetcontent/ItemStackContent.java",
    "content": "package logisticspipes.network.packetcontent;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class ItemStackContent implements IPacketContent<ItemStack> {\n\n\t@Nonnull\n\tprivate ItemStack stack = ItemStack.EMPTY;\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getValue() {\n\t\treturn stack;\n\t}\n\n\t@Override\n\tpublic void setValue(@Nonnull ItemStack value) {\n\t\tstack = value;\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tstack = input.readItemStack();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeItemStack(stack);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packetcontent/PacketContentBuilder.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\npackage logisticspipes.network.packetcontent;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\n\npublic class PacketContentBuilder {\n\n\tprivate final LinkedList<IPacketContent<?>> content = new LinkedList<>();\n\n\tpublic PacketContentBuilder() {\n\t}\n\n\tpublic void build(ModernPacket packet) {\n\t\tpacket.content = Collections.unmodifiableList(content);\n\t}\n\n\tprivate <T extends IPacketContent<?>> T addContent(T part) {\n\t\tcontent.add(part);\n\t\treturn part;\n\t}\n\n\tpublic IntegerContent addInteger() {\n\t\treturn addContent(new IntegerContent());\n\t}\n\n\tpublic ItemStackContent addItemStack() {\n\t\treturn addContent(new ItemStackContent());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/ActivateNBTDebug.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.config.Configs;\nimport logisticspipes.modplugins.nei.LoadingHelper;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ActivateNBTDebug extends ModernPacket {\n\n\tpublic ActivateNBTDebug(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\ttry {\n\t\t\tClass.forName(\"codechicken.nei.handler.NEIClientEventHandler\");\n\t\t\tConfigs.TOOLTIP_INFO = true;\n\t\t\tLoadingHelper.LoadNeiNBTDebugHelper();\n\t\t} catch (ClassNotFoundException ignored) {\n\n\t\t} catch (Exception e1) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\te1.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ActivateNBTDebug(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/AddNewChannelPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class AddNewChannelPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate String name;\n\n\t@Getter\n\t@Setter\n\tprivate ChannelInformation.AccessRights rights;\n\n\t@Getter\n\t@Setter\n\tprivate UUID securityStationID;\n\n\tpublic AddNewChannelPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tname = input.readUTF();\n\t\trights = input.readEnum(ChannelInformation.AccessRights.class);\n\t\tsecurityStationID = input.readUUID();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUTF(name);\n\t\toutput.writeEnum(rights);\n\t\toutput.writeUUID(securityStationID);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(player.getEntityWorld());\n\t\tmanager.createNewChannel(name, PlayerIdentifier.get(player), rights, securityStationID);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new AddNewChannelPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/BufferTransfer.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class BufferTransfer extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate byte[] content;\n\n\tpublic BufferTransfer(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new BufferTransfer(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tSimpleServiceLocator.clientBufferHandler.handlePacket(content);\n\t\t} else {\n\t\t\tSimpleServiceLocator.serverBufferHandler.handlePacket(content, player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tcontent = input.readByteArray();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeByteArray(content);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/DeleteChannelPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DeleteChannelPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate UUID channelIdentifier;\n\n\tpublic DeleteChannelPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tchannelIdentifier = input.readUUID();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUUID(channelIdentifier);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(player.getEntityWorld());\n\t\tmanager.removeChannel(channelIdentifier);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DeleteChannelPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/DummyPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DummyPacket extends ModernPacket {\n\n\tpublic DummyPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tthrow new RuntimeException(\"This packet should never be used\");\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tthrow new RuntimeException(\"This packet should never be used\");\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tthrow new RuntimeException(\"This packet should never be used\");\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DummyPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/EditChannelPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport java.util.Optional;\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class EditChannelPacket extends AddNewChannelPacket {\n\n\t@Getter\n\t@Setter\n\tprivate UUID channelIdentifier;\n\n\tpublic EditChannelPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tchannelIdentifier = input.readUUID();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUUID(channelIdentifier);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(player.getEntityWorld());\n\t\tOptional<ChannelInformation> channelOpt = manager.getChannels().stream()\n\t\t\t\t.filter(chan -> chan.getChannelIdentifier().equals(channelIdentifier))\n\t\t\t\t.findFirst();\n\t\tif (channelOpt.isPresent()) {\n\t\t\tChannelInformation channel = channelOpt.get();\n\t\t\tif (!channel.getName().equals(getName())) {\n\t\t\t\tmanager.updateChannelName(channelIdentifier, getName());\n\t\t\t}\n\t\t\tif (!channel.getRights().equals(getRights()) || (channel.getResponsibleSecurityID() != null && getSecurityStationID() != null && !channel.getResponsibleSecurityID().equals(getSecurityStationID())) || channel.getResponsibleSecurityID() != getSecurityStationID()) {\n\t\t\t\tmanager.updateChannelRights(channelIdentifier, getRights(), getSecurityStationID());\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new EditChannelPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/NEISetCraftingRecipe.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.NonNullList;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class NEISetCraftingRecipe extends CoordinatesPacket {\n\n\tprivate NonNullList<ItemStack> stackList = NonNullList.withSize(9, ItemStack.EMPTY);\n\n\tpublic NEISetCraftingRecipe(int id) {\n\t\tsuper(id);\n\t}\n\n\tpublic NonNullList<ItemStack> getStackList() {\n\t\treturn this.stackList;\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity tile = getTileAs(player.world, TileEntity.class);\n\t\tif (tile instanceof LogisticsCraftingTableTileEntity) {\n\t\t\t((LogisticsCraftingTableTileEntity) tile).handleNEIRecipePacket(getStackList());\n\t\t} else if (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe instanceof PipeBlockRequestTable) {\n\t\t\t((PipeBlockRequestTable) ((LogisticsTileGenericPipe) tile).pipe).handleNEIRecipePacket(getStackList());\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new NEISetCraftingRecipe(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(stackList, (out, stack) -> out.writeNBTTagCompound(stack.isEmpty() ? null : stack.writeToNBT(new NBTTagCompound())));\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tNonNullList<ItemStack> readList = input.readNonNullList(inp -> {\n\t\t\tNBTTagCompound tag = inp.readNBTTagCompound();\n\t\t\treturn tag == null ? null : new ItemStack(tag);\n\t\t}, ItemStack.EMPTY);\n\t\tif (readList != null) stackList = readList;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/PlayerConfigToClientPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PlayerConfigToClientPacket extends ModernPacket {\n\n\t@Setter\n\tprivate ClientConfiguration config;\n\n\tpublic PlayerConfigToClientPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tLogisticsPipes.getClientPlayerConfig().read(input);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tconfig.write(output);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PlayerConfigToClientPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/PlayerConfigToServerPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PlayerConfigToServerPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ClientConfiguration config;\n\n\tpublic PlayerConfigToServerPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tconfig = new ClientConfiguration();\n\t\tconfig.read(input);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsPipes.getServerConfigManager().setClientConfiguration(\n\t\t\t\tPlayerIdentifier.get(player), config);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tconfig.write(output);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PlayerConfigToServerPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/PlayerList.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.interfaces.PlayerListReciver;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringListPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PlayerList extends StringListPacket {\n\n\tpublic PlayerList(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PlayerList(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof PlayerListReciver) {\n\t\t\t((PlayerListReciver) FMLClientHandler.instance().getClient().currentScreen).receivePlayerList(getStringList());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/PlayerListRequest.java",
    "content": "package logisticspipes.network.packets;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.common.DimensionManager;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PlayerListRequest extends ModernPacket {\n\n\tpublic PlayerListRequest(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PlayerListRequest(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tStream<?> allPlayers = Arrays.stream(DimensionManager.getWorlds()).map(worldServer -> worldServer.playerEntities).flatMap(Collection::stream);\n\t\tStream<EntityPlayer> allPlayerEntities = allPlayers.filter(o -> o instanceof EntityPlayer).map(o -> (EntityPlayer) o);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PlayerList.class)\n\t\t\t\t.setStringList(allPlayerEntities.map(entityPlayer -> entityPlayer.getGameProfile().getName()).collect(Collectors.toList())), player);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/RequestUpdateNamesPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.NonNullList;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.common.registry.ForgeRegistries;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RequestUpdateNamesPacket extends ModernPacket {\n\n\tpublic RequestUpdateNamesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tCollection<Item> itemList = ForgeRegistries.ITEMS.getValuesCollection();\n\t\tList<ItemIdentifier> identList = new LinkedList<>();\n\t\tfor (Item item : itemList) {\n\t\t\tif (item != null) {\n\t\t\t\tfor (CreativeTabs tab : item.getCreativeTabs()) {\n\t\t\t\t\tNonNullList<ItemStack> list = NonNullList.create();\n\t\t\t\t\titem.getSubItems(tab, list);\n\t\t\t\t\tif (list.size() > 0) {\n\t\t\t\t\t\tidentList.addAll(list.stream().map(ItemIdentifier::get).collect(Collectors.toList()));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tidentList.add(ItemIdentifier.get(item, 0, null));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tSimpleServiceLocator.clientBufferHandler.setPause(true);\n\t\tfor (ItemIdentifier item : identList) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(UpdateName.class).setIdent(item).setName(item.getFriendlyName()));\n\t\t}\n\t\tSimpleServiceLocator.clientBufferHandler.setPause(false);\n\t\tFMLClientHandler.instance().getClient().player.sendChatMessage(\"Names in send Queue\");\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestUpdateNamesPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/SetGhostItemPacket.java",
    "content": "package logisticspipes.network.packets;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packetcontent.IntegerContent;\nimport logisticspipes.network.packetcontent.ItemStackContent;\nimport logisticspipes.network.packetcontent.PacketContentBuilder;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummySlot;\nimport logisticspipes.utils.gui.FluidSlot;\n\n@StaticResolve\npublic class SetGhostItemPacket extends ModernPacket {\n\n\tprivate final IntegerContent integer;\n\tprivate final ItemStackContent stack;\n\n\tpublic SetGhostItemPacket(int id) {\n\t\tsuper(id);\n\t\tPacketContentBuilder builder = new PacketContentBuilder();\n\t\tinteger = builder.addInteger();\n\t\tstack = builder.addItemStack();\n\t\tbuilder.build(this);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tContainer container = player.openContainer;\n\n\t\tif (container != null) {\n\t\t\tif (integer.getValue() >= 0 && integer.getValue() < container.inventorySlots.size()) {\n\t\t\t\tSlot slot = container.getSlot(integer.getValue());\n\n\t\t\t\tif (slot instanceof DummySlot || slot instanceof FluidSlot) {\n\t\t\t\t\tslot.putStack(stack.getValue());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SetGhostItemPacket(getId());\n\t}\n\n\tpublic SetGhostItemPacket setInteger(int value) {\n\t\tinteger.setValue(value);\n\t\treturn this;\n\t}\n\n\tpublic SetGhostItemPacket setStack(@Nonnull ItemStack value) {\n\t\tstack.setValue(value);\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/UpdateName.java",
    "content": "package logisticspipes.network.packets;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class UpdateName extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifier ident;\n\n\t@Getter\n\t@Setter\n\tprivate String name;\n\n\tpublic UpdateName(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new UpdateName(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(UpdateName.class).setIdent(getIdent()).setName(getIdent().getFriendlyName()));\n\t\t} else {\n\t\t\tMainProxy.proxy.updateNames(getIdent(), getName());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tident = input.readItemIdentifierStack().getItem();\n\t\tname = input.readUTF();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeItemIdentifierStack(ident.makeStack(1));\n\t\toutput.writeUTF(name);\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/AddItemToTrackPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.blocks.stats.TrackingTask;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class AddItemToTrackPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifier item;\n\n\tpublic AddItemToTrackPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsStatisticsTileEntity tile = this.getTileAs(player.getEntityWorld(), LogisticsStatisticsTileEntity.class);\n\t\tboolean found = false;\n\t\tfor (TrackingTask task : tile.tasks) {\n\t\t\tif (task.item.equals(item)) {\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found) {\n\t\t\tTrackingTask task = new TrackingTask();\n\t\t\ttask.item = item;\n\t\t\ttile.tasks.add(task);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeItemIdentifier(item);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\titem = input.readItemIdentifier();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new AddItemToTrackPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/AmountTaskSubGui.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.gui.GuiStatistics;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class AmountTaskSubGui extends InventoryModuleCoordinatesPacket {\n\n\tpublic AmountTaskSubGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiStatistics) {\n\t\t\t((GuiStatistics) FMLClientHandler.instance().getClient().currentScreen).handlePacket1(getIdentList());\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new AmountTaskSubGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/ClearCraftingGridPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ClearCraftingGridPacket extends CoordinatesPacket {\n\n\tpublic ClearCraftingGridPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity table = this.getTileAs(player.getEntityWorld(), TileEntity.class);\n\t\tif (table instanceof LogisticsCraftingTableTileEntity) {\n\t\t} else if (table instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) table).pipe instanceof PipeBlockRequestTable) {\n\t\t\t((PipeBlockRequestTable) ((LogisticsTileGenericPipe) table).pipe).matrix.clearGrid();\n\t\t\t((PipeBlockRequestTable) ((LogisticsTileGenericPipe) table).pipe).cacheRecipe();\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ClearCraftingGridPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/CompilerStatusPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ResourceLocation;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CompilerStatusPacket extends CoordinatesPacket {\n\n\tpublic CompilerStatusPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Getter\n\t@Setter\n\tprivate ResourceLocation category;\n\n\t@Getter\n\t@Setter\n\tprivate double progress;\n\n\t@Getter\n\t@Setter\n\tprivate boolean wasAbleToConsumePower;\n\n\t@Getter\n\t@Setter\n\t@Nonnull\n\tprivate ItemStack disk;\n\n\t@Getter\n\t@Setter\n\t@Nonnull\n\tprivate ItemStack programmer;\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsProgramCompilerTileEntity tile = this.getTileAs(player.world, LogisticsProgramCompilerTileEntity.class);\n\t\ttile.setStateOnClient(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeResourceLocation(category);\n\t\toutput.writeDouble(progress);\n\t\toutput.writeBoolean(wasAbleToConsumePower);\n\t\toutput.writeItemStack(disk);\n\t\toutput.writeItemStack(programmer);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tcategory = input.readResourceLocation();\n\t\tprogress = input.readDouble();\n\t\twasAbleToConsumePower = input.readBoolean();\n\t\tdisk = input.readItemStack();\n\t\tprogrammer = input.readItemStack();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CompilerStatusPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/CompilerTriggerTaskPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.ResourceLocation;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CompilerTriggerTaskPacket extends CoordinatesPacket {\n\n\tpublic CompilerTriggerTaskPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Getter\n\t@Setter\n\tprivate ResourceLocation category;\n\n\t@Getter\n\t@Setter\n\tprivate String type;\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsProgramCompilerTileEntity tile = this.getTileAs(player.world, LogisticsProgramCompilerTileEntity.class);\n\t\ttile.triggerNewTask(getCategory(), getType());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeResourceLocation(category);\n\t\toutput.writeUTF(type);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tcategory = input.readResourceLocation();\n\t\ttype = input.readUTF();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CompilerTriggerTaskPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/CraftingCycleRecipe.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CraftingCycleRecipe extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate boolean down;\n\n\tpublic CraftingCycleRecipe(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity table = this.getTileAs(player.getEntityWorld(), TileEntity.class);\n\t\tif (table instanceof LogisticsCraftingTableTileEntity) {\n\t\t\t((LogisticsCraftingTableTileEntity) table).cycleRecipe(down);\n\t\t} else if (table instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) table).pipe instanceof PipeBlockRequestTable) {\n\t\t\t((PipeBlockRequestTable) ((LogisticsTileGenericPipe) table).pipe).cycleRecipe(down);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CraftingCycleRecipe(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(down);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tdown = input.readBoolean();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/CraftingSetType.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CraftingSetType extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifier targetType;\n\n\tpublic CraftingSetType(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity table = this.getTileAs(player.getEntityWorld(), TileEntity.class);\n\t\tif (table instanceof LogisticsCraftingTableTileEntity) {\n\t\t\t((LogisticsCraftingTableTileEntity) table).targetType = targetType;\n\t\t\t((LogisticsCraftingTableTileEntity) table).cacheRecipe();\n\t\t} else if (table instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) table).pipe instanceof PipeBlockRequestTable) {\n\t\t\t((PipeBlockRequestTable) ((LogisticsTileGenericPipe) table).pipe).targetType = targetType;\n\t\t\t((PipeBlockRequestTable) ((LogisticsTileGenericPipe) table).pipe).cacheRecipe();\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CraftingSetType(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeItemIdentifier(targetType);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttargetType = input.readItemIdentifier();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/LogicControllerPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.logic.interfaces.ILogicControllerTile;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.logic.LogicControllerGuiProvider;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class LogicControllerPacket extends CoordinatesPacket {\n\n\tpublic LogicControllerPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tILogicControllerTile tile = this.getTileAs(player.getEntityWorld(), ILogicControllerTile.class);\n\t\tif (tile == null) {\n\t\t\treturn;\n\t\t}\n\t\tNewGuiHandler.getGui(LogicControllerGuiProvider.class).setTilePos((TileEntity) tile).open(player);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new LogicControllerPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/PipeSolidSideCheck.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PipeSolidSideCheck extends IntegerCoordinatesPacket {\n\n\tpublic PipeSolidSideCheck(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeSolidSideCheck(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tpipe.renderState.checkForRenderUpdate(player.world, pipe.getPos());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/PowerJunctionCheatPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PowerJunctionCheatPacket extends CoordinatesPacket {\n\n\tpublic PowerJunctionCheatPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PowerJunctionCheatPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (!LogisticsPipes.isDEBUG()) {\n\t\t\treturn;\n\t\t}\n\t\tfinal LogisticsPowerJunctionTileEntity tile = this.getTileAs(player.world, LogisticsPowerJunctionTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.addEnergy(100000);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/PowerJunctionLevel.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PowerJunctionLevel extends IntegerCoordinatesPacket {\n\n\tpublic PowerJunctionLevel(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PowerJunctionLevel(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsPowerJunctionTileEntity tile = this.getTileAs(player.world, LogisticsPowerJunctionTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.handlePowerPacket(getInteger());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/PowerPacketLaser.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PowerPacketLaser extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate EnumFacing dir;\n\t@Getter\n\t@Setter\n\tprivate int color;\n\t@Getter\n\t@Setter\n\tprivate boolean reverse;\n\t@Getter\n\t@Setter\n\tprivate boolean renderBall;\n\t@Getter\n\t@Setter\n\tprivate float length;\n\t@Getter\n\t@Setter\n\tprivate boolean remove = false;\n\n\tpublic PowerPacketLaser(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tlength = input.readFloat();\n\t\tdir = input.readFacing();\n\t\tcolor = input.readInt();\n\t\treverse = input.readBoolean();\n\t\trenderBall = input.readBoolean();\n\t\tremove = input.readBoolean();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.getEntityWorld());\n\t\tif (remove) {\n\t\t\ttile.removeLaser(dir, getColor(), isRenderBall());\n\t\t} else {\n\t\t\ttile.addLaser(dir, getLength(), getColor(), isReverse(), isRenderBall());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeFloat(length);\n\t\toutput.writeFacing(dir);\n\t\toutput.writeInt(color);\n\t\toutput.writeBoolean(reverse);\n\t\toutput.writeBoolean(renderBall);\n\t\toutput.writeBoolean(remove);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PowerPacketLaser(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/PowerProviderLevel.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerProviderTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PowerProviderLevel extends CoordinatesPacket {\n\n\tprivate Double aDouble;\n\n\tpublic PowerProviderLevel(int id) {\n\t\tsuper(id);\n\t}\n\n\tpublic double getDouble() {\n\t\treturn aDouble;\n\t}\n\n\tpublic PowerProviderLevel setDouble(double d) {\n\t\taDouble = d;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tsetDouble(input.readDouble());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeDouble(getDouble());\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PowerProviderLevel(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsPowerProviderTileEntity tile = this.getTileAs(player.world, LogisticsPowerProviderTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.handlePowerPacket(getDouble());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/RemoveAmoundTask.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport java.util.Iterator;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.blocks.stats.TrackingTask;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RemoveAmoundTask extends CoordinatesPacket {\n\n\t@Setter\n\t@Getter\n\tprivate ItemIdentifier item;\n\n\tpublic RemoveAmoundTask(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsStatisticsTileEntity tile = this.getTileAs(player.getEntityWorld(), LogisticsStatisticsTileEntity.class);\n\t\tIterator<TrackingTask> iter = tile.tasks.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tTrackingTask task = iter.next();\n\t\t\tif (task.item == item) {\n\t\t\t\titer.remove();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeItemIdentifier(item);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\titem = input.readItemIdentifier();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RemoveAmoundTask(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/RequestAmountTaskSubGui.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.TreeSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\n@StaticResolve\npublic class RequestAmountTaskSubGui extends CoordinatesPacket {\n\n\tpublic RequestAmountTaskSubGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsStatisticsTileEntity tile = this.getTileAs(player.getEntityWorld(), LogisticsStatisticsTileEntity.class);\n\t\tCoreRoutedPipe pipe = tile.getConnectedPipe();\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tMap<ItemIdentifier, Integer> _availableItems = SimpleServiceLocator.logisticsManager.getAvailableItems(pipe.getRouter().getIRoutersByCost());\n\t\tLinkedList<ItemIdentifier> _craftableItems = SimpleServiceLocator.logisticsManager.getCraftableItems(pipe.getRouter().getIRoutersByCost());\n\n\t\tTreeSet<ItemIdentifierStack> _allItems = new TreeSet<>();\n\n\t\tfor (Entry<ItemIdentifier, Integer> item : _availableItems.entrySet()) {\n\t\t\tItemIdentifierStack newStack = item.getKey().makeStack(item.getValue());\n\t\t\t_allItems.add(newStack);\n\t\t}\n\n\t\tfor (ItemIdentifier item : _craftableItems) {\n\t\t\tif (_availableItems.containsKey(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t_allItems.add(item.makeStack(1));\n\t\t}\n\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(AmountTaskSubGui.class).setIdentSet(_allItems), player);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestAmountTaskSubGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/RequestRotationPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IRotationProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestRotationPacket extends CoordinatesPacket {\n\n\tpublic RequestRotationPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestRotationPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIRotationProvider tile = this.getTileOrPipe(player.world, IRotationProvider.class);\n\t\tif (tile != null) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(Rotation.class).setInteger(tile.getRotation()).setPosX(getPosX()).setPosY(getPosY()).setPosZ(getPosZ()), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/RequestRunningCraftingTasks.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.stats.LogisticsStatisticsTileEntity;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\n@StaticResolve\npublic class RequestRunningCraftingTasks extends CoordinatesPacket {\n\n\tpublic RequestRunningCraftingTasks(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsStatisticsTileEntity tile = this.getTileAs(player.getEntityWorld(), LogisticsStatisticsTileEntity.class);\n\t\tCoreRoutedPipe pipe = tile.getConnectedPipe();\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tList<ItemIdentifierStack> items = new ArrayList<>();\n\n\t\tfor (ExitRoute r : pipe.getRouter().getIRoutersByCost()) {\n\t\t\tif (r == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (r.destination.getPipe() instanceof PipeItemsCraftingLogistics) {\n\t\t\t\tPipeItemsCraftingLogistics crafting = (PipeItemsCraftingLogistics) r.destination.getPipe();\n\t\t\t\tList<ItemIdentifierStack> content = crafting.getItemOrderManager().getContentList(player.getEntityWorld());\n\t\t\t\titems.addAll(content);\n\t\t\t}\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RunningCraftingTasks.class).setIdentList(items), player);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestRunningCraftingTasks(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/Rotation.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.interfaces.IRotationProvider;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class Rotation extends IntegerCoordinatesPacket {\n\n\tpublic Rotation(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new Rotation(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIRotationProvider tile = this.getTileOrPipe(player.world, IRotationProvider.class);\n\t\tif (tile != null) {\n\t\t\ttile.setRotation(getInteger());\n\t\t\tplayer.world.notifyNeighborsRespectDebug(new BlockPos(getPosX(), getPosY(), getPosZ()), player.world.getBlockState(new BlockPos(getPosX(), getPosY(), getPosZ())).getBlock(), true);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/RunningCraftingTasks.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.GuiStatistics;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RunningCraftingTasks extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate List<ItemIdentifierStack> identList;\n\n\tpublic RunningCraftingTasks(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiStatistics) {\n\t\t\t((GuiStatistics) FMLClientHandler.instance().getClient().currentScreen).handlePacket2(getIdentList());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeCollection(identList, LPDataOutput::writeItemIdentifierStack);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tidentList = input.readArrayList(LPDataInput::readItemIdentifierStack);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RunningCraftingTasks(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SaveSecurityPlayerPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.NBTCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SaveSecurityPlayerPacket extends NBTCoordinatesPacket {\n\n\tpublic SaveSecurityPlayerPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SaveSecurityPlayerPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.saveNewSecuritySettings(getTag());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityAddCCIdPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityAddCCIdPacket extends IntegerCoordinatesPacket {\n\n\tpublic SecurityAddCCIdPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityAddCCIdPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.addCCToList(getInteger());\n\t\t\ttile.requestList(player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityAuthorizationPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityAuthorizationPacket extends IntegerCoordinatesPacket {\n\n\tpublic SecurityAuthorizationPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityAuthorizationPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\tif (getInteger() == 1) {\n\t\t\t\ttile.authorizeStation();\n\t\t\t} else {\n\t\t\t\ttile.deauthorizeStation();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityCardPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityCardPacket extends IntegerCoordinatesPacket {\n\n\tpublic SecurityCardPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityCardPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.buttonFreqCard(getInteger(), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityRemoveCCIdPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityRemoveCCIdPacket extends IntegerCoordinatesPacket {\n\n\tpublic SecurityRemoveCCIdPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityRemoveCCIdPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.removeCCFromList(getInteger());\n\t\t\ttile.requestList(player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityRequestCCIdsPacket.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityRequestCCIdsPacket extends CoordinatesPacket {\n\n\tpublic SecurityRequestCCIdsPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityRequestCCIdsPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.requestList(player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationAuthorizedList.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringListPacket;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityStationAuthorizedList extends StringListPacket {\n\n\tpublic SecurityStationAuthorizedList(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationAuthorizedList(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tSimpleServiceLocator.securityStationManager.setClientAuthorizationList(getStringList());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationAutoDestroy.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.gui.GuiSecurityStation;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityStationAutoDestroy extends IntegerCoordinatesPacket {\n\n\tpublic SecurityStationAutoDestroy(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationAutoDestroy(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile instanceof LogisticsSecurityTileEntity) {\n\t\t\tif (MainProxy.isClient(player.world)) {\n\t\t\t\ttile.setClientDestroy(getInteger() == 1);\n\t\t\t\thandleClientSide(player);\n\t\t\t} else {\n\t\t\t\ttile.changeDestroy();\n\t\t\t}\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprivate void handleClientSide(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiSecurityStation) {\n\t\t\t((GuiSecurityStation) FMLClientHandler.instance().getClient().currentScreen).refreshCheckBoxes();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationCC.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.gui.GuiSecurityStation;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityStationCC extends IntegerCoordinatesPacket {\n\n\tpublic SecurityStationCC(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationCC(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile instanceof LogisticsSecurityTileEntity) {\n\t\t\tif (MainProxy.isClient(player.world)) {\n\t\t\t\ttile.setClientCC(getInteger() == 1);\n\t\t\t\thandleClientSide(player);\n\t\t\t} else {\n\t\t\t\ttile.changeCC();\n\t\t\t}\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprivate void handleClientSide(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiSecurityStation) {\n\t\t\t((GuiSecurityStation) FMLClientHandler.instance().getClient().currentScreen).refreshCheckBoxes();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationCCIDs.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.NBTCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityStationCCIDs extends NBTCoordinatesPacket {\n\n\tpublic SecurityStationCCIDs(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationCCIDs(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.handleListPacket(getTag());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationId.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SecurityStationId extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate UUID uuid;\n\n\tpublic SecurityStationId(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationId(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\ttile.setClientUUID(getUuid());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeLong(uuid.getMostSignificantBits());\n\t\toutput.writeLong(uuid.getLeastSignificantBits());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tuuid = new UUID(input.readLong(), input.readLong());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationOpenPlayer.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.gui.GuiSecurityStation;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.NBTCoordinatesPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityStationOpenPlayer extends NBTCoordinatesPacket {\n\n\tpublic SecurityStationOpenPlayer(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationOpenPlayer(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\thandleClientSide(player);\n\t\t} else {\n\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprivate void handleClientSide(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiSecurityStation) {\n\t\t\tSecuritySettings setting = new SecuritySettings(null);\n\t\t\tsetting.readFromNBT(getTag());\n\t\t\t((GuiSecurityStation) FMLClientHandler.instance().getClient().currentScreen).handlePlayerSecurityOpen(setting);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/block/SecurityStationOpenPlayerRequest.java",
    "content": "package logisticspipes.network.packets.block;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SecurityStationOpenPlayerRequest extends StringCoordinatesPacket {\n\n\tpublic SecurityStationOpenPlayerRequest(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SecurityStationOpenPlayerRequest(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity tile = this.getTileAs(player.world, LogisticsSecurityTileEntity.class);\n\t\tif (tile != null) {\n\t\t\tif (getString() != null && !getString().isEmpty()) {\n\t\t\t\ttile.handleOpenSecurityPlayer(player, getString());\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/chassis/ChassisGUI.java",
    "content": "package logisticspipes.network.packets.chassis;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ChassisGUI extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int buttonID;\n\n\tpublic ChassisGUI(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(buttonID);\n\t\tsuper.writeData(output);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tbuttonID = input.readInt();\n\t\tsuper.readData(input);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof PipeLogisticsChassis) {\n\t\t\tLogisticsModule subModule = ((PipeLogisticsChassis) pipe.pipe).getSubModule(getButtonID());\n\t\t\tif (subModule instanceof Gui) {\n\t\t\t\tGui.getPipeGuiProvider((Gui) subModule).setPosX(getPosX()).setPosY(getPosY()).setPosZ(getPosZ()).open(player);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChassisGUI(getId());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/chassis/ChestGuiClosed.java",
    "content": "package logisticspipes.network.packets.chassis;\n\nimport java.lang.ref.WeakReference;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LogisticsEventListener;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.module.AsyncQuicksortModule;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ChestGuiClosed extends ModernPacket {\n\n\tpublic ChestGuiClosed(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tList<WeakReference<AsyncQuicksortModule>> list = LogisticsEventListener.chestQuickSortConnection.get(player);\n\t\tif (list == null || list.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tfor (WeakReference<AsyncQuicksortModule> sorter : list) {\n\t\t\tAsyncQuicksortModule module = sorter.get();\n\t\t\tif (module == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmodule.removeWatchingPlayer(player);\n\t\t}\n\t\tLogisticsEventListener.chestQuickSortConnection.remove(player);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChestGuiClosed(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/chassis/ChestGuiOpened.java",
    "content": "package logisticspipes.network.packets.chassis;\n\nimport java.lang.ref.WeakReference;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LogisticsEventListener;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.module.AsyncQuicksortModule;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ChestGuiOpened extends ModernPacket {\n\n\tpublic ChestGuiOpened(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tList<WeakReference<AsyncQuicksortModule>> list = LogisticsEventListener.chestQuickSortConnection.get(player);\n\t\tif (list == null || list.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(EnableQuickSortMarker.class), player);\n\t\tfor (WeakReference<AsyncQuicksortModule> sorter : list) {\n\t\t\tAsyncQuicksortModule module = sorter.get();\n\t\t\tif (module == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmodule.addWatchingPlayer(player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChestGuiOpened(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/chassis/EnableQuickSortMarker.java",
    "content": "package logisticspipes.network.packets.chassis;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.QuickSortChestMarkerStorage;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class EnableQuickSortMarker extends ModernPacket {\n\n\tpublic EnableQuickSortMarker(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tQuickSortChestMarkerStorage.getInstance().enable();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new EnableQuickSortMarker(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/cpipe/CPipeCleanupImport.java",
    "content": "package logisticspipes.network.packets.cpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class CPipeCleanupImport extends ModuleCoordinatesPacket {\n\n\tpublic CPipeCleanupImport(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CPipeCleanupImport(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal ModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.importCleanup();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/cpipe/CPipeSatelliteImport.java",
    "content": "package logisticspipes.network.packets.cpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class CPipeSatelliteImport extends ModuleCoordinatesPacket {\n\n\tpublic CPipeSatelliteImport(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CPipeSatelliteImport(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.importFromCraftingTable(player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/cpipe/CPipeSatelliteImportBack.java",
    "content": "package logisticspipes.network.packets.cpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class CPipeSatelliteImportBack extends InventoryModuleCoordinatesPacket {\n\n\tpublic CPipeSatelliteImportBack(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CPipeSatelliteImportBack(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (int i = 0; i < getStackList().size(); i++) {\n\t\t\tmodule.dummyInventory.setInventorySlotContents(i, getStackList().get(i));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/cpipe/CraftingPipeOpenConnectedGuiPacket.java",
    "content": "package logisticspipes.network.packets.cpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class CraftingPipeOpenConnectedGuiPacket extends ModuleCoordinatesPacket {\n\n\tpublic CraftingPipeOpenConnectedGuiPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CraftingPipeOpenConnectedGuiPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.openAttachedGui(player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debug/PipeDebugLogAskForTarget.java",
    "content": "package logisticspipes.network.packets.debug;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.RayTraceResult;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport static net.minecraft.util.math.RayTraceResult.Type.BLOCK;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeDebugLogAskForTarget extends ModernPacket {\n\n\tpublic PipeDebugLogAskForTarget(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tRayTraceResult box = FMLClientHandler.instance().getClient().objectMouseOver;\n\t\tif (box != null && box.typeOfHit == BLOCK) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PipeDebugLogResponse.class).setBlockPos(box.getBlockPos()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeDebugLogAskForTarget(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debug/PipeDebugLogResponse.java",
    "content": "package logisticspipes.network.packets.debug;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PipeDebugLogResponse extends CoordinatesPacket {\n\n\tpublic PipeDebugLogResponse(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.getEntityWorld());\n\t\tif (tile != null) {\n\t\t\t((CoreRoutedPipe) tile.pipe).debug.openForPlayer(player);\n\t\t\tplayer.sendMessage(new TextComponentString(\"Debug log enabled.\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeDebugLogResponse(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debug/SendNewLogLine.java",
    "content": "package logisticspipes.network.packets.debug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.debug.LogWindow;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SendNewLogLine extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int windowID;\n\n\t@Getter\n\t@Setter\n\tprivate String line;\n\n\tpublic SendNewLogLine(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\twindowID = input.readInt();\n\t\tline = input.readUTF();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogWindow.getWindow(windowID).newLine(line);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(windowID);\n\t\toutput.writeUTF(line);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SendNewLogLine(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debug/SendNewLogWindow.java",
    "content": "package logisticspipes.network.packets.debug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.debug.LogWindow;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SendNewLogWindow extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int windowID;\n\n\t@Getter\n\t@Setter\n\tprivate String title;\n\n\tpublic SendNewLogWindow(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\twindowID = input.readInt();\n\t\ttitle = input.readUTF();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogWindow.getWindow(windowID).setTitle(title);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(windowID);\n\t\toutput.writeUTF(title);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SendNewLogWindow(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debug/UpdateStatusEntries.java",
    "content": "package logisticspipes.network.packets.debug;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.IReadListObject;\nimport logisticspipes.network.IWriteListObject;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.debug.LogWindow;\nimport logisticspipes.pipes.basic.debug.StatusEntry;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class UpdateStatusEntries extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tpublic int windowID;\n\n\t@Getter\n\t@Setter\n\tpublic List<StatusEntry> status;\n\n\tpublic UpdateStatusEntries(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\twindowID = input.readInt();\n\t\tstatus = input.readArrayList(new IReadListObject<StatusEntry>() {\n\n\t\t\t@Override\n\t\t\tpublic StatusEntry readObject(LPDataInput input) {\n\t\t\t\tStatusEntry status = new StatusEntry();\n\t\t\t\tstatus.name = input.readUTF();\n\t\t\t\tif (input.readBoolean()) {\n\t\t\t\t\tstatus.subEntry = input.readArrayList(this);\n\t\t\t\t}\n\t\t\t\treturn status;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogWindow.getWindow(windowID).updateStatus(status);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(windowID);\n\t\toutput.writeCollection(status, new IWriteListObject<StatusEntry>() {\n\n\t\t\t@Override\n\t\t\tpublic void writeObject(LPDataOutput output, StatusEntry entry) {\n\t\t\t\toutput.writeUTF(entry.name);\n\t\t\t\toutput.writeBoolean(entry.subEntry != null);\n\t\t\t\tif (entry.subEntry != null) {\n\t\t\t\t\toutput.writeCollection(entry.subEntry, this);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new UpdateStatusEntries(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debuggui/DebugAskForTarget.java",
    "content": "package logisticspipes.network.packets.debuggui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.RayTraceResult;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DebugAskForTarget extends ModernPacket {\n\n\tpublic DebugAskForTarget(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tRayTraceResult box = FMLClientHandler.instance().getClient().objectMouseOver;\n\t\tif (box == null) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DebugTargetResponse.class).setMode(DebugTargetResponse.TargetMode.None));\n\t\t} else if (box.typeOfHit == RayTraceResult.Type.BLOCK) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DebugTargetResponse.class).setMode(DebugTargetResponse.TargetMode.Block)\n\t\t\t\t\t.setAdditions(new int[] { box.getBlockPos().getX(), box.getBlockPos().getY(), box.getBlockPos().getZ() }));\n\t\t} else if (box.typeOfHit == RayTraceResult.Type.ENTITY) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DebugTargetResponse.class).setMode(DebugTargetResponse.TargetMode.Entity)\n\t\t\t\t\t.setAdditions(new int[] { box.entityHit.getEntityId() }));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DebugAskForTarget(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debuggui/DebugDataPacket.java",
    "content": "package logisticspipes.network.packets.debuggui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.commands.commands.debug.DebugGuiController;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DebugDataPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate byte[] payload;\n\n\t@Getter\n\t@Setter\n\tprivate int identifier;\n\n\tpublic DebugDataPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tpayload = input.readByteArray();\n\t\tidentifier = input.readInt();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tDebugGuiController.instance().handleDataPacket(payload, identifier, player);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeByteArray(payload);\n\t\toutput.writeInt(identifier);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DebugDataPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debuggui/DebugPanelOpen.java",
    "content": "package logisticspipes.network.packets.debuggui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.commands.commands.debug.DebugGuiController;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DebugPanelOpen extends ModernPacket {\n\n\t@Setter\n\t@Getter\n\tprivate String name;\n\n\t@Getter\n\t@Setter\n\tprivate int identification;\n\n\tpublic DebugPanelOpen(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DebugPanelOpen(getId());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsetName(input.readUTF());\n\t\tsetIdentification(input.readInt());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeUTF(getName());\n\t\toutput.writeInt(getIdentification());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\ttry {\n\t\t\tDebugGuiController.instance().createNewDebugGui(getName(), getIdentification());\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/debuggui/DebugTargetResponse.java",
    "content": "package logisticspipes.network.packets.debuggui;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.TextComponentString;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.commands.chathelper.LPChatListener;\nimport logisticspipes.commands.commands.debug.DebugGuiController;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.gui.OpenChatGui;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DebugTargetResponse extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate TargetMode mode;\n\t@Getter\n\t@Setter\n\tprivate int[] additions = new int[0];\n\n\tpublic DebugTargetResponse(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tmode = TargetMode.values()[input.readByte()];\n\t\tadditions = input.readIntArray();\n\t}\n\n\t@Override\n\tpublic void processPacket(final EntityPlayer player) {\n\t\tif (mode == TargetMode.None) {\n\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No Target Found\"));\n\t\t} else if (mode == TargetMode.Block) {\n\t\t\tint x = additions[0];\n\t\t\tint y = additions[1];\n\t\t\tint z = additions[2];\n\t\t\tplayer.sendMessage(new TextComponentString(\"Checking Block at: x:\" + x + \" y:\" + y + \" z:\" + z));\n\t\t\tBlock id = player.world.getBlockState(new BlockPos(x, y, z)).getBlock();\n\t\t\tplayer.sendMessage(new TextComponentString(\"Found Block with Id: \" + id.getClass()));\n\t\t\tfinal TileEntity tile = player.world.getTileEntity(new BlockPos(x, y, z));\n\t\t\tif (tile == null) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No TileEntity found\"));\n\t\t\t} else {\n\t\t\t\tLPChatListener.addTask(() -> {\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(\n\t\t\t\t\t\t\tChatColor.GREEN + \"Starting debuging of TileEntity: \" + ChatColor.BLUE + ChatColor.UNDERLINE + tile.getClass().getSimpleName()));\n\t\t\t\t\tDebugGuiController.instance().startWatchingOf(tile, player);\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t\t\treturn true;\n\t\t\t\t}, player);\n\t\t\t\tplayer.sendMessage(new TextComponentString(\n\t\t\t\t\t\tChatColor.AQUA + \"Start debuging of TileEntity: \" + ChatColor.BLUE + ChatColor.UNDERLINE + tile.getClass().getSimpleName()\n\t\t\t\t\t\t\t\t+ ChatColor.AQUA + \"? \" + ChatColor.RESET + \"<\" + ChatColor.GREEN + \"yes\" + ChatColor.RESET + \"/\" + ChatColor.RED + \"no\"\n\t\t\t\t\t\t\t\t+ ChatColor.RESET + \">\"));\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t}\n\t\t} else if (mode == TargetMode.Entity) {\n\t\t\tint entityId = additions[0];\n\t\t\tfinal Entity entity = player.world.getEntityByID(entityId);\n\t\t\tif (entity == null) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No Entity found\"));\n\t\t\t} else {\n\t\t\t\tLPChatListener.addTask(() -> {\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(\n\t\t\t\t\t\t\tChatColor.GREEN + \"Starting debuging of Entity: \" + ChatColor.BLUE + ChatColor.UNDERLINE + entity.getClass().getSimpleName()));\n\t\t\t\t\tDebugGuiController.instance().startWatchingOf(entity, player);\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t\t\treturn true;\n\t\t\t\t}, player);\n\t\t\t\tplayer.sendMessage(new TextComponentString(\n\t\t\t\t\t\tChatColor.AQUA + \"Start debuging of Entity: \" + ChatColor.BLUE + ChatColor.UNDERLINE + entity.getClass().getSimpleName()\n\t\t\t\t\t\t\t\t+ ChatColor.AQUA + \"? \" + ChatColor.RESET + \"<\" + ChatColor.GREEN + \"yes\" + ChatColor.RESET + \"/\" + ChatColor.RED + \"no\"\n\t\t\t\t\t\t\t\t+ ChatColor.RESET + \">\"));\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeByte(mode.ordinal());\n\t\toutput.writeIntArray(additions);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DebugTargetResponse(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n\n\tpublic enum TargetMode {\n\t\tBlock,\n\t\tEntity,\n\t\tNone\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/ChannelInformationPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.IGUIChannelInformationReceiver;\nimport logisticspipes.network.abstractpackets.GuiPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.exception.TargetNotFoundException;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ChannelInformationPacket extends GuiPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ChannelInformation information;\n\n\t@Getter\n\t@Setter\n\tprivate boolean targeted;\n\n\tpublic ChannelInformationPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tinformation = input.readChannelInformation();\n\t\ttargeted = input.readBoolean();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeChannelInformation(information);\n\t\toutput.writeBoolean(targeted);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIGUIChannelInformationReceiver screen = this.getGui(IGUIChannelInformationReceiver.class);\n\t\tif (screen != null) {\n\t\t\tscreen.handleChannelInformation(information, targeted);\n\t\t} else if (targeted) {\n\t\t\tthrow new TargetNotFoundException(\"GuiDoesNotWantPacket\", this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChannelInformationPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/DummyContainerSlotClick.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.inventory.ClickType;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.ColorSlot;\nimport logisticspipes.utils.gui.DummyContainer;\nimport logisticspipes.utils.gui.DummySlot;\nimport logisticspipes.utils.gui.FluidSlot;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class DummyContainerSlotClick extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tint slotId;\n\n\t@Getter\n\t@Setter\n\t@Nonnull\n\tItemStack stack;\n\n\t@Getter\n\t@Setter\n\tint button;\n\n\tpublic DummyContainerSlotClick(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tslotId = input.readInt();\n\t\tstack = input.readItemIdentifierStack().makeNormalStack();\n\t\tbutton = input.readInt();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (player instanceof EntityPlayerMP && ((EntityPlayerMP) player).openContainer instanceof DummyContainer) {\n\t\t\tDummyContainer container = (DummyContainer) ((EntityPlayerMP) player).openContainer;\n\t\t\tSlot slot = container.inventorySlots.get(slotId);\n\t\t\tif (slot instanceof DummySlot || slot instanceof ColorSlot || slot instanceof FluidSlot) {\n\t\t\t\tcontainer.handleDummyClick(slot, slotId, stack, button, ClickType.PICKUP, player);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(slotId);\n\t\toutput.writeItemIdentifierStack(ItemIdentifierStack.getFromStack(stack));\n\t\toutput.writeInt(button);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DummyContainerSlotClick(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/FuzzySlotSettingsPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport java.util.BitSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.IFuzzySlot;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class FuzzySlotSettingsPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int slotNumber;\n\n\t@Getter\n\t@Setter\n\tprivate BitSet flags;\n\n\tpublic FuzzySlotSettingsPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tslotNumber = input.readInt();\n\t\tflags = input.readBitSet();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (player.openContainer != null && player.openContainer.getSlot(slotNumber) instanceof IFuzzySlot) {\n\t\t\t((IFuzzySlot) player.openContainer.getSlot(slotNumber)).getFuzzyFlags().replaceWith(flags);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(slotNumber);\n\t\toutput.writeBitSet(flags);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FuzzySlotSettingsPacket(getId());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/GuiClosePacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class GuiClosePacket extends CoordinatesPacket {\n\n\tpublic GuiClosePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\t// always mark the GUI origin's chunk dirty - something may have changed in the GUI\n\t\tgetTileAs(player.world, TileEntity.class).markDirty();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new GuiClosePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/GuiOpenChassis.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.pipe.ChassisGuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class GuiOpenChassis extends CoordinatesPacket {\n\n\tpublic GuiOpenChassis(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof CoreRoutedPipe) {\n\t\t\tNewGuiHandler.getGui(ChassisGuiProvider.class).setFlag(pipe.pipe.getUpgradeManager().hasUpgradeModuleUpgrade()).setSlot(ModulePositionType.IN_PIPE).setPositionInt(0).setPosX(getPosX()).setPosY(getPosY()).setPosZ(getPosZ()).open(player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new GuiOpenChassis(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/GuiReopenPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class GuiReopenPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int guiID;\n\n\tpublic GuiReopenPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(getGuiID());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tguiID = input.readInt();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tplayer.openGui(LogisticsPipes.instance, getGuiID(), player.world, getPosX(), getPosY(), getPosZ());\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new GuiReopenPacket(getId());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/OpenAddChannelGUIPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.AddChannelGuiProvider;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OpenAddChannelGUIPacket extends CoordinatesPacket {\n\n\tpublic OpenAddChannelGUIPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity tile = player.getEntityWorld().getTileEntity(new BlockPos(getPosX(), getPosY(), getPosZ()));\n\t\tUUID securityID = null;\n\t\tif (tile instanceof LogisticsSecurityTileEntity) {\n\t\t\tLogisticsSecurityTileEntity security = (LogisticsSecurityTileEntity) tile;\n\t\t\tsecurityID = security.getSecId();\n\t\t}\n\t\tUUID finalSecurityID = securityID;\n\t\tNewGuiHandler.getGui(AddChannelGuiProvider.class).setSecurityStationID(finalSecurityID).open(player);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenAddChannelGUIPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/OpenChatGui.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.client.gui.GuiChat;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class OpenChatGui extends ModernPacket {\n\n\tpublic OpenChatGui(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\t@ClientSideOnlyMethodContent\n\tpublic void processPacket(EntityPlayer player) {\n\t\tFMLClientHandler.instance().getClient().displayGuiScreen(new GuiChat());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenChatGui(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/OpenEditChannelGUIPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport java.util.Optional;\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.EditChannelGuiProvider;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class OpenEditChannelGUIPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate String identifier;\n\n\tpublic OpenEditChannelGUIPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tidentifier = input.readUTF();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUTF(identifier);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity tile = player.getEntityWorld().getTileEntity(new BlockPos(getPosX(), getPosY(), getPosZ()));\n\t\tUUID securityID = null;\n\t\tif (tile instanceof LogisticsSecurityTileEntity) {\n\t\t\tLogisticsSecurityTileEntity security = (LogisticsSecurityTileEntity) tile;\n\t\t\tsecurityID = security.getSecId();\n\t\t}\n\t\tUUID finalSecurityID = securityID;\n\t\tIChannelManager channelManager = SimpleServiceLocator.channelManagerProvider\n\t\t\t\t.getChannelManager(player.getEntityWorld());\n\t\tOptional<ChannelInformation> match = channelManager.getChannels().stream()\n\t\t\t\t.filter(channel -> channel.getChannelIdentifier().toString().equals(getIdentifier())).findFirst();\n\t\tmatch.ifPresent(channel -> NewGuiHandler.getGui(EditChannelGuiProvider.class).setResponsibleSecurityID(finalSecurityID).setChannel(channel).open(player));\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenEditChannelGUIPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/OpenGUIPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class OpenGUIPacket extends ModernPacket {\n\n\t/**\n\t * GUI Type ID\n\t */\n\t@Getter\n\t@Setter\n\tprivate int guiID;\n\n\t/**\n\t * GUI Count ID\n\t */\n\t@Getter\n\t@Setter\n\tprivate int windowID;\n\n\t/**\n\t * GUI Additional Information\n\t */\n\t@Getter\n\t@Setter\n\tprivate byte[] guiData;\n\n\tpublic OpenGUIPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tguiID = input.readInt();\n\t\twindowID = input.readInt();\n\t\tguiData = input.readByteArray();\n\t}\n\n\t@Override\n\t@ClientSideOnlyMethodContent\n\tpublic void processPacket(EntityPlayer player) {\n\t\tNewGuiHandler.openGui(this, player);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(guiID);\n\t\toutput.writeInt(windowID);\n\t\toutput.writeByteArray(guiData);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenGUIPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/OpenSecurityChannelManagerPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.block.SecurityChannelManagerGui;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OpenSecurityChannelManagerPacket extends CoordinatesPacket {\n\n\tpublic OpenSecurityChannelManagerPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsSecurityTileEntity securityTile = this.getTileAs(player.getEntityWorld(), LogisticsSecurityTileEntity.class);\n\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(player.getEntityWorld());\n\t\tNewGuiHandler.getGui(SecurityChannelManagerGui.class).setChannelInformations(manager.getAllowedChannels(player)).setTilePos(securityTile).open(player);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenSecurityChannelManagerPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/OpenUpgradePacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractguis.UpgradeCoordinatesGuiProvider;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.SlotPacket;\nimport logisticspipes.pipes.upgrades.IConfigPipeUpgrade;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.UpgradeSlot;\n\n@StaticResolve\npublic class OpenUpgradePacket extends SlotPacket {\n\n\tpublic OpenUpgradePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tUpgradeSlot slot = getSlot(player, UpgradeSlot.class);\n\t\tIPipeUpgrade upgrade = slot.getUpgrade();\n\t\tif (upgrade instanceof IConfigPipeUpgrade) {\n\t\t\tUpgradeCoordinatesGuiProvider gui = ((IConfigPipeUpgrade) upgrade).getGUI();\n\t\t\tif (gui != null) {\n\t\t\t\tgui.setSlot(slot).setLPPos(slot.getManager().getPipePosition()).open(player);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OpenUpgradePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/ProvideSatellitePipeListPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.popup.GuiSelectSatellitePopup;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ProvideSatellitePipeListPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate List<Pair<String, UUID>> list;\n\n\tpublic ProvideSatellitePipeListPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tlist = input.readArrayList(input1 -> new Pair<>(input1.readUTF(), input1.readUUID()));\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(list, (output1, object) -> {\n\t\t\toutput1.writeUTF(object.getValue1());\n\t\t\toutput1.writeUUID(object.getValue2());\n\t\t});\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (Minecraft.getMinecraft().currentScreen instanceof LogisticsBaseGuiScreen) {\n\t\t\tSubGuiScreen subGUI = ((LogisticsBaseGuiScreen) Minecraft.getMinecraft().currentScreen).getSubGui();\n\t\t\tif (subGUI instanceof GuiSelectSatellitePopup) {\n\t\t\t\t((GuiSelectSatellitePopup) subGUI).handleSatelliteList(list);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ProvideSatellitePipeListPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/gui/RequestSatellitePipeListPacket.java",
    "content": "package logisticspipes.network.packets.gui;\n\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.UUID;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.BooleanCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeFluidSatellite;\nimport logisticspipes.pipes.PipeItemsSatelliteLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.tuples.Pair;\n\n@StaticResolve\npublic class RequestSatellitePipeListPacket extends BooleanCoordinatesPacket {\n\n\tpublic RequestSatellitePipeListPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tCoreRoutedPipe rPipe = (CoreRoutedPipe) pipe.pipe;\n\t\tList<Pair<String, UUID>> list;\n\t\tif (rPipe.getRouter() == null || rPipe.getRouter().getRouteTable() == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.isFlag()) {\n\t\t\tlist = PipeFluidSatellite.AllSatellites.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(it -> it.getRouter() != null)\n\t\t\t\t\t.filter(it -> {\n\t\t\t\t\t\tList<List<ExitRoute>> routingTable = rPipe.getRouter().getRouteTable();\n\t\t\t\t\t\treturn routingTable.size() > it.getRouterId() && routingTable.get(it.getRouterId()) != null && !routingTable.get(it.getRouterId()).isEmpty();\n\t\t\t\t\t})\n\t\t\t\t\t.sorted(Comparator.comparingDouble(it -> rPipe.getRouter().getRouteTable().get(it.getRouterId()).stream().map(it1 -> it1.distanceToDestination).min(Double::compare).get()))\n\t\t\t\t\t.map(it -> new Pair<>(it.getSatellitePipeName(), it.getRouter().getId()))\n\t\t\t\t\t.collect(Collectors.toList());\n\t\t} else {\n\t\t\tlist = PipeItemsSatelliteLogistics.AllSatellites.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(it -> it.getRouter() != null)\n\t\t\t\t\t.filter(it -> {\n\t\t\t\t\t\tList<List<ExitRoute>> routingTable = rPipe.getRouter().getRouteTable();\n\t\t\t\t\t\treturn routingTable.size() > it.getRouterId() && routingTable.get(it.getRouterId()) != null && !routingTable.get(it.getRouterId()).isEmpty();\n\t\t\t\t\t})\n\t\t\t\t\t.sorted(Comparator.comparingDouble(it -> rPipe.getRouter().getRouteTable().get(it.getRouterId()).stream().map(it1 -> it1.distanceToDestination).min(Double::compare).get()))\n\t\t\t\t\t.map(it -> new Pair<>(it.getSatellitePipeName(), it.getRouter().getId()))\n\t\t\t\t\t.collect(Collectors.toList());\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ProvideSatellitePipeListPacket.class).setList(list), player);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestSatellitePipeListPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/ChestContent.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IChestContentReceiver;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ChestContent extends InventoryModuleCoordinatesPacket {\n\n\tpublic ChestContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChestContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe != null && pipe.pipe instanceof IChestContentReceiver) {\n\t\t\t((IChestContentReceiver) pipe.pipe).setReceivedChestContent(getIdentList());\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDSettingsPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.hud.HUDConfig;\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class HUDSettingsPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int buttonId;\n\n\t@Getter\n\t@Setter\n\tprivate boolean state;\n\n\t@Getter\n\t@Setter\n\tprivate int slot;\n\n\tpublic HUDSettingsPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDSettingsPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal ItemStack equipment = player.inventory.getStackInSlot(slot);\n\t\tif (equipment.getItem() != LPItems.hudGlasses) return;\n\t\tIHUDConfig config = new HUDConfig(equipment);\n\t\tswitch (buttonId) {\n\t\t\tcase 0:\n\t\t\t\tconfig.setChassisHUD(state);\n\t\t\t\tif (config.isChassisHUD()) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.chassie.enabled\"));\n\t\t\t\t} else {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.chassie.disabled\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tconfig.setHUDCrafting(state);\n\t\t\t\tif (config.isHUDCrafting()) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.crafting.enabled\"));\n\t\t\t\t} else {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.crafting.disabled\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tconfig.setHUDInvSysCon(state);\n\t\t\t\tif (config.isHUDInvSysCon()) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.invsyscon.enabled\"));\n\t\t\t\t} else {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.invsyscon.disabled\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tconfig.setHUDPowerJunction(state);\n\t\t\t\tif (config.isHUDPowerLevel()) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.powerjunction.enabled\"));\n\t\t\t\t} else {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.powerjunction.disabled\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 4:\n\t\t\t\tconfig.setHUDProvider(state);\n\t\t\t\tif (config.isHUDProvider()) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.provider.enabled\"));\n\t\t\t\t} else {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.provider.disabled\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 5:\n\t\t\t\tconfig.setHUDSatellite(state);\n\t\t\t\tif (config.isHUDSatellite()) {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.satellite.enabled\"));\n\t\t\t\t} else {\n\t\t\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.hud.config.satellite.disabled\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\tif (player.inventoryContainer != null) {\n\t\t\tplayer.inventoryContainer.detectAndSendChanges();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tbuttonId = input.readInt();\n\t\tstate = input.readBoolean();\n\t\tslot = input.readInt();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(buttonId);\n\t\toutput.writeBoolean(state);\n\t\toutput.writeInt(slot);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDStartBlockWatchingPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IBlockWatchingHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class HUDStartBlockWatchingPacket extends CoordinatesPacket {\n\n\tpublic HUDStartBlockWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDStartBlockWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIBlockWatchingHandler tile = this.getTileAs(player.world, IBlockWatchingHandler.class);\n\t\tif (tile != null) {\n\t\t\ttile.playerStartWatching(player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDStartModuleWatchingPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class HUDStartModuleWatchingPacket extends ModuleCoordinatesPacket {\n\n\tpublic HUDStartModuleWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDStartModuleWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIModuleWatchReciver handler = this.getLogisticsModule(player, IModuleWatchReciver.class);\n\t\tif (handler == null) {\n\t\t\treturn;\n\t\t}\n\t\thandler.startWatching(player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDStartWatchingPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IWatchingHandler;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class HUDStartWatchingPacket extends IntegerCoordinatesPacket {\n\n\tpublic HUDStartWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDStartWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof IWatchingHandler) {\n\t\t\tIWatchingHandler handler = (IWatchingHandler) pipe.pipe;\n\t\t\thandler.playerStartWatching(player, getInteger());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDStopBlockWatchingPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IBlockWatchingHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class HUDStopBlockWatchingPacket extends CoordinatesPacket {\n\n\tpublic HUDStopBlockWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDStopBlockWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIBlockWatchingHandler tile = this.getTileAs(player.world, IBlockWatchingHandler.class);\n\t\tif (tile != null) {\n\t\t\ttile.playerStopWatching(player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDStopModuleWatchingPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IModuleWatchReciver;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class HUDStopModuleWatchingPacket extends ModuleCoordinatesPacket {\n\n\tpublic HUDStopModuleWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDStopModuleWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIModuleWatchReciver handler = this.getLogisticsModule(player, IModuleWatchReciver.class);\n\t\tif (handler == null) {\n\t\t\treturn;\n\t\t}\n\t\thandler.stopWatching(player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/hud/HUDStopWatchingPacket.java",
    "content": "package logisticspipes.network.packets.hud;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IWatchingHandler;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class HUDStopWatchingPacket extends IntegerCoordinatesPacket {\n\n\tpublic HUDStopWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new HUDStopWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof IWatchingHandler) {\n\t\t\tIWatchingHandler handler = (IWatchingHandler) pipe.pipe;\n\t\t\thandler.playerStopWatching(player, getInteger());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/module/AdvancedExtractorSneakyGuiPacket.java",
    "content": "package logisticspipes.network.packets.module;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.network.guis.module.inhand.SneakyModuleInHandGuiProvider;\nimport logisticspipes.network.guis.module.inpipe.SneakyModuleInSlotGuiProvider;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.DummyModuleContainer;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\n\n@StaticResolve\npublic class AdvancedExtractorSneakyGuiPacket extends ModuleCoordinatesPacket {\n\n\tpublic AdvancedExtractorSneakyGuiPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new AdvancedExtractorSneakyGuiPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (getType() == ModulePositionType.IN_HAND) {\n\t\t\tif (player.openContainer instanceof DummyModuleContainer) {\n\t\t\t\tDummyModuleContainer dummy = (DummyModuleContainer) player.openContainer;\n\t\t\t\tif (dummy.getModule() instanceof AsyncAdvancedExtractor) {\n\t\t\t\t\tplayer.closeScreen();\n\t\t\t\t\tNewGuiHandler.getGui(SneakyModuleInHandGuiProvider.class).setInvSlot(getPositionInt()).open(player);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tPipeLogisticsChassis pipe = getTileOrPipe(player.world, PipeLogisticsChassis.class);\n\t\tLogisticsModule subModule = pipe.getSubModule(getPositionInt());\n\t\tif (subModule instanceof AsyncAdvancedExtractor) {\n\t\t\tNewGuiHandler.getGui(SneakyModuleInSlotGuiProvider.class)\n\t\t\t\t\t.setSneakyOrientation(((AsyncAdvancedExtractor) subModule).getSneakyDirection())\n\t\t\t\t\t.setSlot(getType())\n\t\t\t\t\t.setPositionInt(getPositionInt())\n\t\t\t\t\t.setPosX(getPosX())\n\t\t\t\t\t.setPosY(getPosY())\n\t\t\t\t\t.setPosZ(getPosZ())\n\t\t\t\t\t.open(player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/module/ItemSinkImportPacket.java",
    "content": "package logisticspipes.network.packets.module;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.gui.module.ItemSinkGui;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ItemSinkImportPacket extends ModuleCoordinatesPacket {\n\n\t@Nullable\n\t@Setter\n\t@Getter\n\tpublic List<ItemIdentifier> importedItems = null;\n\n\tpublic ItemSinkImportPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(importedItems, LPDataOutput::writeItemIdentifier);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\timportedItems = input.readArrayList(LPDataInput::readItemIdentifier);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ItemSinkImportPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (MainProxy.isServer(player.world)) {\n\t\t\tModuleItemSink module = this.getLogisticsModule(player, ModuleItemSink.class);\n\t\t\tif (module == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ItemSinkImportPacket.class)\n\t\t\t\t.setImportedItems(module.getAdjacentInventoriesItems()\n\t\t\t\t\t.limit(module.filterInventory.getSizeInventory())\n\t\t\t\t\t.collect(Collectors.toList()))\n\t\t\t\t.setPacketPos(this), player);\n\t\t} else if (MainProxy.isClient(player.world)) {\n\t\t\tif (importedItems == null) return;\n\t\t\tif (Minecraft.getMinecraft().currentScreen instanceof ItemSinkGui) {\n\t\t\t\t((ItemSinkGui) Minecraft.getMinecraft().currentScreen).importFromInventory(importedItems);\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/module/ModuleBasedItemSinkList.java",
    "content": "package logisticspipes.network.packets.module;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.IStringBasedModule;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ModuleBasedItemSinkList extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate NBTTagCompound nbt;\n\n\tpublic ModuleBasedItemSinkList(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ModuleBasedItemSinkList(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tIStringBasedModule module = this.getLogisticsModule(player, IStringBasedModule.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.readFromNBT(nbt);\n\t\tif (MainProxy.isServer(player.getEntityWorld()) && getType().isInWorld()) {\n\t\t\tmodule.listChanged();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeNBTTagCompound(nbt);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tnbt = input.readNBTTagCompound();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/module/ModuleInventory.java",
    "content": "package logisticspipes.network.packets.module;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IModuleInventoryReceive;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ModuleInventory extends InventoryModuleCoordinatesPacket {\n\n\tpublic ModuleInventory(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ModuleInventory(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (getIdentList() == null) return;\n\t\tIModuleInventoryReceive module = this.getLogisticsModule(player, IModuleInventoryReceive.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.handleInvContent(getIdentList());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/module/ModulePropertiesUpdate.java",
    "content": "package logisticspipes.network.packets.module;\n\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.ContainerPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.logisticspipes.ItemModuleInformationManager;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.property.PropertyHolder;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ModulePropertiesUpdate extends ModuleCoordinatesPacket {\n\n\t@Nonnull\n\tpublic NBTTagCompound tag = new NBTTagCompound();\n\n\tpublic ModulePropertiesUpdate(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeNBTTagCompound(tag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttag = Objects.requireNonNull(input.readNBTTagCompound(), \"read null NBT in ModulePropertiesUpdate\");\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ModulePropertiesUpdate(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsModule module = this.getLogisticsModule(player, LogisticsModule.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\n\t\t// sync updated properties\n\t\tmodule.readFromNBT(tag);\n\n\t\tif (!getType().isInWorld() && player.openContainer instanceof ContainerPlayer) {\n\t\t\t// FIXME: saveInformation & markDirty on module property change? should be called only once\n\t\t\t// sync slot in player inventory and mark player inventory dirty\n\t\t\tItemModuleInformationManager.saveInformation(player.inventory.mainInventory.get(getPositionInt()), module);\n\t\t\tplayer.inventory.markDirty();\n\t\t}\n\n\t\tMainProxy.runOnServer(player.world, () -> () -> {\n\t\t\t// resync client; always\n\t\t\tMainProxy.sendPacketToPlayer(fromPropertyHolder(module).setModulePos(module), player);\n\t\t});\n\t}\n\n\t@Nonnull\n\tpublic static ModuleCoordinatesPacket fromPropertyHolder(PropertyHolder holder) {\n\t\tfinal ModulePropertiesUpdate packet = PacketHandler.getPacket(ModulePropertiesUpdate.class);\n\t\tPropertyHolder.writeToNBT(packet.tag, holder);\n\t\treturn packet;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/module/OreDictItemSinkList.java",
    "content": "package logisticspipes.network.packets.module;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.NBTModuleCoordinatesPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OreDictItemSinkList extends NBTModuleCoordinatesPacket {\n\n\tpublic OreDictItemSinkList(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OreDictItemSinkList(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleOreDictItemSink module = this.getLogisticsModule(player, ModuleOreDictItemSink.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.readFromNBT(getTag());\n\t\tif (MainProxy.isServer(player.getEntityWorld()) && getType().isInWorld()) {\n\t\t\tmodule.OreListChanged();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/AdvancedExtractorInclude.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.BooleanModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\n\n@StaticResolve\npublic class AdvancedExtractorInclude extends BooleanModuleCoordinatesPacket {\n\n\tpublic AdvancedExtractorInclude(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new AdvancedExtractorInclude(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tAsyncAdvancedExtractor receiver = this.getLogisticsModule(player, AsyncAdvancedExtractor.class);\n\t\tif (receiver == null) {\n\t\t\treturn;\n\t\t}\n\t\treceiver.getItemsIncluded().setValue(isFlag());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/ItemSinkDefault.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.network.abstractpackets.BooleanModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ItemSinkDefault extends BooleanModuleCoordinatesPacket {\n\n\tpublic ItemSinkDefault(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ItemSinkDefault(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleItemSink module = this.getLogisticsModule(player, ModuleItemSink.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.setDefaultRoute(isFlag());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/ProviderModuleInclude.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.network.abstractpackets.BooleanModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ProviderModuleInclude extends BooleanModuleCoordinatesPacket {\n\n\tpublic ProviderModuleInclude(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ProviderModuleInclude(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal ModuleProvider module = this.getLogisticsModule(player, ModuleProvider.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.isExclusionFilter.setValue(isFlag());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/ProviderModuleMode.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ProviderModuleMode extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int mode;\n\n\tpublic ProviderModuleMode(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ProviderModuleMode(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal ModuleProvider module = this.getLogisticsModule(player, ModuleProvider.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.providerMode.setValue(ProviderMode.modeFromIntSafe(mode));\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(mode);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tmode = input.readInt();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/QuickSortState.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.QuickSortChestMarkerStorage;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class QuickSortState extends IntegerModuleCoordinatesPacket {\n\n\tpublic QuickSortState(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tQuickSortChestMarkerStorage.getInstance().setSlots(getPosX(), getPosY(), getPosZ(), getPositionInt(), getInteger());\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new QuickSortState(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/SneakyModuleDirectionUpdate.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.DirectionModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.module.SneakyDirection;\n\n@StaticResolve\npublic class SneakyModuleDirectionUpdate extends DirectionModuleCoordinatesPacket {\n\n\tpublic SneakyModuleDirectionUpdate(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SneakyModuleDirectionUpdate(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tSneakyDirection sneakyModule = this.getLogisticsModule(player, SneakyDirection.class);\n\t\tif (sneakyModule == null) {\n\t\t\treturn;\n\t\t}\n\t\tsneakyModule.setSneakyDirection(getDirection());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/modules/SupplierPipeMode.java",
    "content": "package logisticspipes.network.packets.modules;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.GuiSupplierPipe;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.modules.ModuleActiveSupplier.PatternMode;\nimport logisticspipes.modules.ModuleActiveSupplier.SupplyMode;\nimport logisticspipes.network.abstractpackets.IntegerModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SupplierPipeMode extends IntegerModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate boolean hasPatternUpgrade;\n\n\tpublic SupplierPipeMode(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SupplierPipeMode(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleActiveSupplier module = this.getLogisticsModule(player, ModuleActiveSupplier.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (hasPatternUpgrade) {\n\t\t\tmodule.patternMode.setValue(PatternMode.values()[getInteger()]);\n\t\t} else {\n\t\t\tmodule.requestMode.setValue(SupplyMode.values()[getInteger()]);\n\t\t}\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiSupplierPipe) {\n\t\t\t((GuiSupplierPipe) FMLClientHandler.instance().getClient().currentScreen).refreshMode();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\thasPatternUpgrade = input.readBoolean();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(hasPatternUpgrade);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/multiblock/MultiBlockCoordinatesPacket.java",
    "content": "package logisticspipes.network.packets.multiblock;\n\nimport java.util.List;\nimport java.util.Set;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@StaticResolve\npublic class MultiBlockCoordinatesPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate Set<DoubleCoordinates> targetPos;\n\n\t@Getter\n\t@Setter\n\tprivate List<CoreMultiBlockPipe.SubBlockTypeForShare> subTypes;\n\n\tpublic MultiBlockCoordinatesPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(targetPos);\n\t\toutput.writeCollection(subTypes, LPDataOutput::writeEnum);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttargetPos = input.readSet(DoubleCoordinates::new);\n\t\tsubTypes = input.readArrayList(data1 -> data1.readEnum(CoreMultiBlockPipe.SubBlockTypeForShare.class));\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericSubMultiBlock block = this.getTileAs(player.getEntityWorld(), LogisticsTileGenericSubMultiBlock.class);\n\t\tblock.setPosition(targetPos, subTypes);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new MultiBlockCoordinatesPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/ComponentList.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.config.Configs;\nimport logisticspipes.gui.orderer.GuiOrderer;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.IResource.ColorCode;\nimport logisticspipes.request.resources.ResourceNetwork;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ComponentList extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate Collection<IResource> used = new ArrayList<>();\n\n\t@Getter\n\t@Setter\n\tprivate Collection<IResource> missing = new ArrayList<>();\n\n\tpublic ComponentList(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ComponentList(getId());\n\t}\n\n\t@Override\n\t@ClientSideOnlyMethodContent\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (Configs.DISPLAY_POPUP && FMLClientHandler.instance().getClient().currentScreen instanceof GuiOrderer) {\n\t\t\t((GuiOrderer) FMLClientHandler.instance().getClient().currentScreen)\n\t\t\t\t\t.handleSimulateAnswer(used, missing, (GuiOrderer) FMLClientHandler.instance().getClient().currentScreen, player);\n\t\t} else if (Configs.DISPLAY_POPUP && FMLClientHandler.instance().getClient().currentScreen instanceof GuiRequestTable) {\n\t\t\t((GuiRequestTable) FMLClientHandler.instance().getClient().currentScreen)\n\t\t\t\t\t.handleSimulateAnswer(used, missing, (GuiRequestTable) FMLClientHandler.instance().getClient().currentScreen, player);\n\t\t} else {\n\t\t\tfor (IResource item : used) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(\"Component: \" + item.getDisplayText(ColorCode.SUCCESS)));\n\t\t\t}\n\t\t\tfor (IResource item : missing) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(\"Missing: \" + item.getDisplayText(ColorCode.MISSING)));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeCollection(used);\n\t\toutput.writeCollection(missing);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tused = input.readArrayList(ResourceNetwork::readResource);\n\t\tmissing = input.readArrayList(ResourceNetwork::readResource);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/DiscContent.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.network.abstractpackets.ItemPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class DiscContent extends ItemPacket {\n\n\tpublic DiscContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DiscContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe tile = this.getPipe(player.world);\n\t\tif (tile == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (tile.pipe instanceof PipeItemsRequestLogisticsMk2) {\n\t\t\tif (MainProxy.isServer(tile.getWorld())) {\n\t\t\t\tif (!((PipeItemsRequestLogisticsMk2) tile.pipe).getDisk().isEmpty() && ((PipeItemsRequestLogisticsMk2) tile.pipe).getDisk().getItem().equals(LPItems.disk)) {\n\t\t\t\t\tif (!getStack().isEmpty() && getStack().getItem().equals(LPItems.disk)) {\n\t\t\t\t\t\t((PipeItemsRequestLogisticsMk2) tile.pipe).getDisk().setTagCompound(getStack().getTagCompound());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t((PipeItemsRequestLogisticsMk2) tile.pipe).setDisk(getStack());\n\t\t\t}\n\t\t}\n\t\tif (tile.pipe instanceof PipeBlockRequestTable) {\n\t\t\tif (MainProxy.isServer(tile.getWorld())) {\n\t\t\t\tif (!((PipeBlockRequestTable) tile.pipe).diskInv.getStackInSlot(0).isEmpty() && ((PipeBlockRequestTable) tile.pipe).diskInv.getStackInSlot(0).getItem().equals(LPItems.disk)) {\n\t\t\t\t\tif (!getStack().isEmpty() && getStack().getItem().equals(LPItems.disk)) {\n\t\t\t\t\t\t((PipeBlockRequestTable) tile.pipe).diskInv.getStackInSlot(0).setTagCompound(getStack().getTagCompound());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t((PipeBlockRequestTable) tile.pipe).diskInv.setInventorySlotContents(0, getStack());\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/DiskDropPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class DiskDropPacket extends CoordinatesPacket {\n\n\tpublic DiskDropPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DiskDropPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeItemsRequestLogisticsMk2) {\n\t\t\tif (((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk() != null) {\n\t\t\t\tif (((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().getItem().equals(LPItems.disk)) {\n\t\t\t\t\tif (!((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().hasTagCompound()) {\n\t\t\t\t\t\t((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().setTagCompound(new NBTTagCompound());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t((PipeItemsRequestLogisticsMk2) pipe.pipe).dropDisk();\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(DiscContent.class).setStack(((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk()).setBlockPos(pipe.getPos()), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/DiskMacroRequestPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class DiskMacroRequestPacket extends IntegerCoordinatesPacket {\n\n\tpublic DiskMacroRequestPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DiskMacroRequestPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeItemsRequestLogisticsMk2) {\n\t\t\tif (((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk() == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().getItem().equals(LPItems.disk)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().hasTagCompound()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tNBTTagCompound nbt = ((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().getTagCompound();\n\t\t\tif (!nbt.hasKey(\"macroList\")) {\n\t\t\t\tNBTTagList list = new NBTTagList();\n\t\t\t\tnbt.setTag(\"macroList\", list);\n\t\t\t}\n\t\t\tNBTTagList list = nbt.getTagList(\"macroList\", 10);\n\t\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\t\tif (i == getInteger()) {\n\t\t\t\t\tNBTTagCompound itemlist = list.getCompoundTagAt(i);\n\t\t\t\t\tRequestHandler.requestMacrolist(itemlist, (PipeItemsRequestLogisticsMk2) pipe.pipe, player);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (pipe.pipe instanceof PipeBlockRequestTable) {\n\t\t\tif (((PipeBlockRequestTable) pipe.pipe).getDisk() == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!((PipeBlockRequestTable) pipe.pipe).getDisk().getItem().equals(LPItems.disk)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!((PipeBlockRequestTable) pipe.pipe).getDisk().hasTagCompound()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tNBTTagCompound nbt = ((PipeBlockRequestTable) pipe.pipe).getDisk().getTagCompound();\n\t\t\tif (!nbt.hasKey(\"macroList\")) {\n\t\t\t\tNBTTagList list = new NBTTagList();\n\t\t\t\tnbt.setTag(\"macroList\", list);\n\t\t\t}\n\t\t\tNBTTagList list = nbt.getTagList(\"macroList\", 10);\n\t\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\t\tif (i == getInteger()) {\n\t\t\t\t\tNBTTagCompound itemlist = list.getCompoundTagAt(i);\n\t\t\t\t\tRequestHandler.requestMacrolist(itemlist, (PipeBlockRequestTable) pipe.pipe, player);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/DiskRequestConectPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class DiskRequestConectPacket extends CoordinatesPacket {\n\n\tpublic DiskRequestConectPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DiskRequestConectPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeItemsRequestLogisticsMk2) {\n\t\t\tif (((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk() != null) {\n\t\t\t\tif (((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().getItem().equals(LPItems.disk)) {\n\t\t\t\t\tif (!((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().hasTagCompound()) {\n\t\t\t\t\t\t((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().setTagCompound(new NBTTagCompound());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(DiscContent.class).setStack(((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk()).setBlockPos(pipe.getPos()), player);\n\t\t}\n\t\tif (pipe.pipe instanceof PipeBlockRequestTable) {\n\t\t\tif (((PipeBlockRequestTable) pipe.pipe).diskInv.getStackInSlot(0) != null) {\n\t\t\t\tif (((PipeBlockRequestTable) pipe.pipe).diskInv.getStackInSlot(0).getItem().equals(LPItems.disk)) {\n\t\t\t\t\tif (!((PipeBlockRequestTable) pipe.pipe).diskInv.getStackInSlot(0).hasTagCompound()) {\n\t\t\t\t\t\t((PipeBlockRequestTable) pipe.pipe).diskInv.getStackInSlot(0).setTagCompound(new NBTTagCompound());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(DiscContent.class).setStack(((PipeBlockRequestTable) pipe.pipe).diskInv.getStackInSlot(0)).setBlockPos(pipe.getPos()), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/DiskSetNamePacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringCoordinatesPacket;\nimport logisticspipes.pipes.PipeItemsRequestLogisticsMk2;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class DiskSetNamePacket extends StringCoordinatesPacket {\n\n\tpublic DiskSetNamePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new DiskSetNamePacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeItemsRequestLogisticsMk2) {\n\t\t\tif (((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk() == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().getItem().equals(LPItems.disk)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().hasTagCompound()) {\n\t\t\t\t((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().setTagCompound(new NBTTagCompound());\n\t\t\t}\n\t\t\tNBTTagCompound nbt = ((PipeItemsRequestLogisticsMk2) pipe.pipe).getDisk().getTagCompound();\n\t\t\tnbt.setString(\"name\", getString());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/MissingItems.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.config.Configs;\nimport logisticspipes.gui.orderer.GuiOrderer;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.IResource.ColorCode;\nimport logisticspipes.request.resources.ResourceNetwork;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class MissingItems extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate Collection<IResource> items = new ArrayList<>();\n\n\t@Setter\n\t@Getter\n\tprivate boolean flag;\n\n\tpublic MissingItems(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new MissingItems(getId());\n\t}\n\n\t@Override\n\t@ClientSideOnlyMethodContent\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (Configs.DISPLAY_POPUP && FMLClientHandler.instance().getClient().currentScreen instanceof GuiOrderer) {\n\t\t\t((GuiOrderer) FMLClientHandler.instance().getClient().currentScreen)\n\t\t\t\t\t.handleRequestAnswer(getItems(), isFlag(), (GuiOrderer) FMLClientHandler.instance().getClient().currentScreen, player);\n\t\t} else if (Configs.DISPLAY_POPUP && FMLClientHandler.instance().getClient().currentScreen instanceof GuiRequestTable) {\n\t\t\t((GuiRequestTable) FMLClientHandler.instance().getClient().currentScreen)\n\t\t\t\t\t.handleRequestAnswer(getItems(), isFlag(), (GuiRequestTable) FMLClientHandler.instance().getClient().currentScreen, player);\n\t\t} else if (isFlag()) {\n\t\t\tfor (IResource item : items) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"Missing: \" + item.getDisplayText(ColorCode.MISSING)));\n\t\t\t}\n\t\t} else {\n\t\t\tfor (IResource item : items) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.GREEN + \"Requested: \" + item.getDisplayText(ColorCode.SUCCESS)));\n\t\t\t}\n\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.GREEN + \"Request successful!\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeCollection(items);\n\t\toutput.writeBoolean(isFlag());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\titems = input.readArrayList(ResourceNetwork::readResource);\n\t\tsetFlag(input.readBoolean());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/OrderWatchRemovePacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IRequestWatcher;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OrderWatchRemovePacket extends IntegerCoordinatesPacket {\n\n\tpublic OrderWatchRemovePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.world);\n\t\tif (tile != null && tile.pipe instanceof IRequestWatcher) {\n\t\t\t((IRequestWatcher) tile.pipe).handleClientSideRemove(getInteger());\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OrderWatchRemovePacket(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/OrdererContent.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.gui.orderer.GuiOrderer;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OrdererContent extends InventoryModuleCoordinatesPacket {\n\n\tpublic OrdererContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OrdererContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiOrderer) {\n\t\t\t((GuiOrderer) FMLClientHandler.instance().getClient().currentScreen).handlePacket(getIdentList());\n\t\t} else if (FMLClientHandler.instance().getClient().currentScreen instanceof GuiRequestTable) {\n\t\t\t((GuiRequestTable) FMLClientHandler.instance().getClient().currentScreen).handlePacket(getIdentList());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/OrdererManagerContent.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.IOrderManagerContentReceiver;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OrdererManagerContent extends InventoryModuleCoordinatesPacket {\n\n\tpublic OrdererManagerContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OrdererManagerContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe tile = this.getPipe(player.world);\n\t\tif (tile == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (tile.pipe instanceof IOrderManagerContentReceiver) {\n\t\t\t((IOrderManagerContentReceiver) tile.pipe).setOrderManagerContent(getIdentList());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/OrdererRefreshRequestPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class OrdererRefreshRequestPacket extends IntegerCoordinatesPacket {\n\n\tpublic OrdererRefreshRequestPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OrdererRefreshRequestPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tint dimension = (getInteger() - (getInteger() % 10)) / 10;\n\t\tfinal LogisticsTileGenericPipe pipe = MainProxy.proxy.getPipeInDimensionAt(dimension, getPosX(), getPosY(), getPosZ(), player);\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tRequestHandler.DisplayOptions option;\n\t\tswitch (getInteger() % 10) {\n\t\t\tcase 0:\n\t\t\t\toption = RequestHandler.DisplayOptions.Both;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\toption = RequestHandler.DisplayOptions.SupplyOnly;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\toption = RequestHandler.DisplayOptions.CraftOnly;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\toption = RequestHandler.DisplayOptions.Both;\n\t\t\t\tbreak;\n\t\t}\n\t\tRequestHandler.refresh(player, (CoreRoutedPipe) pipe.pipe, option);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/OrdererWatchPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.IRequestWatcher;\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ResourceNetwork;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class OrdererWatchPacket extends IntegerCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate IResource stack;\n\n\t@Getter\n\t@Setter\n\tprivate LinkedLogisticsOrderList orders;\n\n\tpublic OrdererWatchPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\tResourceNetwork.writeResource(output, stack); //stack can be null\n\t\toutput.writeSerializable(orders);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tstack = ResourceNetwork.readResource(input);\n\t\torders = new LinkedLogisticsOrderList(input);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.world);\n\t\tif (tile.pipe instanceof IRequestWatcher) {\n\t\t\t((IRequestWatcher) tile.pipe).handleClientSideListInfo(getInteger(), getStack(), getOrders());\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new OrdererWatchPacket(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/RequestComponentPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.RequestPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestComponentPacket extends RequestPacket {\n\n\tpublic RequestComponentPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestComponentPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = MainProxy.proxy.getPipeInDimensionAt(getDimension(), getPosX(), getPosY(), getPosZ(), player);\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tRequestHandler.simulate(player, getStack(), (CoreRoutedPipe) pipe.pipe);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/RequestFluidOrdererRefreshPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestFluidOrdererRefreshPacket extends IntegerCoordinatesPacket {\n\n\tpublic RequestFluidOrdererRefreshPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestFluidOrdererRefreshPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tint dimension = getInteger();\n\t\tfinal LogisticsTileGenericPipe pipe = MainProxy.proxy.getPipeInDimensionAt(dimension, getPosX(), getPosY(), getPosZ(), player);\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tRequestHandler.refreshFluid(player, (CoreRoutedPipe) pipe.pipe);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/RequestSubmitListPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestSubmitListPacket extends InventoryModuleCoordinatesPacket {\n\n\tpublic RequestSubmitListPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestSubmitListPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!(pipe.pipe instanceof PipeBlockRequestTable)) {\n\t\t\treturn;\n\t\t}\n\t\tRequestHandler.requestList(player, getIdentList(), (CoreRoutedPipe) pipe.pipe);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/RequestSubmitPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.RequestPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestSubmitPacket extends RequestPacket {\n\n\tpublic RequestSubmitPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestSubmitPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = MainProxy.proxy.getPipeInDimensionAt(getDimension(), getPosX(), getPosY(), getPosZ(), player);\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tRequestHandler.request(player, getStack(), (CoreRoutedPipe) pipe.pipe);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/orderer/SubmitFluidRequestPacket.java",
    "content": "package logisticspipes.network.packets.orderer;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.RequestPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SubmitFluidRequestPacket extends RequestPacket {\n\n\tpublic SubmitFluidRequestPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SubmitFluidRequestPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = MainProxy.proxy.getPipeInDimensionAt(getDimension(), getPosX(), getPosY(), getPosZ(), player);\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe) || !(pipe.pipe instanceof IRequestFluid)) {\n\t\t\treturn;\n\t\t}\n\t\tRequestHandler.requestFluid(player, getStack(), (CoreRoutedPipe) pipe.pipe, (IRequestFluid) pipe.pipe);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/AskForOpenTarget.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.RayTraceResult;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class AskForOpenTarget extends ModernPacket {\n\n\tpublic AskForOpenTarget(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tRayTraceResult box = FMLClientHandler.instance().getClient().objectMouseOver;\n\t\tif (box.typeOfHit == RayTraceResult.Type.BLOCK) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SlotFinderActivatePacket.class)\n\t\t\t\t\t.setTargetPosX(box.getBlockPos().getX())\n\t\t\t\t\t.setTargetPosY(box.getBlockPos().getY())\n\t\t\t\t\t.setTargetPosZ(box.getBlockPos().getZ()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new AskForOpenTarget(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/ChassisOrientationPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ChassisOrientationPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\t@Nullable\n\tprivate EnumFacing dir;\n\n\tpublic ChassisOrientationPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof PipeLogisticsChassis) {\n\t\t\t((PipeLogisticsChassis) pipe.pipe).setPointedOrientation(dir);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChassisOrientationPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/ChassisPipeModuleContent.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class ChassisPipeModuleContent extends InventoryModuleCoordinatesPacket {\n\n\tpublic ChassisPipeModuleContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ChassisPipeModuleContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof PipeLogisticsChassis) {\n\t\t\tPipeLogisticsChassis chassis = (PipeLogisticsChassis) pipe.pipe;\n\t\t\tchassis.handleModuleItemIdentifierList(getIdentList());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/CraftingPipeSetSatellitePacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.IntegerModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n/**\n * Created by davboecki on 20/06/2019.\n * All rights reserved.\n */\n@StaticResolve\npublic class CraftingPipeSetSatellitePacket extends IntegerModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate UUID pipeID;\n\n\tpublic CraftingPipeSetSatellitePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tpipeID = input.readUUID();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeUUID(pipeID);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (getInteger() == 0) {\n\t\t\tmodule.setSatelliteUUID(getPipeID());\n\t\t} else if (getInteger() >= 10 && getInteger() < 20) {\n\t\t\tmodule.setAdvancedSatelliteUUID(getInteger() - 10, getPipeID());\n\t\t} else if (getInteger() == 100) {\n\t\t\tmodule.setFluidSatelliteUUID(getPipeID());\n\t\t} else if (getInteger() >= 110 && getInteger() <= 120) {\n\t\t\tmodule.setAdvancedFluidSatelliteUUID(getInteger() - 110, getPipeID());\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CraftingPipeSetSatellitePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/CraftingPipeUpdatePacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class CraftingPipeUpdatePacket extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int[] amount = new int[ItemUpgrade.MAX_LIQUID_CRAFTER];\n\n\t@Getter\n\t@Setter\n\tprivate String[] liquidSatelliteNameArray = new String[ItemUpgrade.MAX_LIQUID_CRAFTER];\n\n\t@Getter\n\t@Setter\n\tprivate String liquidSatelliteName = \"\";\n\n\t@Getter\n\t@Setter\n\tprivate String satelliteName = \"\";\n\n\t@Getter\n\t@Setter\n\tprivate String[] advancedSatelliteNameArray = new String[9];\n\n\t@Getter\n\t@Setter\n\tprivate int priority = 0;\n\n\tpublic CraftingPipeUpdatePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.handleCraftingUpdatePacket(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeIntArray(amount);\n\t\toutput.writeUTFArray(liquidSatelliteNameArray);\n\t\toutput.writeUTF(liquidSatelliteName);\n\t\toutput.writeUTF(satelliteName);\n\t\toutput.writeUTFArray(advancedSatelliteNameArray);\n\t\toutput.writeInt(priority);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tamount = input.readIntArray();\n\t\tliquidSatelliteNameArray = input.readUTFArray();\n\t\tliquidSatelliteName = input.readUTF();\n\t\tsatelliteName = input.readUTF();\n\t\tadvancedSatelliteNameArray = input.readUTFArray();\n\t\tpriority = input.readInt();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CraftingPipeUpdatePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/CraftingPriority.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.IntegerModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class CraftingPriority extends IntegerModuleCoordinatesPacket {\n\n\tpublic CraftingPriority(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new CraftingPriority(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\tmodule.priority.setValue(getInteger());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/FindMostLikelyRecipeComponents.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.TreeSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.gui.popup.GuiRecipeImport;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\n\n@StaticResolve\npublic class FindMostLikelyRecipeComponents extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate List<GuiRecipeImport.Candidates> content;\n\n\tpublic FindMostLikelyRecipeComponents(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity tile = this.getTileAs(player.getEntityWorld(), TileEntity.class);\n\t\tCoreRoutedPipe pipe = null;\n\t\tif (tile instanceof LogisticsCraftingTableTileEntity) {\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tTileEntity conn = CoordinateUtils.add(((LogisticsCraftingTableTileEntity) tile).getLPPosition(), dir).getTileEntity(player.getEntityWorld());\n\t\t\t\tif (conn instanceof LogisticsTileGenericPipe) {\n\t\t\t\t\tif (((LogisticsTileGenericPipe) conn).pipe instanceof PipeItemsCraftingLogistics) {\n\t\t\t\t\t\tpipe = (CoreRoutedPipe) ((LogisticsTileGenericPipe) conn).pipe;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tif (((LogisticsTileGenericPipe) tile).pipe instanceof PipeBlockRequestTable) {\n\t\t\t\tpipe = (CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe;\n\t\t\t}\n\t\t}\n\t\tList<Integer> list = new ArrayList<Integer>(content.size());\n\t\twhile (list.size() < content.size()) {\n\t\t\tlist.add(-1);\n\t\t}\n\t\tif (pipe == null) return;\n\t\tLinkedList<ItemIdentifier> craftable = null;\n\t\tfor (int j = 0; j < content.size(); j++) {\n\t\t\tGuiRecipeImport.Candidates candidates = content.get(j);\n\t\t\tint maxItemPos = -1;\n\t\t\tint max = 0;\n\t\t\tfor (int i = 0; i < candidates.order.size(); i++) {\n\t\t\t\tItemIdentifier ident = candidates.order.get(i).getItem();\n\t\t\t\tint newAmount = SimpleServiceLocator.logisticsManager.getAmountFor(ident, pipe.getRouter().getIRoutersByCost());\n\t\t\t\tif (newAmount > max) {\n\t\t\t\t\tmax = newAmount;\n\t\t\t\t\tmaxItemPos = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (max < 64) {\n\t\t\t\tif (craftable == null) {\n\t\t\t\t\tcraftable = SimpleServiceLocator.logisticsManager.getCraftableItems(pipe.getRouter().getIRoutersByCost());\n\t\t\t\t}\n\t\t\t\tfor (ItemIdentifier craft : craftable) {\n\t\t\t\t\tfor (int i = 0; i < candidates.order.size(); i++) {\n\t\t\t\t\t\tItemIdentifier ident = candidates.order.get(i).getItem();\n\t\t\t\t\t\tif (craft == ident) {\n\t\t\t\t\t\t\tmaxItemPos = i;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlist.set(j, maxItemPos);\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MostLikelyRecipeComponentsResponse.class).setResponse(list), player);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tcontent = input.readArrayList(input1 -> {\n\t\t\tGuiRecipeImport.Candidates can = new GuiRecipeImport.Candidates(new TreeSet<>());\n\t\t\tcan.order = input1.readArrayList(LPDataInput::readItemIdentifierStack);\n\t\t\treturn can;\n\t\t});\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(content, (data, object) -> data.writeCollection(object.order,\n\t\t\t\tLPDataOutput::writeItemIdentifierStack));\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FindMostLikelyRecipeComponents(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/FireWallFlag.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.BitSetCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeItemsFirewall;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class FireWallFlag extends BitSetCoordinatesPacket {\n\n\tpublic FireWallFlag(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FireWallFlag(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeItemsFirewall) {\n\t\t\tPipeItemsFirewall firewall = (PipeItemsFirewall) pipe.pipe;\n\t\t\tfirewall.setFlags(getFlags());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/FluidCraftingAmount.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.abstractpackets.Integer2ModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class FluidCraftingAmount extends Integer2ModuleCoordinatesPacket {\n\n\tpublic FluidCraftingAmount(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FluidCraftingAmount(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tModuleCrafter module = this.getLogisticsModule(player, ModuleCrafter.class);\n\t\tif (module == null) {\n\t\t\treturn;\n\t\t}\n\t\t// integer2 is the slot and integer is the amount\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tmodule.liquidAmounts.set(getInteger2(), getInteger());\n\t\t} else {\n\t\t\tmodule.changeFluidAmount(getInteger(), getInteger2(), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/FluidSupplierAmount.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeFluidSupplierMk2;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class FluidSupplierAmount extends IntegerCoordinatesPacket {\n\n\tpublic FluidSupplierAmount(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FluidSupplierAmount(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!(pipe.pipe instanceof PipeFluidSupplierMk2)) {\n\t\t\treturn;\n\t\t}\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\t((PipeFluidSupplierMk2) pipe.pipe).setAmount(getInteger());\n\t\t} else {\n\t\t\t((PipeFluidSupplierMk2) pipe.pipe).changeFluidAmount(getInteger(), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/FluidSupplierMinMode.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeFluidSupplierMk2;\nimport logisticspipes.pipes.PipeFluidSupplierMk2.MinMode;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class FluidSupplierMinMode extends IntegerCoordinatesPacket {\n\n\tpublic FluidSupplierMinMode(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FluidSupplierMinMode(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeFluidSupplierMk2) {\n\t\t\t((PipeFluidSupplierMk2) pipe.pipe).setMinMode(MinMode.values()[getInteger()]);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/FluidSupplierMode.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeFluidSupplierMk2;\nimport logisticspipes.pipes.PipeItemsFluidSupplier;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class FluidSupplierMode extends IntegerCoordinatesPacket {\n\n\tpublic FluidSupplierMode(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new FluidSupplierMode(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tif (pipe.pipe instanceof PipeItemsFluidSupplier) {\n\t\t\t\t((PipeItemsFluidSupplier) pipe.pipe).setRequestingPartials((getInteger() % 10) == 1);\n\t\t\t}\n\t\t\tif (pipe.pipe instanceof PipeFluidSupplierMk2) {\n\t\t\t\t((PipeFluidSupplierMk2) pipe.pipe).setRequestingPartials((getInteger() % 10) == 1);\n\t\t\t}\n\t\t} else {\n\t\t\tif (pipe.pipe instanceof PipeItemsFluidSupplier) {\n\t\t\t\tPipeItemsFluidSupplier liquid = (PipeItemsFluidSupplier) pipe.pipe;\n\t\t\t\tliquid.setRequestingPartials((getInteger() % 10) == 1);\n\t\t\t}\n\t\t\tif (pipe.pipe instanceof PipeFluidSupplierMk2) {\n\t\t\t\tPipeFluidSupplierMk2 liquid = (PipeFluidSupplierMk2) pipe.pipe;\n\t\t\t\tliquid.setRequestingPartials((getInteger() % 10) == 1);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/InvSysConContent.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.gui.GuiInvSysConnector;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class InvSysConContent extends InventoryModuleCoordinatesPacket {\n\n\tpublic InvSysConContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new InvSysConContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiInvSysConnector) {\n\t\t\t((GuiInvSysConnector) FMLClientHandler.instance().getClient().currentScreen).handleContentAnswer(getIdentList());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/InvSysConContentRequest.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class InvSysConContentRequest extends CoordinatesPacket {\n\n\tpublic InvSysConContentRequest(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new InvSysConContentRequest(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof PipeItemsInvSysConnector) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(InvSysConContent.class).setIdentSet(((PipeItemsInvSysConnector) pipe.pipe).getExpectedItems()), player);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/InvSysConOpenSelectChannelPopupPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.pipe.InvSysConSelectChannelPopupGUIProvider;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class InvSysConOpenSelectChannelPopupPacket extends CoordinatesPacket {\n\n\tpublic InvSysConOpenSelectChannelPopupPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof PipeItemsInvSysConnector) {\n\t\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(player.getEntityWorld());\n\t\t\tNewGuiHandler.getGui(InvSysConSelectChannelPopupGUIProvider.class).setChannelInformations(manager.getAllowedChannels(player)).setTilePos(pipe).open(player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new InvSysConOpenSelectChannelPopupPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/InvSysConResistance.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class InvSysConResistance extends IntegerCoordinatesPacket {\n\n\tpublic InvSysConResistance(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new InvSysConResistance(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (MainProxy.isClient(player.world)) {\n\t\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\t\tif (pipe == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pipe.pipe instanceof PipeItemsInvSysConnector) {\n\t\t\t\tPipeItemsInvSysConnector invCon = (PipeItemsInvSysConnector) pipe.pipe;\n\t\t\t\tinvCon.resistance = getInteger();\n\t\t\t}\n\t\t} else {\n\t\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\t\tif (pipe == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pipe.pipe instanceof PipeItemsInvSysConnector) {\n\t\t\t\tPipeItemsInvSysConnector invCon = (PipeItemsInvSysConnector) pipe.pipe;\n\t\t\t\tinvCon.resistance = getInteger();\n\t\t\t\tinvCon.getRouter().update(true, invCon);\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/InvSysConSetChannelOnPipePacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringCoordinatesPacket;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class InvSysConSetChannelOnPipePacket extends StringCoordinatesPacket {\n\n\tpublic InvSysConSetChannelOnPipePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof PipeItemsInvSysConnector) {\n\t\t\tPipeItemsInvSysConnector conPipe = (PipeItemsInvSysConnector) pipe.pipe;\n\t\t\tconPipe.setChannelFromClient(UUID.fromString(getString()));\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new InvSysConSetChannelOnPipePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/ItemAmountSignUpdatePacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.Integer2CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.signs.IPipeSign;\nimport logisticspipes.pipes.signs.ItemAmountPipeSign;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ItemAmountSignUpdatePacket extends Integer2CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifierStack stack = null;\n\n\tpublic ItemAmountSignUpdatePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());\n\t\tif (pipe == null || !pipe.isInitialized()) {\n\t\t\treturn;\n\t\t}\n\n\t\tIPipeSign sign = ((CoreRoutedPipe) pipe.pipe).getPipeSign(EnumFacing.byIndex(getInteger()));\n\t\tif (sign == null) {\n\t\t\treturn;\n\t\t}\n\t\t((ItemAmountPipeSign) sign).amount = getInteger2();\n\t\t((ItemAmountPipeSign) sign).itemTypeInv.setInventorySlotContents(0, stack);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tif (input.readBoolean()) {\n\t\t\tstack = input.readItemIdentifierStack();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\tif (stack == null) {\n\t\t\toutput.writeBoolean(false);\n\t\t} else {\n\t\t\toutput.writeBoolean(true);\n\t\t\toutput.writeItemIdentifierStack(stack);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ItemAmountSignUpdatePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/ItemBufferSyncPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ListSyncPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ItemBufferSyncPacket\n\t\textends ListSyncPacket<Triplet<ItemIdentifierStack, Pair<Integer /* Time */, Integer /* BufferCounter */>, LPTravelingItemServer>> {\n\n\tpublic ItemBufferSyncPacket(int id, int x, int y, int z) {\n\t\tsuper(id, x, y, z);\n\t}\n\n\tpublic ItemBufferSyncPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeObject(LPDataOutput output,\n\t\t\tTriplet<ItemIdentifierStack, Pair<Integer /* Time */, Integer /* BufferCounter */>, LPTravelingItemServer> object) {\n\t\toutput.writeItemIdentifierStack(object.getValue1());\n\t}\n\n\t@Override\n\tpublic Triplet<ItemIdentifierStack, Pair<Integer /* Time */, Integer /* BufferCounter */>, LPTravelingItemServer> readObject(LPDataInput input) {\n\t\treturn new Triplet<>(input.readItemIdentifierStack(), null, null);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());\n\t\tif (pipe == null || pipe.pipe == null || pipe.pipe.transport == null) {\n\t\t\treturn;\n\t\t}\n\t\tpipe.pipe.transport._itemBuffer.clear();\n\t\tpipe.pipe.transport._itemBuffer.addAll(getList());\n\t}\n\n\t@Override\n\tpublic ItemBufferSyncPacket template() {\n\t\treturn new ItemBufferSyncPacket(getId(), getPosX(), getPosY(), getPosZ());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/MostLikelyRecipeComponentsResponse.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.gui.GuiLogisticsCraftingTable;\nimport logisticspipes.gui.orderer.GuiRequestTable;\nimport logisticspipes.gui.popup.GuiRecipeImport;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class MostLikelyRecipeComponentsResponse extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tList<Integer> response;\n\n\tpublic MostLikelyRecipeComponentsResponse(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tresponse = input.readArrayList(LPDataInput::readInt);\n\t}\n\n\t@Override\n\t@ClientSideOnlyMethodContent\n\tpublic void processPacket(EntityPlayer player) {\n\t\tGuiScreen firstGui = Minecraft.getMinecraft().currentScreen;\n\t\tLogisticsBaseGuiScreen gui;\n\t\tif (firstGui instanceof GuiLogisticsCraftingTable) {\n\t\t\tgui = (GuiLogisticsCraftingTable) firstGui;\n\t\t} else if (firstGui instanceof GuiRequestTable) {\n\t\t\tgui = (GuiRequestTable) firstGui;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t\tGuiRecipeImport importGui = null;\n\t\tSubGuiScreen sub = gui.getSubGui();\n\t\twhile (sub != null) {\n\t\t\tif (sub instanceof GuiRecipeImport) {\n\t\t\t\timportGui = (GuiRecipeImport) sub;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tsub = sub.getSubGui();\n\t\t}\n\t\tif (importGui == null) return;\n\t\timportGui.handleProposePacket(response);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeCollection(response, LPDataOutput::writeInt);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new MostLikelyRecipeComponentsResponse(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/ParticleFX.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.NonNull;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.ISpawnParticles.ParticleCount;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipefxhandlers.PipeFXRenderHandler;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ParticleFX extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\t@NonNull\n\tprivate Collection<ParticleCount> particles;\n\n\tpublic ParticleFX(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ParticleFX(getId());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tint nparticles = input.readInt();\n\t\tparticles = new ArrayList<>(nparticles);\n\t\tfor (int i = 0; i < nparticles; i++) {\n\t\t\tint particle = input.readByte();\n\t\t\tint amount = input.readInt();\n\t\t\tparticles.add(new ParticleCount(Particles.values()[particle], amount));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(particles.size());\n\t\tfor (ParticleCount pc : particles) {\n\t\t\toutput.writeByte(pc.getParticle().ordinal());\n\t\t\toutput.writeInt(pc.getAmount());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (!Minecraft.isFancyGraphicsEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tfor (ParticleCount pc : particles) {\n\t\t\tPipeFXRenderHandler.spawnGenericParticle(pc.getParticle(), getPosX(), getPosY(), getPosZ(), pc.getAmount());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeContentPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.lang.ref.WeakReference;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemClient;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeContentPacket extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifierStack item;\n\t@Getter\n\t@Setter\n\tprivate int travelId;\n\n\tpublic PipeContentPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\titem = input.readItemIdentifierStack();\n\t\ttravelId = input.readInt();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tWeakReference<LPTravelingItemClient> ref = LPTravelingItem.clientList.get(travelId);\n\t\tLPTravelingItemClient content = null;\n\t\tif (ref != null) {\n\t\t\tcontent = ref.get();\n\t\t}\n\t\tif (content == null) {\n\t\t\tcontent = new LPTravelingItemClient(travelId, item);\n\t\t\tLPTravelingItem.clientList.put(travelId, new WeakReference<>(content));\n\t\t\tsynchronized (LPTravelingItem.forceKeep) {\n\t\t\t\tLPTravelingItem.forceKeep.add(new Pair<>(10, content)); //Keep in memory for min 10 ticks\n\t\t\t}\n\t\t} else {\n\t\t\tcontent.setItem(item);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeItemIdentifierStack(item);\n\t\toutput.writeInt(travelId);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeContentPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeContentRequest.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.lang.ref.WeakReference;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.IntegerPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PipeContentRequest extends IntegerPacket {\n\n\tpublic PipeContentRequest(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tWeakReference<LPTravelingItemServer> ref = LPTravelingItem.serverList.get(getInteger());\n\t\tLPTravelingItemServer item = null;\n\t\tif (ref != null) {\n\t\t\titem = ref.get();\n\t\t}\n\t\tif (item != null) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PipeContentPacket.class).setItem(item.getItemIdentifierStack()).setTravelId(item.getId()), player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeContentRequest(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeDebugAskForTarget.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.text.TextComponentString;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@StaticResolve\npublic class PipeDebugAskForTarget extends ModernPacket {\n\n\t@Setter\n\t@Getter\n\tprivate boolean isServer;\n\n\tpublic PipeDebugAskForTarget(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tisServer = input.readBoolean();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tRayTraceResult box = FMLClientHandler.instance().getClient().objectMouseOver;\n\t\tif (box != null && box.typeOfHit == RayTraceResult.Type.BLOCK) {\n\t\t\tif (!isServer) {\n\t\t\t\tTileEntity tile = new DoubleCoordinates(box.getBlockPos()).getTileEntity(player.getEntityWorld());\n\t\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\t\t((LogisticsTileGenericPipe) tile).pipe.debug.debugThisPipe = !((LogisticsTileGenericPipe) tile).pipe.debug.debugThisPipe;\n\t\t\t\t\tif (((LogisticsTileGenericPipe) tile).pipe.debug.debugThisPipe) {\n\t\t\t\t\t\tplayer.sendMessage(new TextComponentString(\"Debug enabled On Client\"));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tplayer.sendMessage(new TextComponentString(\"Debug disabled On Client\"));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PipeDebugResponse.class).setBlockPos(box.getBlockPos()));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeBoolean(isServer);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeDebugAskForTarget(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeDebugResponse.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class PipeDebugResponse extends CoordinatesPacket {\n\n\tpublic PipeDebugResponse(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());\n\t\tif (pipe != null && pipe.isInitialized()) {\n\t\t\tpipe.pipe.debug.debugThisPipe = !pipe.pipe.debug.debugThisPipe;\n\t\t\tif (pipe.pipe.debug.debugThisPipe) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(\"Debug enabled on Server\"));\n\t\t\t} else {\n\t\t\t\tplayer.sendMessage(new TextComponentString(\"Debug disabled on Server\"));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeDebugResponse(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeFluidUpdate.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.BitSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fluids.FluidRegistry;\nimport net.minecraftforge.fluids.FluidStack;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeFluidUpdate extends CoordinatesPacket {\n\n\t@Getter(value = AccessLevel.PRIVATE)\n\t@Setter\n\tprivate FluidStack[] renderCache = new FluidStack[EnumFacing.VALUES.length];\n\tprivate BitSet bits = new BitSet();\n\n\tpublic PipeFluidUpdate(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tbits = input.readBitSet();\n\t\tfor (int i = 0; i < renderCache.length; i++) {\n\t\t\tif (bits.get(i)) {\n\t\t\t\trenderCache[i] = new FluidStack(FluidRegistry.getFluid(input.readUTF()), input.readInt(), input.readNBTTagCompound());\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\tfor (int i = 0; i < renderCache.length; i++) {\n\t\t\tbits.set(i, renderCache[i] != null);\n\t\t}\n\t\toutput.writeBitSet(bits);\n\t\tfor (FluidStack aRenderCache : renderCache) {\n\t\t\tif (aRenderCache != null) {\n\t\t\t\toutput.writeUTF(aRenderCache.getFluid().getName());\n\t\t\t\toutput.writeInt(aRenderCache.amount);\n\t\t\t\toutput.writeNBTTagCompound(aRenderCache.tag);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null || pipe.pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!(pipe.pipe.transport instanceof PipeFluidTransportLogistics)) {\n\t\t\treturn;\n\t\t}\n\t\t((PipeFluidTransportLogistics) pipe.pipe.transport).renderCache = renderCache;\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeFluidUpdate(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeManagerContentPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.routing.order.ClientSideOrderInfo;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.routing.order.LogisticsOrderManager;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeManagerContentPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate LogisticsOrderManager<? extends LogisticsOrder, ?> manager;\n\n\tprivate List<IOrderInfoProvider> clientOrder;\n\n\tpublic PipeManagerContentPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tCoreRoutedPipe cPipe = (CoreRoutedPipe) pipe.pipe;\n\t\tcPipe.getClientSideOrderManager().clear();\n\t\tcPipe.getClientSideOrderManager().addAll(clientOrder);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeManagerContentPacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\n\t\t// manual collection write, because generics are wrong here\n\t\toutput.writeInt(manager.size());\n\t\tfor (LogisticsOrder order : manager) {\n\t\t\toutput.writeSerializable(order);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\n\t\tclientOrder = input.readLinkedList(ClientSideOrderInfo::new);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeManagerWatchingPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeManagerWatchingPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate boolean start;\n\n\tpublic PipeManagerWatchingPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());\n\t\tif (pipe == null || !(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tCoreRoutedPipe cPipe = (CoreRoutedPipe) pipe.pipe;\n\t\tif (start) {\n\t\t\tcPipe.getOrderManager().startWatching(player);\n\t\t} else {\n\t\t\tcPipe.getOrderManager().stopWatching(player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeManagerWatchingPacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeBoolean(start);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tstart = input.readBoolean();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipePositionPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipePositionPacket extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int travelId;\n\t@Getter\n\t@Setter\n\tprivate float speed;\n\t@Getter\n\t@Setter\n\tprivate float position;\n\t@Getter\n\t@Setter\n\tprivate EnumFacing input;\n\t@Getter\n\t@Setter\n\tprivate EnumFacing output;\n\t@Getter\n\t@Setter\n\tprivate float yaw;\n\n\tpublic PipePositionPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.TRANSPORT);\n\t\tif (tile == null || tile.pipe == null || tile.pipe.transport == null) {\n\t\t\treturn;\n\t\t}\n\t\ttile.pipe.transport.handleItemPositionPacket(travelId, input, output, speed, position, yaw);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(travelId);\n\t\toutput.writeFloat(speed);\n\t\toutput.writeFloat(position);\n\t\toutput.writeFacing(input);\n\t\toutput.writeFacing(this.output);\n\t\toutput.writeFloat(yaw);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttravelId = input.readInt();\n\t\tspeed = input.readFloat();\n\t\tposition = input.readFloat();\n\t\tthis.input = input.readFacing();\n\t\toutput = input.readFacing();\n\t\tyaw = input.readFloat();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipePositionPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipePropertiesUpdate.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.property.PropertyHolder;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipePropertiesUpdate extends CoordinatesPacket {\n\n\t@Nonnull\n\tpublic NBTTagCompound tag = new NBTTagCompound();\n\n\tpublic PipePropertiesUpdate(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeNBTTagCompound(tag);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttag = Objects.requireNonNull(input.readNBTTagCompound(), \"read null NBT in PipePropertiesUpdate\");\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipePropertiesUpdate(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (!(tile.pipe instanceof PropertyHolder)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// sync updated properties\n\t\ttile.pipe.readFromNBT(tag);\n\n\t\tMainProxy.runOnServer(player.world, () -> () -> {\n\t\t\t// resync client; always\n\t\t\tMainProxy.sendPacketToPlayer(fromPropertyHolder((PropertyHolder) tile.pipe).setPacketPos(this), player);\n\t\t});\n\t}\n\n\t@Nonnull\n\tpublic static PipePropertiesUpdate fromPropertyHolder(PropertyHolder holder) {\n\t\tfinal PipePropertiesUpdate packet = PacketHandler.getPacket(PipePropertiesUpdate.class);\n\t\tPropertyHolder.writeToNBT(packet.tag, holder);\n\t\treturn packet;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeSignTypes.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeSignTypes extends CoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate List<Integer> types;\n\n\tpublic PipeSignTypes(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (pipe == null || !pipe.isInitialized()) {\n\t\t\treturn;\n\t\t}\n\t\t((CoreRoutedPipe) pipe.pipe).handleSignPacket(types);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeCollection(types, LPDataOutput::writeInt);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttypes = input.readArrayList(LPDataInput::readInt);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeSignTypes(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/PipeTileStatePacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.IClientState;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataIOWrapper;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class PipeTileStatePacket extends CoordinatesPacket {\n\n\t@Setter\n\tprivate IClientState renderState;\n\n\t@Setter\n\tprivate IClientState coreState;\n\n\t@Setter\n\tprivate IClientState pipe;\n\n\t@Getter\n\tprivate byte[] bytesRenderState;\n\n\t@Getter\n\tprivate byte[] bytesCoreState;\n\n\t@Getter\n\tprivate byte[] bytesPipe;\n\n\t@Getter\n\t@Setter\n\tprivate int statePacketId;\n\n\tpublic PipeTileStatePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.NONE);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.statePacketId < statePacketId) {\n\t\t\tLPDataIOWrapper.provideData(bytesRenderState, pipe.renderState::readData);\n\t\t\tLPDataIOWrapper.provideData(bytesCoreState, pipe.coreState::readData);\n\t\t\tpipe.afterStateUpdated();\n\t\t\tif (pipe.pipe != null && bytesPipe.length != 0) {\n\t\t\t\tLPDataIOWrapper.provideData(bytesPipe, pipe.pipe::readData);\n\t\t\t}\n\t\t\tpipe.statePacketId = statePacketId;\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new PipeTileStatePacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\n\t\tIClientState[] clientStates = new IClientState[] { renderState, coreState, pipe };\n\t\tbyte[][] clientStateBuffers = new byte[][] { bytesRenderState, bytesCoreState, bytesPipe };\n\t\tfor (int i = 0; i < clientStates.length; i++) {\n\t\t\tclientStateBuffers[i] = LPDataIOWrapper.collectData(clientStates[i]::writeData);\n\t\t\toutput.writeByteArray(clientStateBuffers[i]);\n\t\t}\n\n\t\toutput.writeInt(statePacketId);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\n\t\tbytesRenderState = input.readByteArray();\n\t\tbytesCoreState = input.readByteArray();\n\t\tbytesPipe = input.readByteArray();\n\n\t\tstatePacketId = input.readInt();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/RequestChassisOrientationPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestChassisOrientationPacket extends CoordinatesPacket {\n\n\tpublic RequestChassisOrientationPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tif (pipe.pipe instanceof PipeLogisticsChassis) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ChassisOrientationPacket.class).setDir(((PipeLogisticsChassis) pipe.pipe).getPointedOrientation()).setPosX(getPosX()).setPosY(getPosY()).setPosZ(getPosZ()), player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestChassisOrientationPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/RequestPipeDimension.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.gui.orderer.GuiOrderer;\nimport logisticspipes.network.abstractpackets.IntegerPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestPipeDimension extends IntegerPacket {\n\n\tpublic RequestPipeDimension(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestPipeDimension(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiOrderer) {\n\t\t\t((GuiOrderer) FMLClientHandler.instance().getClient().currentScreen).dimension = getInteger();\n\t\t\t((GuiOrderer) FMLClientHandler.instance().getClient().currentScreen).refreshItems();\n\t\t} else {\n\t\t\tGuiOrderer.dimensioncache = getInteger();\n\t\t\tGuiOrderer.cachetime = System.currentTimeMillis();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/RequestRoutingLasersPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.ArrayList;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.config.Configs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.LaserData;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.pathfinder.PathFinder;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestRoutingLasersPacket extends CoordinatesPacket {\n\n\tprivate abstract static class Log {\n\n\t\tabstract void log(String log);\n\t}\n\n\t@Data\n\t@AllArgsConstructor\n\tprivate static class DataEntry {\n\n\t\tfinal LogisticsTileGenericPipe pipe;\n\t\tfinal EnumFacing dir;\n\t\tfinal ArrayList<ExitRoute> connectedRouters;\n\t\tfinal List<LaserData> lasers;\n\t\tfinal EnumSet<PipeRoutingConnectionType> connectionType;\n\t\tfinal Log log;\n\t}\n\n\tprivate boolean firstPipe = false;\n\n\tpublic RequestRoutingLasersPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe tile = this.getPipe(player.world);\n\t\tif (tile == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (tile.pipe instanceof CoreRoutedPipe) {\n\t\t\tIRouter router = ((CoreRoutedPipe) tile.pipe).getRouter();\n\n\t\t\t//this is here to allow players to manually trigger a network-wide LSA update\n\t\t\trouter.forceLsaUpdate();\n\n\t\t\tList<List<ExitRoute>> exits = router.getRouteTable();\n\t\t\tHashMap<EnumFacing, ArrayList<ExitRoute>> routers = new HashMap<>();\n\t\t\tfor (List<ExitRoute> exit : exits) {\n\t\t\t\tif (exit == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (ExitRoute e : exit) {\n\t\t\t\t\tif (!routers.containsKey(e.exitOrientation)) {\n\t\t\t\t\t\trouters.put(e.exitOrientation, new ArrayList<>());\n\t\t\t\t\t}\n\t\t\t\t\tif (!routers.get(e.exitOrientation).contains(e)) {\n\t\t\t\t\t\trouters.get(e.exitOrientation).add(e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tArrayList<LaserData> lasers = new ArrayList<>();\n\t\t\tfirstPipe = true;\n\t\t\tfor (final EnumFacing dir : routers.keySet()) {\n\t\t\t\tif (dir == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\thandleRouteInDirection(tile, dir, routers.get(dir), lasers, EnumSet.allOf(PipeRoutingConnectionType.class), new Log() {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tvoid log(String log) {\n\t\t\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\t\t\tSystem.out.println(dir.name() + \": \" + log);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tlasers = compressLasers(lasers);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingLaserPacket.class).setLasers(lasers), player);\n\t\t}\n\t}\n\n\tprivate void handleRouteInDirection(final LogisticsTileGenericPipe pipeIn, EnumFacing dirIn, ArrayList<ExitRoute> connectedRoutersIn, final List<LaserData> lasersIn, EnumSet<PipeRoutingConnectionType> connectionTypeIn, final Log logIn) {\n\t\tList<DataEntry> worklist = new LinkedList<>();\n\t\tworklist.add(new DataEntry(pipeIn, dirIn, connectedRoutersIn, lasersIn, connectionTypeIn, logIn));\n\t\twhile (!worklist.isEmpty()) {\n\t\t\tfinal DataEntry entry = worklist.remove(0);\n\t\t\tfinal LogisticsTileGenericPipe pipe = entry.pipe;\n\t\t\tfinal EnumFacing dir = entry.dir;\n\t\t\tfinal ArrayList<ExitRoute> connectedRouters = entry.connectedRouters;\n\t\t\tfinal List<LaserData> lasers = entry.lasers;\n\t\t\tfinal EnumSet<PipeRoutingConnectionType> connectionType = entry.connectionType;\n\t\t\tfinal Log log = entry.log;\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tlog.log(\"Size: \" + connectedRouters.size());\n\t\t\t}\n\t\t\tlasers.add(new LaserData(pipe.getX(), pipe.getY(), pipe.getZ(), dir, connectionType).setStartPipe(firstPipe));\n\t\t\tfirstPipe = false;\n\t\t\tHashMap<CoreRoutedPipe, ExitRoute> map = PathFinder.paintAndgetConnectedRoutingPipes(pipe, dir, Configs.LOGISTICS_DETECTION_COUNT, Configs.LOGISTICS_DETECTION_LENGTH, (world, laser) -> {\n\t\t\t\tif (pipe.getWorld() == world) {\n\t\t\t\t\tlasers.add(laser);\n\t\t\t\t}\n\t\t\t}, connectionType);\n\t\t\tfor (CoreRoutedPipe connectedPipe : map.keySet()) {\n\t\t\t\tIRouter newRouter = connectedPipe.getRouter();\n\t\t\t\tIterator<ExitRoute> iRoutes = connectedRouters.iterator();\n\t\t\t\twhile (iRoutes.hasNext()) {\n\t\t\t\t\tExitRoute route = iRoutes.next();\n\t\t\t\t\tif (route.destination == newRouter) {\n\t\t\t\t\t\tiRoutes.remove();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tMap<CoreRoutedPipe, ArrayList<ExitRoute>> sort = new HashMap<>();\n\t\t\tfor (ExitRoute routeTo : connectedRouters) {\n\t\t\t\tExitRoute result = null;\n\t\t\t\tCoreRoutedPipe resultPipe = null;\n\t\t\t\tfor (Entry<CoreRoutedPipe, ExitRoute> routeCanidate : map.entrySet()) {\n\t\t\t\t\tList<ExitRoute> distances = routeCanidate.getValue().destination.getDistanceTo(routeTo.destination);\n\t\t\t\t\tfor (ExitRoute distance : distances) {\n\t\t\t\t\t\tif (distance.isSameWay(routeTo)) {\n\t\t\t\t\t\t\tif (result == null || result.distanceToDestination > distance.distanceToDestination) {\n\t\t\t\t\t\t\t\tresult = distance;\n\t\t\t\t\t\t\t\tresultPipe = routeCanidate.getKey();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!sort.containsKey(resultPipe)) {\n\t\t\t\t\tsort.put(resultPipe, new ArrayList<>());\n\t\t\t\t}\n\t\t\t\tif (!sort.get(resultPipe).contains(result)) {\n\t\t\t\t\tsort.get(resultPipe).add(result);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (Entry<CoreRoutedPipe, ArrayList<ExitRoute>> connectedPipe : sort.entrySet()) {\n\t\t\t\tHashMap<EnumFacing, ArrayList<ExitRoute>> routers = new HashMap<>();\n\t\t\t\tfor (ExitRoute exit : connectedPipe.getValue()) {\n\t\t\t\t\tif (!routers.containsKey(exit.exitOrientation)) {\n\t\t\t\t\t\trouters.put(exit.exitOrientation, new ArrayList<>());\n\t\t\t\t\t}\n\t\t\t\t\tif (!routers.get(exit.exitOrientation).contains(exit)) {\n\t\t\t\t\t\trouters.get(exit.exitOrientation).add(exit);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (final EnumFacing exitDir : routers.keySet()) {\n\t\t\t\t\tif (exitDir == null) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tworklist.add(new DataEntry(connectedPipe.getKey().container, exitDir, routers.get(exitDir), lasers, map.get(connectedPipe.getKey()).connectionDetails, new Log() {\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tvoid log(String logString) {\n\t\t\t\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\t\t\t\tlog.log(exitDir.name() + \": \" + logString);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate ArrayList<LaserData> compressLasers(ArrayList<LaserData> lasers) {\n\t\tArrayList<LaserData> options = new ArrayList<>(lasers);\n\t\tIterator<LaserData> iLasers = lasers.iterator();\n\t\twhile (iLasers.hasNext()) {\n\t\t\tboolean compressed = false;\n\t\t\tLaserData data = iLasers.next();\n\t\t\tBlockPos next = new BlockPos(data.getPosX(), data.getPosY(), data.getPosZ()).offset(data.getDir(), data.getLength());\n\t\t\tboolean found;\n\t\t\tdo {\n\t\t\t\tfound = false;\n\t\t\t\tIterator<LaserData> iOptions = options.iterator();\n\t\t\t\twhile (iOptions.hasNext()) {\n\t\t\t\t\tLaserData d = iOptions.next();\n\t\t\t\t\tif (d.getPosX() == next.getX() && d.getPosY() == next.getY() && d.getPosZ() == next.getZ()) {\n\t\t\t\t\t\tif (data.getDir().equals(d.getDir()) && data.getConnectionType().equals(d.getConnectionType())) {\n\t\t\t\t\t\t\tdata.setLength(data.getLength() + d.getLength());\n\t\t\t\t\t\t\tnext = next.offset(data.getDir(), data.getLength());\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t\tiOptions.remove();\n\t\t\t\t\t\t\tlasers.remove(d);\n\t\t\t\t\t\t\tcompressed = true;\n\t\t\t\t\t\t} else if (data.getDir().equals(d.getDir())) {\n\t\t\t\t\t\t\tdata.setFinalPipe(false);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} while (found);\n\t\t\tif (compressed) {\n\t\t\t\tiLasers = lasers.iterator();\n\t\t\t}\n\t\t}\n\t\treturn lasers;\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestRoutingLasersPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/RequestSignPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RequestSignPacket extends CoordinatesPacket {\n\n\tpublic RequestSignPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld());\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\t((CoreRoutedPipe) pipe.pipe).sendSignData(player, false);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RequestSignPacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/RoutingLaserPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.routing.LaserData;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingLaserPacket extends ModernPacket {\n\n\t@Setter\n\t@Getter\n\tList<LaserData> lasers = new ArrayList<>();\n\n\tpublic RoutingLaserPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\twhile (input.readBoolean()) {\n\t\t\tlasers.add(new LaserData(input));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsHUDRenderer.instance().setLasers(getLasers());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tfor (LaserData laser : lasers) {\n\t\t\toutput.writeBoolean(true);\n\t\t\tlaser.writeData(output);\n\t\t}\n\t\toutput.writeBoolean(false);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingLaserPacket(getId());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/SendQueueContent.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.interfaces.ISendQueueContentRecieiver;\nimport logisticspipes.network.abstractpackets.InventoryModuleCoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class SendQueueContent extends InventoryModuleCoordinatesPacket {\n\n\tpublic SendQueueContent(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SendQueueContent(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.pipe instanceof ISendQueueContentRecieiver) {\n\t\t\tISendQueueContentRecieiver receiver = (ISendQueueContentRecieiver) pipe.pipe;\n\t\t\treceiver.handleSendQueueItemIdentifierList(getIdentList());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/SlotFinderActivatePacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.renderer.GuiOverlay;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SlotFinderActivatePacket extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int targetPosX;\n\t@Getter\n\t@Setter\n\tprivate int targetPosY;\n\t@Getter\n\t@Setter\n\tprivate int targetPosZ;\n\t@Getter\n\t@Setter\n\tprivate int slot;\n\n\tpublic SlotFinderActivatePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SlotFinderActivatePacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(targetPosX);\n\t\toutput.writeInt(targetPosY);\n\t\toutput.writeInt(targetPosZ);\n\t\toutput.writeInt(slot);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\ttargetPosX = input.readInt();\n\t\ttargetPosY = input.readInt();\n\t\ttargetPosZ = input.readInt();\n\t\tslot = input.readInt();\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tGuiOverlay overlay = GuiOverlay.getInstance();\n\n\t\toverlay.setPipePosX(getPosX());\n\t\toverlay.setPipePosY(getPosY());\n\t\toverlay.setPipePosZ(getPosZ());\n\t\toverlay.setTargetPosX(getTargetPosX());\n\t\toverlay.setTargetPosY(getTargetPosY());\n\t\toverlay.setTargetPosZ(getTargetPosZ());\n\t\toverlay.setSlot(getSlot());\n\t\toverlay.setOverlaySlotActive(true);\n\t\toverlay.setPositionInt(getPositionInt());\n\t\toverlay.setPositionType(getType());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/SlotFinderNumberPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport net.minecraftforge.items.CapabilityItemHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SlotFinderNumberPacket extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int pipePosX;\n\t@Getter\n\t@Setter\n\tprivate int pipePosY;\n\t@Getter\n\t@Setter\n\tprivate int pipePosZ;\n\t@Setter\n\tprivate int inventorySlot;\n\t@Getter\n\t@Setter\n\tprivate int slot;\n\n\tpublic SlotFinderNumberPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SlotFinderNumberPacket(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tTileEntity inv = this.getTileAs(player.world, tile -> tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null));\n\t\tIInventoryUtil util = SimpleServiceLocator.inventoryUtilFactory.getInventoryUtil(inv, null);\n\t\tif (util == null) return;\n\t\tSlot result = null;\n\t\tif (player.openContainer.inventorySlots.get(inventorySlot).slotNumber == inventorySlot) {\n\t\t\tresult = player.openContainer.inventorySlots.get(inventorySlot);\n\t\t}\n\t\tif (result == null) {\n\t\t\tfor (Slot slotObject : player.openContainer.inventorySlots) {\n\t\t\t\tif (slotObject.slotNumber == inventorySlot) {\n\t\t\t\t\tresult = slotObject;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (result == null) {\n\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.chat.slotnotfound\"));\n\t\t\treturn;\n\t\t}\n\t\tint resultIndex = -1;\n\t\tItemStack content = result.getStack();\n\t\tif (!content.isEmpty()) {\n\t\t\tfor (int i = 0; i < util.getSizeInventory(); i++) {\n\t\t\t\tif (content == util.getStackInSlot(i)) {\n\t\t\t\t\tresultIndex = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tItemStack dummyStack = new ItemStack(Blocks.DIRT, 1, 0);\n\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\tnbt.setBoolean(\"LPStackFinderBoolean\", true); //Make it unique\n\t\t\tdummyStack.setTagCompound(nbt); // dummyStack: yay, I am unique\n\t\t\tresult.putStack(dummyStack);\n\t\t\tfor (int i = 0; i < util.getSizeInventory(); i++) {\n\t\t\t\tif (dummyStack == util.getStackInSlot(i)) {\n\t\t\t\t\tresultIndex = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (resultIndex == -1) {\n\t\t\t\tfor (int i = 0; i < util.getSizeInventory(); i++) {\n\t\t\t\t\tItemStack stack = util.getStackInSlot(i);\n\t\t\t\t\tif (stack.isEmpty()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (ItemIdentifier.get(stack).equals(ItemIdentifier.get(dummyStack)) && stack.getCount() == dummyStack.getCount()) {\n\t\t\t\t\t\tresultIndex = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tresult.putStack(ItemStack.EMPTY);\n\t\t}\n\n\t\tif (resultIndex == -1) {\n\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.chat.slotnotfound\"));\n\t\t} else {\n\t\t\t//Copy pipe to coordinates to use the getPipe method\n\t\t\tsetPosX(getPipePosX());\n\t\t\tsetPosY(getPipePosY());\n\t\t\tsetPosZ(getPipePosZ());\n\t\t\tModuleActiveSupplier module = this.getLogisticsModule(player, ModuleActiveSupplier.class);\n\t\t\tif (module != null) {\n\t\t\t\tmodule.slotAssignmentPattern.set(slot, resultIndex);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(inventorySlot);\n\t\toutput.writeInt(slot);\n\t\toutput.writeInt(pipePosX);\n\t\toutput.writeInt(pipePosY);\n\t\toutput.writeInt(pipePosZ);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tinventorySlot = input.readInt();\n\t\tslot = input.readInt();\n\t\tpipePosX = input.readInt();\n\t\tpipePosY = input.readInt();\n\t\tpipePosZ = input.readInt();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/SlotFinderOpenGuiPacket.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemBlock;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.BlockPos;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ISpecialInsertion;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.ModuleCoordinatesPacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SlotFinderOpenGuiPacket extends ModuleCoordinatesPacket {\n\n\t@Getter\n\t@Setter\n\tprivate int slot;\n\n\tpublic SlotFinderOpenGuiPacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\t//hack to avoid wrenching blocks\n\t\tint savedEquipped = player.inventory.currentItem;\n\t\tboolean foundSlot = false;\n\t\t//try to find a empty slot\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tif (player.inventory.getStackInSlot(i).isEmpty()) {\n\t\t\t\tfoundSlot = true;\n\t\t\t\tplayer.inventory.currentItem = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t//okay, anything that's a block?\n\t\tif (!foundSlot) {\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tItemStack is = player.inventory.getStackInSlot(i);\n\t\t\t\tif (!is.isEmpty() && is.getItem() instanceof ItemBlock) {\n\t\t\t\t\tfoundSlot = true;\n\t\t\t\t\tplayer.inventory.currentItem = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t//give up and select whatever is right of the current slot\n\t\tif (!foundSlot) {\n\t\t\tplayer.inventory.currentItem = (player.inventory.currentItem + 1) % 9;\n\t\t}\n\n\t\tboolean openedGui = false;\n\t\tfinal LogisticsTileGenericPipe genericPipe = getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tif (genericPipe.isRoutingPipe()) {\n\t\t\topenedGui = genericPipe.getRoutingPipe().getAvailableAdjacent().inventories().stream()\n\t\t\t\t\t.filter(neighbor -> LPNeighborTileEntityKt.getInventoryUtil(neighbor) instanceof ISpecialInsertion)\n\t\t\t\t\t.anyMatch(neighbor -> {\n\t\t\t\t\t\tfor (ICraftingRecipeProvider provider : SimpleServiceLocator.craftingRecipeProviders) {\n\t\t\t\t\t\t\tif (provider.canOpenGui(neighbor.getTileEntity())) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tBlock block = neighbor.getTileEntity().getBlockType();\n\t\t\t\t\t\tfinal BlockPos blockPos = neighbor.getTileEntity().getPos();\n\t\t\t\t\t\tfinal IBlockState blockState = player.world.getBlockState(blockPos);\n\t\t\t\t\t\tif (!block.isAir(blockState, player.world, blockPos)) {\n\t\t\t\t\t\t\tint xCoord = blockPos.getX();\n\t\t\t\t\t\t\tint yCoord = blockPos.getY();\n\t\t\t\t\t\t\tint zCoord = blockPos.getZ();\n\n\t\t\t\t\t\t\tif (SimpleServiceLocator.enderStorageProxy.isEnderChestBlock(block)) {\n\t\t\t\t\t\t\t\tSimpleServiceLocator.enderStorageProxy.openEnderChest(player.world, xCoord, yCoord, zCoord, player);\n\t\t\t\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SlotFinderActivatePacket.class)\n\t\t\t\t\t\t\t\t\t\t.setTargetPosX(xCoord)\n\t\t\t\t\t\t\t\t\t\t.setTargetPosY(yCoord)\n\t\t\t\t\t\t\t\t\t\t.setTargetPosZ(zCoord)\n\t\t\t\t\t\t\t\t\t\t.setSlot(getSlot())\n\t\t\t\t\t\t\t\t\t\t.setPacketPos(this), player);\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (block.onBlockActivated(player.world, blockPos, blockState, player, EnumHand.MAIN_HAND, EnumFacing.UP, 0, 0, 0)) {\n\t\t\t\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SlotFinderActivatePacket.class)\n\t\t\t\t\t\t\t\t\t\t.setTargetPosX(xCoord)\n\t\t\t\t\t\t\t\t\t\t.setTargetPosY(yCoord)\n\t\t\t\t\t\t\t\t\t\t.setTargetPosZ(zCoord)\n\t\t\t\t\t\t\t\t\t\t.setSlot(getSlot())\n\t\t\t\t\t\t\t\t\t\t.setPacketPos(this), player);\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t});\n\t\t}\n\n\t\tif (!openedGui) {\n\t\t\tLogisticsPipes.log.warn(\"Ignored SlotFinderOpenGuiPacket from \" + player.toString() + \", because of failing preconditions\");\n\t\t}\n\n\t\tplayer.inventory.currentItem = savedEquipped;\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SlotFinderOpenGuiPacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(slot);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tslot = input.readInt();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/pipe/StatUpdate.java",
    "content": "package logisticspipes.network.packets.pipe;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class StatUpdate extends CoordinatesPacket {\n\n\t@Setter\n\tprivate CoreRoutedPipe pipe;\n\tprivate int stat_session_sent;\n\tprivate int stat_session_recieved;\n\tprivate int stat_session_relayed;\n\tprivate long stat_lifetime_sent;\n\tprivate long stat_lifetime_recieved;\n\tprivate long stat_lifetime_relayed;\n\tprivate int server_routing_table_size;\n\n\tpublic StatUpdate(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new StatUpdate(getId());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = this.getPipe(player.world);\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn;\n\t\t}\n\t\tCoreRoutedPipe cPipe = (CoreRoutedPipe) pipe.pipe;\n\t\tcPipe.stat_session_sent = stat_session_sent;\n\t\tcPipe.stat_session_recieved = stat_session_recieved;\n\t\tcPipe.stat_session_relayed = stat_session_relayed;\n\t\tcPipe.stat_lifetime_sent = stat_lifetime_sent;\n\t\tcPipe.stat_lifetime_recieved = stat_lifetime_recieved;\n\t\tcPipe.stat_lifetime_relayed = stat_lifetime_relayed;\n\t\tcPipe.server_routing_table_size = server_routing_table_size;\n\t}\n\n\tprivate void initData() {\n\t\tsetPosX(pipe.getX());\n\t\tsetPosY(pipe.getY());\n\t\tsetPosZ(pipe.getZ());\n\t\tstat_session_sent = pipe.stat_session_sent;\n\t\tstat_session_recieved = pipe.stat_session_recieved;\n\t\tstat_session_relayed = pipe.stat_session_relayed;\n\t\tstat_lifetime_sent = pipe.stat_lifetime_sent;\n\t\tstat_lifetime_recieved = pipe.stat_lifetime_recieved;\n\t\tstat_lifetime_relayed = pipe.stat_lifetime_relayed;\n\t\tint numentries = 0;\n\t\tfor (List<ExitRoute> route : pipe.getRouter().getRouteTable()) {\n\t\t\tif (route != null && !route.isEmpty()) {\n\t\t\t\t++numentries;\n\t\t\t}\n\t\t}\n\t\tserver_routing_table_size = numentries;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tinitData();\n\t\tsuper.writeData(output);\n\t\toutput.writeInt(stat_session_sent);\n\t\toutput.writeInt(stat_session_recieved);\n\t\toutput.writeInt(stat_session_relayed);\n\t\toutput.writeLong(stat_lifetime_sent);\n\t\toutput.writeLong(stat_lifetime_recieved);\n\t\toutput.writeLong(stat_lifetime_relayed);\n\t\toutput.writeInt(server_routing_table_size);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tstat_session_sent = input.readInt();\n\t\tstat_session_recieved = input.readInt();\n\t\tstat_session_relayed = input.readInt();\n\t\tstat_lifetime_sent = input.readLong();\n\t\tstat_lifetime_recieved = input.readLong();\n\t\tstat_lifetime_relayed = input.readLong();\n\t\tserver_routing_table_size = input.readInt();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateAskForTarget.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.RayTraceResult;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport logisticspipes.asm.ClientSideOnlyMethodContent;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateTargetResponse.TargetMode;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateAskForTarget extends ModernPacket {\n\n\tpublic RoutingUpdateAskForTarget(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\t@ClientSideOnlyMethodContent\n\tpublic void processPacket(EntityPlayer player) {\n\t\tRayTraceResult box = FMLClientHandler.instance().getClient().objectMouseOver;\n\t\tif (box == null) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateTargetResponse.class).setMode(TargetMode.None));\n\t\t} else if (box.typeOfHit == RayTraceResult.Type.BLOCK) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateTargetResponse.class).setMode(TargetMode.Block)\n\t\t\t\t\t.setAdditions(new int[] { box.getBlockPos().getX(), box.getBlockPos().getY(), box.getBlockPos().getZ() }));\n\t\t} else if (box.typeOfHit == RayTraceResult.Type.ENTITY) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateTargetResponse.class).setMode(TargetMode.Entity)\n\t\t\t\t\t.setAdditions(new int[] { box.entityHit.getEntityId() }));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateAskForTarget(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateCanidatePipe.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateCanidatePipe extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ExitRoute exitRoute;\n\n\tpublic RoutingUpdateCanidatePipe(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\t// do not handle packet if the ExitRoute could not be read\n\t\tif (exitRoute != null) {\n\t\t\tClientViewController.instance().handlePacket(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateCanidatePipe(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\ttry {\n\t\t\texitRoute = new ExitRoute(input);\n\t\t} catch (RuntimeException e) {\n\t\t\tLogisticsPipes.log.error(\"Could not read ExitRoute from RoutingUpdateCanidatePipe\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\texitRoute.write(output);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateClearClient.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateClearClient extends ModernPacket {\n\n\tpublic RoutingUpdateClearClient(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tClientViewController.instance().clear();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateClearClient(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateDebugCanidateList.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateDebugCanidateList extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate List<ExitRoute> exitRoutes;\n\n\tpublic RoutingUpdateDebugCanidateList(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tfinal LinkedList<ExitRoute> readExitRoutes = input.readLinkedList(objInput -> {\n\t\t\ttry {\n\t\t\t\treturn new ExitRoute(objInput);\n\t\t\t} catch (RuntimeException e) {\n\t\t\t\tLogisticsPipes.log.error(\"Could not read ExitRoute in RoutingUpdateDebugCanidateList\", e);\n\t\t\t}\n\t\t\treturn null;\n\t\t});\n\t\tif (readExitRoutes == null) {\n\t\t\tLogisticsPipes.log.error(\"Read a non-existent ExitRoute collection in RoutingUpdateDebugCanidateList\");\n\t\t\texitRoutes = Collections.emptyList();\n\t\t\treturn;\n\t\t}\n\t\texitRoutes = readExitRoutes.stream().filter(Objects::nonNull).collect(Collectors.toList());\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tClientViewController.instance().updateList(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeCollection(exitRoutes);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateDebugCanidateList(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateDebugClosedSet.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport java.util.EnumSet;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@StaticResolve\npublic class RoutingUpdateDebugClosedSet extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate DoubleCoordinates pos;\n\n\t@Getter\n\t@Setter\n\tprivate EnumSet<PipeRoutingConnectionType> set;\n\n\tpublic RoutingUpdateDebugClosedSet(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tset = input.readEnumSet(PipeRoutingConnectionType.class);\n\t\tpos = new DoubleCoordinates(input);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tClientViewController.instance().handlePacket(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeEnumSet(set, PipeRoutingConnectionType.class);\n\t\toutput.writeSerializable(pos);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateDebugClosedSet(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateDebugFilters.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@StaticResolve\npublic class RoutingUpdateDebugFilters extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate DoubleCoordinates pos;\n\n\t@Setter\n\tprivate EnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters;\n\n\t@Getter\n\tprivate EnumMap<PipeRoutingConnectionType, List<List<DoubleCoordinates>>> filterPositions;\n\n\tpublic RoutingUpdateDebugFilters(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tpos = new DoubleCoordinates(input);\n\t\tfilterPositions = new EnumMap<>(PipeRoutingConnectionType.class);\n\t\tshort id;\n\t\twhile ((id = input.readShort()) != -1) {\n\t\t\tPipeRoutingConnectionType type = PipeRoutingConnectionType.values[id];\n\t\t\tList<List<DoubleCoordinates>> typeFilters = new ArrayList<>();\n\t\t\tint length;\n\t\t\twhile ((length = input.readShort()) != -1) {\n\t\t\t\tList<DoubleCoordinates> linkedFilter = new ArrayList<>();\n\t\t\t\tfor (int i = 0; i < length; i++) {\n\t\t\t\t\tlinkedFilter.add(new DoubleCoordinates(input));\n\t\t\t\t}\n\t\t\t\ttypeFilters.add(linkedFilter);\n\t\t\t}\n\t\t\tfilterPositions.put(type, typeFilters);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tClientViewController.instance().handlePacket(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeSerializable(pos);\n\t\tfor (PipeRoutingConnectionType type : filters.keySet()) {\n\t\t\toutput.writeShort(type.ordinal());\n\t\t\tfor (List<IFilter> linkedFilter : filters.get(type)) {\n\t\t\t\toutput.writeShort(linkedFilter.size());\n\t\t\t\tfor (IFilter filter : linkedFilter) {\n\t\t\t\t\toutput.writeSerializable(filter.getLPPosition());\n\t\t\t\t}\n\t\t\t}\n\t\t\toutput.writeShort(-1);\n\t\t}\n\t\toutput.writeShort(-1);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateDebugFilters(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateDoneDebug.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateDoneDebug extends ModernPacket {\n\n\tpublic RoutingUpdateDoneDebug(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tClientViewController.instance().done(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateDoneDebug(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateInitDebug.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateInitDebug extends ModernPacket {\n\n\tpublic RoutingUpdateInitDebug(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tClientViewController.instance().init(this);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateInitDebug(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateSourcePipe.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateSourcePipe extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate ExitRoute exitRoute;\n\n\tpublic RoutingUpdateSourcePipe(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (exitRoute != null) {\n\t\t\tClientViewController.instance().handlePacket(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateSourcePipe(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\ttry {\n\t\t\texitRoute = new ExitRoute(input);\n\t\t} catch (RuntimeException e) {\n\t\t\tLogisticsPipes.log.error(\"Could not read ExitRoute from RoutingUpdateSourcePipe\", e);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\texitRoute.write(output);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateTargetResponse.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.TextComponentString;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.commands.chathelper.LPChatListener;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.gui.OpenChatGui;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.routing.debug.DebugController;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class RoutingUpdateTargetResponse extends ModernPacket {\n\n\t@Getter\n\t@Setter\n\tprivate TargetMode mode;\n\t@Getter\n\t@Setter\n\tprivate int[] additions = new int[0];\n\n\tpublic RoutingUpdateTargetResponse(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tmode = TargetMode.values()[input.readByte()];\n\t\tadditions = input.readIntArray();\n\t}\n\n\t@Override\n\tpublic void processPacket(final EntityPlayer player) {\n\t\tif (mode == TargetMode.None) {\n\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No Target Found\"));\n\t\t} else if (mode == TargetMode.Block) {\n\t\t\tint x = additions[0];\n\t\t\tint y = additions[1];\n\t\t\tint z = additions[2];\n\t\t\tplayer.sendMessage(new TextComponentString(\"Checking Block at: x:\" + x + \" y:\" + y + \" z:\" + z));\n\t\t\tBlock id = player.world.getBlockState(new BlockPos(x, y, z)).getBlock();\n\t\t\tplayer.sendMessage(new TextComponentString(\"Found Block with Id: \" + Block.getIdFromBlock(id)));\n\t\t\tfinal TileEntity tile = player.world.getTileEntity(new BlockPos(x, y, z));\n\t\t\tif (tile == null) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No TileEntity found\"));\n\t\t\t} else if (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No LogisticsTileGenericPipe found\"));\n\t\t\t} else if (!(((LogisticsTileGenericPipe) tile).pipe instanceof CoreRoutedPipe)) {\n\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"No CoreRoutedPipe found\"));\n\t\t\t} else {\n\t\t\t\tLPChatListener.addTask(() -> {\n\t\t\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.GREEN + \"Starting RoutingTable debug update.\"));\n\t\t\t\t\tDebugController.instance(player).debug(((ServerRouter) ((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).getRouter()));\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t\t\treturn true;\n\t\t\t\t}, player);\n\t\t\t\tplayer.sendMessage(new TextComponentString(\n\t\t\t\t\t\tChatColor.AQUA + \"Start RoutingTable debug update ? \" + ChatColor.RESET + \"<\" + ChatColor.GREEN + \"yes\" + ChatColor.RESET + \"/\"\n\t\t\t\t\t\t\t\t+ ChatColor.RED + \"no\" + ChatColor.RESET + \">\"));\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), player);\n\t\t\t}\n\t\t} else if (mode == TargetMode.Entity) {\n\t\t\tplayer.sendMessage(new TextComponentString(ChatColor.RED + \"Entity not allowed\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeByte(mode.ordinal());\n\t\toutput.writeIntArray(additions);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateTargetResponse(getId());\n\t}\n\n\t@Override\n\tpublic boolean isCompressable() {\n\t\treturn true;\n\t}\n\n\tpublic enum TargetMode {\n\t\tBlock,\n\t\tEntity,\n\t\tNone\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/routingdebug/RoutingUpdateUntrace.java",
    "content": "package logisticspipes.network.packets.routingdebug;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.IntegerPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.routing.debug.DebugController;\nimport logisticspipes.utils.StaticResolve;\n\n@StaticResolve\npublic class RoutingUpdateUntrace extends IntegerPacket {\n\n\tpublic RoutingUpdateUntrace(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tDebugController.instance(player).untrace(getInteger());\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new RoutingUpdateUntrace(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/satpipe/SatelliteSetNamePacket.java",
    "content": "package logisticspipes.network.packets.satpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringCoordinatesPacket;\nimport logisticspipes.pipes.SatelliteNamingResult;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.SatellitePipe;\n\n@StaticResolve\npublic class SatelliteSetNamePacket extends StringCoordinatesPacket {\n\n\tpublic SatelliteSetNamePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tLogisticsTileGenericPipe pipe = this.getPipe(player.getEntityWorld(), LTGPCompletionCheck.PIPE);\n\t\tif (pipe == null || pipe.pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tString newName = getString();\n\t\tSatelliteNamingResult result = null;\n\t\tif (newName.trim().isEmpty()) {\n\t\t\tresult = SatelliteNamingResult.BLANK_NAME;\n\t\t} else if (pipe.pipe instanceof SatellitePipe) {\n\t\t\tfinal SatellitePipe satellitePipe = (SatellitePipe) pipe.pipe;\n\t\t\tif (satellitePipe.getSatellitesOfType().stream().anyMatch(it -> it.getSatellitePipeName().equals(newName))) {\n\t\t\t\tresult = SatelliteNamingResult.DUPLICATE_NAME;\n\t\t\t} else {\n\t\t\t\tresult = SatelliteNamingResult.SUCCESS;\n\t\t\t\tsatellitePipe.setSatellitePipeName(newName);\n\t\t\t\tsatellitePipe.updateWatchers();\n\t\t\t\tsatellitePipe.ensureAllSatelliteStatus();\n\t\t\t}\n\t\t}\n\t\tif (result != null) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SetNameResult.class).setResult(result).setNewName(getString()), player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SatelliteSetNamePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/satpipe/SetNameResult.java",
    "content": "package logisticspipes.network.packets.satpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.gui.GuiSatellitePipe;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.SatelliteNamingResult;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SetNameResult extends ModernPacket {\n\n\t@Setter\n\t@Getter\n\tprivate SatelliteNamingResult result;\n\t@Setter\n\t@Getter\n\tprivate String newName;\n\n\tpublic SetNameResult(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tresult = input.readEnum(SatelliteNamingResult.class);\n\t\tnewName = input.readUTF();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeEnum(result);\n\t\toutput.writeUTF(newName);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiSatellitePipe) {\n\t\t\t((GuiSatellitePipe) FMLClientHandler.instance().getClient().currentScreen).handleResponse(result, newName);\n\t\t}\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SetNameResult(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/satpipe/SyncSatelliteNamePacket.java",
    "content": "package logisticspipes.network.packets.satpipe;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.StringCoordinatesPacket;\nimport logisticspipes.pipes.PipeFluidSatellite;\nimport logisticspipes.pipes.PipeItemsSatelliteLogistics;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.SatellitePipe;\n\n@StaticResolve\npublic class SyncSatelliteNamePacket extends StringCoordinatesPacket {\n\n\tpublic SyncSatelliteNamePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SyncSatelliteNamePacket(getId());\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tfinal LogisticsTileGenericPipe pipe = getPipe(player.world, LTGPCompletionCheck.PIPE);\n\t\tif (pipe == null || pipe.pipe == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (pipe.pipe instanceof SatellitePipe) {\n\t\t\t((SatellitePipe) pipe.pipe).setSatellitePipeName(getString());\n\t\t}\n\t\t\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/upgrade/SneakyUpgradeSidePacket.java",
    "content": "package logisticspipes.network.packets.upgrade;\n\nimport java.util.Objects;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.SlotPacket;\nimport logisticspipes.pipes.upgrades.SneakyUpgradeConfig;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.UpgradeSlot;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SneakyUpgradeSidePacket extends SlotPacket {\n\n\t@Setter\n\t@Getter\n\tprivate EnumFacing side;\n\n\tpublic SneakyUpgradeSidePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tUpgradeSlot slot = getSlot(player, UpgradeSlot.class);\n\t\tItemStack stack = slot.getStack();\n\t\tif (stack.isEmpty()) return;\n\t\tif (!stack.hasTagCompound()) {\n\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t}\n\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\ttag.setString(SneakyUpgradeConfig.SIDE_KEY, SneakyUpgradeConfig.Sides.getNameForDirection(side));\n\t\tslot.putStack(stack);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeFacing(side);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tside = input.readFacing();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SneakyUpgradeSidePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/network/packets/upgrade/ToogleDisconnectionUpgradeSidePacket.java",
    "content": "package logisticspipes.network.packets.upgrade;\n\nimport java.util.Objects;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.abstractpackets.SlotPacket;\nimport logisticspipes.pipes.upgrades.ConnectionUpgradeConfig;\nimport logisticspipes.utils.StaticResolve;\nimport logisticspipes.utils.gui.UpgradeSlot;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class ToogleDisconnectionUpgradeSidePacket extends SlotPacket {\n\n\t@Getter\n\t@Setter\n\tprivate EnumFacing side;\n\n\tpublic ToogleDisconnectionUpgradeSidePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tUpgradeSlot slot = getSlot(player, UpgradeSlot.class);\n\t\tItemStack stack = slot.getStack();\n\t\tif (stack.isEmpty()) return;\n\n\t\tif (!stack.hasTagCompound()) {\n\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t}\n\n\t\tNBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\tString sideName = ConnectionUpgradeConfig.Sides.getNameForDirection(side);\n\t\ttag.setBoolean(sideName, !tag.getBoolean(sideName));\n\n\t\tstack.setTagCompound(tag);\n\n\t\tslot.putStack(stack);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\toutput.writeFacing(side);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tside = input.readFacing();\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new ToogleDisconnectionUpgradeSidePacket(getId());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/EntityModelFX.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.Particle;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\n\npublic class EntityModelFX extends Particle {\n\n\tprivate final IModel3D model;\n\tprivate final I3DOperation[] operations;\n\tprivate final ResourceLocation texture;\n\n\tpublic EntityModelFX(World world, double x, double y, double z, IModel3D model, I3DOperation[] i3dOperations, ResourceLocation texture) {\n\t\tsuper(world, x, y, z, 0, -5, 0);\n\t\tthis.model = model;\n\t\tthis.operations = i3dOperations;\n\t\tthis.texture = texture;\n\t}\n\n\t@Override\n\tpublic void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) {\n\t\tTessellator.getInstance().draw();\n\t\tGL11.glPushMatrix();\n\t\tdouble x = posX - Particle.interpPosX;\n\t\tdouble y = posY - Particle.interpPosY;\n\t\tdouble z = posZ - Particle.interpPosZ;\n\t\tGL11.glTranslated(x, y, z);\n\n\t\tSimpleServiceLocator.cclProxy.getRenderState().reset();\n\t\tSimpleServiceLocator.cclProxy.getRenderState().setAlphaOverride(0xff);\n\n\t\tMinecraft.getMinecraft().getTextureManager().bindTexture(texture);\n\t\tSimpleServiceLocator.cclProxy.getRenderState().startDrawing(GL11.GL_QUADS, DefaultVertexFormats.OLDMODEL_POSITION_TEX_NORMAL);\n\t\tmodel.render(operations);\n\t\tSimpleServiceLocator.cclProxy.getRenderState().draw();\n\n\t\tGL11.glPopMatrix();\n\t\t// Set texture back to particles\n\t\tMinecraft.getMinecraft().getTextureManager().bindTexture(new ResourceLocation(\"textures/particle/particles.png\"));\n\t\tBufferBuilder buffer = Tessellator.getInstance().getBuffer();\n\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/EntitySparkleFX.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport java.util.Random;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.entity.EntityPlayerSP;\nimport net.minecraft.client.particle.Particle;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport org.lwjgl.opengl.GL11;\n\npublic class EntitySparkleFX extends Particle {\n\n\tpublic int multiplier;\n\tpublic boolean shrink;\n\tpublic int particle;\n\tpublic int blendmode;\n\n\tpublic EntitySparkleFX(World world, double x, double y, double z, float scalemult, float red, float green, float blue, int var12) {\n\t\tsuper(world, x, y, z, 0.0D, 0.0D, 0.0D);\n\t\tshrink = false;\n\t\tparticle = 0;\n\t\tblendmode = 1;\n\n\t\tparticleRed = red;\n\t\tparticleGreen = green;\n\t\tparticleBlue = blue;\n\t\tparticleGravity = 0.07F;\n\t\tmotionX = motionY = motionZ = 0.0D;\n\t\tparticleScale *= scalemult;\n\t\tparticleMaxAge = 3 * var12 - 1;\n\t\tmultiplier = var12;\n\t\tcanCollide = false;\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/particles/particles.png\");\n\tprivate static final ResourceLocation field_110737_b = new ResourceLocation(\"textures/particle/particles.png\");\n\n\t@Override\n\tpublic void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) {\n\t\tTessellator.getInstance().draw();\n\t\tGL11.glPushMatrix();\n\t\tGL11.glDepthMask(false);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, blendmode);\n\t\tMinecraft.getMinecraft().renderEngine.bindTexture(EntitySparkleFX.TEXTURE);\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 0.75F);\n\t\tint var8 = particle + particleAge / multiplier;\n\t\tfloat var9 = var8 % 8 / 8.0F;\n\t\tfloat var10 = var9 + 0.124875F;\n\t\tfloat var11 = var8 / 8 / 8.0F;\n\t\tfloat var12 = var11 + 0.124875F;\n\t\tfloat var13 = 0.1F * particleScale * ((float) (particleMaxAge - particleAge + 1) / (float) particleMaxAge);\n\t\tfloat var14 = (float) (prevPosX + (posX - prevPosX) * partialTicks - Particle.interpPosX);\n\t\tfloat var15 = (float) (prevPosY + (posY - prevPosY) * partialTicks - Particle.interpPosY);\n\t\tfloat var16 = (float) (prevPosZ + (posZ - prevPosZ) * partialTicks - Particle.interpPosZ);\n\t\tfloat var17 = 1.0F;\n\t\tBufferBuilder buffer = Tessellator.getInstance().getBuffer();\n\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);\n\t\t//tesselator.setBrightness(240);\n\t\tbuffer.pos(var14 - rotationX * var13 - rotationXY * var13, var15 - rotationZ * var13, var16 - rotationYZ * var13 - rotationXZ * var13).tex(var10, var12).color(particleRed * var17, particleGreen * var17, particleBlue * var17, 1.0F).endVertex();\n\t\tbuffer.pos(var14 - rotationX * var13 + rotationXY * var13, var15 + rotationZ * var13, var16 - rotationYZ * var13 + rotationXZ * var13).tex(var10, var11).color(particleRed * var17, particleGreen * var17, particleBlue * var17, 1.0F).endVertex();\n\t\tbuffer.pos(var14 + rotationX * var13 + rotationXY * var13, var15 + rotationZ * var13, var16 + rotationYZ * var13 + rotationXZ * var13).tex(var9, var11).color(particleRed * var17, particleGreen * var17, particleBlue * var17, 1.0F).endVertex();\n\t\tbuffer.pos(var14 + rotationX * var13 - rotationXY * var13, var15 - rotationZ * var13, var16 + rotationYZ * var13 - rotationXZ * var13).tex(var9, var12).color(particleRed * var17, particleGreen * var17, particleBlue * var17, 1.0F).endVertex();\n\t\tTessellator.getInstance().draw();\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\tGL11.glDepthMask(true);\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\tGL11.glPopMatrix();\n\t\tMinecraft.getMinecraft().renderEngine.bindTexture(EntitySparkleFX.field_110737_b);\n\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);\n\t}\n\n\t/**\n\t * Called to update the entity's position/logic.\n\t */\n\t@Override\n\tpublic void onUpdate() {\n\t\ttry {\n\t\t\tEntityPlayerSP var1 = Minecraft.getMinecraft().player;\n\n\t\t\tif (var1.getDistance(posX, posY, posZ) > 50) {\n\t\t\t\tsetExpired();\n\t\t\t}\n\n\t\t\tprevPosX = posX;\n\t\t\tprevPosY = posY;\n\t\t\tprevPosZ = posZ;\n\n\t\t\tif (particleAge++ >= particleMaxAge) {\n\t\t\t\tsetExpired();\n\t\t\t}\n\n\t\t\tmotionX -= 0.05D * particleGravity - 0.1D * particleGravity * new Random().nextDouble();\n\t\t\tmotionY -= 0.05D * particleGravity - 0.1D * particleGravity * new Random().nextDouble();\n\t\t\tmotionZ -= 0.05D * particleGravity - 0.1D * particleGravity * new Random().nextDouble();\n\n\t\t\tmove(motionX, motionY, motionZ);\n\t\t\tmotionX *= 0.9800000190734863D;\n\t\t\tmotionY *= 0.9800000190734863D;\n\t\t\tmotionZ *= 0.9800000190734863D;\n\n\t\t\tif (onGround) {\n\t\t\t\tmotionX *= 0.699999988079071D;\n\t\t\t\tmotionZ *= 0.699999988079071D;\n\t\t\t}\n\t\t} catch (Exception ignored) {\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/GenericSparkleFactory.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport net.minecraft.world.World;\n\npublic class GenericSparkleFactory {\n\n\tpublic static EntitySparkleFX getSparkleInstance(World world, double x, double y, double z, float red, float green, float blue, int amount) {\n\n\t\tEntitySparkleFX effect;\n\n\t\tfloat boundry = 0.4F;\n\t\tint pipeWidth = 3;\n\n\t\tfloat width = boundry + world.rand.nextInt(pipeWidth) / 10.0F;\n\t\tfloat length = boundry + world.rand.nextInt(pipeWidth) / 10.0F;\n\t\tfloat height = world.rand.nextInt(7) / 10.0F + 0.2F;\n\n\t\tfloat scalemult = 1f + (float) Math.log10(amount);\n\n\t\teffect = new EntitySparkleFX(world, x + length, y + height, z + width, scalemult, red, green, blue, 6 + world.rand.nextInt(3));\n\n\t\treturn effect;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/ParticleProvider.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\npublic interface ParticleProvider {\n\n\tfloat red = 1;\n\tfloat green = 1;\n\tfloat blue = 1;\n\n\tParticle createGenericParticle(WorldClient world, double x, double y, double z, int amount);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/Particles.java",
    "content": "package logisticspipes.pipefxhandlers;\n\npublic enum Particles {\n\tWhiteParticle,\n\tRedParticle,\n\tBlueParticle,\n\tGreenParticle,\n\tGoldParticle,\n\tVioletParticle,\n\tOrangeParticle,\n\tLightGreenParticle,\n\tLightRedParticle\n\n\t/**\n\t * General color arangement: SinkReply: blue Extract: orange\n\t * Provide/request: violet Use power: gold Render update: green Power status\n\t * change: red Special cases: white\n\t */\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/PipeFXLaserPowerBall.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport java.util.Random;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.Particle;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.experimental.Accessors;\nimport org.lwjgl.opengl.GL11;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@Accessors(chain = true)\npublic class PipeFXLaserPowerBall extends Particle {\n\n\tprivate static final ResourceLocation ball = new ResourceLocation(\"logisticspipes\", \"textures/particles/laserBall.png\");\n\tprivate static final ResourceLocation field_110737_b = new ResourceLocation(\"textures/particle/particles.png\");\n\tprivate static final int ROTATIONSPEED = 5;\n\tprivate static final Random RAND = new Random();\n\n\tprivate float random;\n\tprivate TileEntity tile;\n\n\tpublic PipeFXLaserPowerBall(World par1World, DoubleCoordinates pos, int color, TileEntity tile) {\n\t\tsuper(par1World, pos.getXCoord() + 0.5D, pos.getYCoord() + 0.5D, pos.getZCoord() + 0.5D, 0.0D, 0.0D, 0.0D);\n\t\tthis.tile = tile;\n\t\tsetSize(0.02F, 0.02F);\n\t\tparticleRed = ((float) ((color & 0xff0000) >> 16)) / 0xff;\n\t\tparticleGreen = ((float) ((color & 0x00ff00) >> 8)) / 0xff;\n\t\tparticleBlue = ((float) ((color & 0x0000ff) >> 0)) / 0xff;\n\t\tcanCollide = false;\n\t\tmotionX = 0.0D;\n\t\tmotionY = 0.0D;\n\t\tmotionZ = 0.0D;\n\t\tprevPosX = posX;\n\t\tprevPosY = posY;\n\t\tprevPosZ = posZ;\n\t\tparticleMaxAge = 0;\n\t\trandom = PipeFXLaserPowerBall.RAND.nextFloat() * PipeFXLaserPowerBall.RAND.nextInt(360 / PipeFXLaserPowerBall.ROTATIONSPEED);\n\t\tEntity renderentity = FMLClientHandler.instance().getClient().getRenderViewEntity();\n\t\tint visibleDistance = 50;\n\t\tif (!FMLClientHandler.instance().getClient().gameSettings.fancyGraphics) {\n\t\t\tvisibleDistance = 25;\n\t\t}\n\t\tif (renderentity.getDistance(posX, posY, posZ) > visibleDistance) {\n\t\t\tsetExpired();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onUpdate() {\n\t\tif (tile.isInvalid()) {\n\t\t\tsetExpired();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) {\n\t\tTessellator.getInstance().draw();\n\t\tGL11.glPushMatrix();\n\t\tfloat rot = (world.provider.getWorldTime() + random) % (360 / PipeFXLaserPowerBall.ROTATIONSPEED) * PipeFXLaserPowerBall.ROTATIONSPEED + PipeFXLaserPowerBall.ROTATIONSPEED * partialTicks;\n\n\t\tGL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, 10497.0F);\n\t\tGL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, 10497.0F);\n\t\tGL11.glDisable(GL11.GL_CULL_FACE);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);\n\t\tGL11.glDepthMask(false);\n\n\t\tdouble x = posX - Particle.interpPosX;\n\t\tdouble y = posY - Particle.interpPosY;\n\t\tdouble z = posZ - Particle.interpPosZ;\n\t\tGL11.glTranslated(x, y, z);\n\n\t\tGL11.glRotatef(rot, 0.0F, 1.0F, 0.0F);\n\t\tGL11.glRotatef(rot, 0.0F, 0.0F, 1.0F);\n\t\tint repeat = 3;\n\t\tfloat rotate = 60.0F;\n\t\tMinecraft.getMinecraft().renderEngine.bindTexture(PipeFXLaserPowerBall.ball);\n\t\tfor (int t = 0; t < repeat; t++) {\n\t\t\tGL11.glRotatef(rotate, 0.0F, 0.0F, 1.0F);\n\t\t\tfor (int u = 0; u < repeat; u++) {\n\t\t\t\tGL11.glRotatef(rotate, 1.0F, 0.0F, 0.0F);\n\t\t\t\tfor (int v = 0; v < repeat; v++) {\n\t\t\t\t\tGL11.glRotatef(rotate, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\tBufferBuilder buffer = Tessellator.getInstance().getBuffer();\n\t\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);\n\t\t\t\t\tdouble zoom = 0.25D;\n\t\t\t\t\tbuffer.pos(zoom, zoom, 0.0D).tex(1.0D, 1.0D).color(particleRed, particleGreen, particleBlue, 0.8F).endVertex();\n\t\t\t\t\tbuffer.pos(zoom, -zoom, 0.0D).tex(1.0D, 0.0D).color(particleRed, particleGreen, particleBlue, 0.8F).endVertex();\n\t\t\t\t\tbuffer.pos(-zoom, -zoom, 0.0D).tex(0.0D, 0.0D).color(particleRed, particleGreen, particleBlue, 0.8F).endVertex();\n\t\t\t\t\tbuffer.pos(-zoom, zoom, 0.0D).tex(0.0D, 1.0D).color(particleRed, particleGreen, particleBlue, 0.8F).endVertex();\n\t\t\t\t\tTessellator.getInstance().draw();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tGL11.glDepthMask(true);\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\tGL11.glEnable(GL11.GL_CULL_FACE);\n\t\tGL11.glPopMatrix();\n\t\tMinecraft.getMinecraft().renderEngine.bindTexture(PipeFXLaserPowerBall.field_110737_b);\n\t\tBufferBuilder buffer = Tessellator.getInstance().getBuffer();\n\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/PipeFXLaserPowerBeam.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport java.util.Random;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.Particle;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.MathHelper;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Setter;\nimport lombok.experimental.Accessors;\nimport org.lwjgl.opengl.GL11;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@Accessors(chain = true)\npublic class PipeFXLaserPowerBeam extends Particle {\n\n\tprivate static final ResourceLocation beam = new ResourceLocation(\"logisticspipes\", \"textures/particles/laserBeam.png\");\n\tprivate static final ResourceLocation field_110737_b = new ResourceLocation(\"textures/particle/particles.png\");\n\tprivate static final int ROTATIONSPEED = 5;\n\tprivate static final Random RAND = new Random();\n\n\t@Setter\n\tprivate boolean reverse = false;\n\tprivate float length;\n\tprivate float yaw;\n\tprivate float pitch;\n\tprivate float random;\n\tprivate TileEntity tile;\n\n\tpublic PipeFXLaserPowerBeam(World par1World, DoubleCoordinates pos, float length, EnumFacing dir, int color, TileEntity tile) {\n\t\tsuper(par1World, pos.getXCoord() + 0.5D, pos.getYCoord() + 0.5D, pos.getZCoord() + 0.5D, 0.0D, 0.0D, 0.0D);\n\t\tsetSize(0.02F, 0.02F);\n\t\tthis.tile = tile;\n\t\tparticleRed = ((float) ((color & 0xff0000) >> 16)) / 0xff;\n\t\tparticleGreen = ((float) ((color & 0x00ff00) >> 8)) / 0xff;\n\t\tparticleBlue = ((float) ((color & 0x0000ff) >> 0)) / 0xff;\n\t\tcanCollide = false;\n\t\tmotionX = 0.0D;\n\t\tmotionY = 0.0D;\n\t\tmotionZ = 0.0D;\n\t\tprevPosX = posX;\n\t\tprevPosY = posY;\n\t\tprevPosZ = posZ;\n\t\tthis.length = length;\n\t\trandom = PipeFXLaserPowerBeam.RAND.nextFloat() * PipeFXLaserPowerBeam.RAND.nextInt(10);\n\t\tdir = dir.getOpposite();\n\t\tyaw = ((float) (Math.atan2(dir.getDirectionVec().getX(), dir.getDirectionVec().getZ()) * 180.0D / Math.PI));\n\t\tpitch = ((float) (Math.atan2(dir.getDirectionVec().getY(), MathHelper.sqrt(dir.getDirectionVec().getX() * dir.getDirectionVec().getX() + dir.getDirectionVec().getZ() * dir.getDirectionVec().getZ())) * 180.0D / Math.PI));\n\t\tparticleMaxAge = 0;\n\t\tEntity renderentity = FMLClientHandler.instance().getClient().getRenderViewEntity();\n\t\tint visibleDistance = 50;\n\t\tif (!FMLClientHandler.instance().getClient().gameSettings.fancyGraphics) {\n\t\t\tvisibleDistance = 25;\n\t\t}\n\t\tif (renderentity.getDistance(posX, posY, posZ) > visibleDistance) {\n\t\t\tsetExpired();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onUpdate() {\n\t\tif (tile.isInvalid()) {\n\t\t\tsetExpired();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void renderParticle(BufferBuilder worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ) {\n\t\tTessellator.getInstance().draw();\n\t\tGL11.glPushMatrix();\n\t\tfloat slide = world.getTotalWorldTime() + random;\n\t\tfloat rot = world.provider.getWorldTime() % (360 / PipeFXLaserPowerBeam.ROTATIONSPEED) * PipeFXLaserPowerBeam.ROTATIONSPEED + PipeFXLaserPowerBeam.ROTATIONSPEED * partialTicks;\n\n\t\tGL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, 10497.0F);\n\t\tGL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, 10497.0F);\n\n\t\tGL11.glDisable(GL11.GL_CULL_FACE);\n\n\t\tfloat partSlide = slide + partialTicks;\n\t\tif (reverse) {\n\t\t\tpartSlide *= -1.0F;\n\t\t}\n\t\tfloat globalTextureSlide = -partSlide * 0.2F - MathHelper.floor(-partSlide * 0.1F);\n\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);\n\t\tGL11.glDepthMask(false);\n\n\t\tdouble x = posX - Particle.interpPosX;\n\t\tdouble y = posY - Particle.interpPosY;\n\t\tdouble z = posZ - Particle.interpPosZ;\n\t\tGL11.glTranslated(x, y, z);\n\n\t\tGL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);\n\t\tGL11.glRotatef(180.0F + yaw, 0.0F, 0.0F, -1.0F);\n\t\tGL11.glRotatef(pitch, 1.0F, 0.0F, 0.0F);\n\n\t\tGL11.glRotatef(rot, 0.0F, 1.0F, 0.0F);\n\t\tif (length != 0) {\n\t\t\tMinecraft.getMinecraft().renderEngine.bindTexture(PipeFXLaserPowerBeam.beam);\n\t\t\tfor (int t = 0; t < 3; t++) {\n\t\t\t\tdouble texturePos = -1.0F + globalTextureSlide + t / 3.0F;\n\t\t\t\tGL11.glRotatef(60.0F, 0.0F, 1.0F, 0.0F);\n\t\t\t\tBufferBuilder buffer = Tessellator.getInstance().getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);\n\t\t\t\tbuffer.pos(-0.07D, length, 0.0D).tex(1.0D, length + texturePos).color(particleRed, particleGreen, particleBlue, 0.5F).endVertex();\n\t\t\t\tbuffer.pos(-0.07D, 0.0D, 0.0D).tex(1.0D, texturePos).color(particleRed, particleGreen, particleBlue, 0.5F).endVertex();\n\t\t\t\tbuffer.pos(0.07D, 0.0D, 0.0D).tex(0.0D, texturePos).color(particleRed, particleGreen, particleBlue, 0.5F).endVertex();\n\t\t\t\tbuffer.pos(0.07D, length, 0.0D).tex(0.0D, length + texturePos).color(particleRed, particleGreen, particleBlue, 0.5F).endVertex();\n\t\t\t\tTessellator.getInstance().draw();\n\t\t\t}\n\t\t}\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tGL11.glDepthMask(true);\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\tGL11.glEnable(GL11.GL_CULL_FACE);\n\t\tGL11.glPopMatrix();\n\t\tMinecraft.getMinecraft().renderEngine.bindTexture(PipeFXLaserPowerBeam.field_110737_b);\n\t\tBufferBuilder buffer = Tessellator.getInstance().getBuffer();\n\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.PARTICLE_POSITION_TEX_COLOR_LMAP);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/PipeFXRenderHandler.java",
    "content": "package logisticspipes.pipefxhandlers;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.proxy.MainProxy;\n\npublic class PipeFXRenderHandler {\n\n\tprivate static ParticleProvider[] particlemap = new ParticleProvider[Particles.values().length];\n\n\tpublic static void spawnGenericParticle(Particles particle, double x, double y, double z, int amount) {\n\t\tif (MainProxy.getClientMainWorld() == null) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tMinecraft mc = Minecraft.getMinecraft();\n\t\t\tint var14 = mc.gameSettings.particleSetting;\n\t\t\tdouble var15 = mc.getRenderViewEntity().posX - x;\n\t\t\tdouble var17 = mc.getRenderViewEntity().posY - y;\n\t\t\tdouble var19 = mc.getRenderViewEntity().posZ - z;\n\t\t\tParticle effect;\n\n\t\t\tdouble var22 = 16.0D;\n\n\t\t\tif (var15 * var15 + var17 * var17 + var19 * var19 > var22 * var22) {\n\t\t\t\treturn;\n\t\t\t} else if (var14 > 1) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tParticleProvider provider = PipeFXRenderHandler.particlemap[particle.ordinal()];\n\t\t\tif (provider == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (int i = 0; i < Math.sqrt(amount); i++) {\n\t\t\t\teffect = provider.createGenericParticle(mc.world, x, y, z, amount);\n\t\t\t\tif (effect != null) {\n\t\t\t\t\tmc.effectRenderer.addEffect(effect);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (NullPointerException ignored) {}\n\t}\n\n\tpublic static void registerParticleHandler(Particles particle, ParticleProvider provider) {\n\t\tif (PipeFXRenderHandler.particlemap[particle.ordinal()] == null) {\n\t\t\tPipeFXRenderHandler.particlemap[particle.ordinal()] = provider;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityBlueSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityBlueSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0F;\n\tfloat green = 0F;\n\tfloat blue = 1F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityGoldSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityGoldSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0.93F;\n\tfloat green = 0.80F;\n\tfloat blue = 0.36F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityGreenSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityGreenSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0F;\n\tfloat green = 1F;\n\tfloat blue = 0F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityLightGreenSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityLightGreenSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0.8125F;\n\tfloat green = 0.9411764705882353F;\n\tfloat blue = 0.3098039215686275F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityLightRedSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityLightRedSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0.9375F;\n\tfloat green = 0.3203125F;\n\tfloat blue = 0.30859375F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityOrangeSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityOrangeSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0.97F;\n\tfloat green = 0.46F;\n\tfloat blue = 0.19F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityRedSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityRedSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 1F;\n\tfloat green = 0F;\n\tfloat blue = 0F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityVioletSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityVioletSparkleFXProvider implements ParticleProvider {\n\n\tfloat red = 0.51F;\n\tfloat green = 0.04F;\n\tfloat blue = 0.73F;\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, red, green, blue, amount);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipefxhandlers/providers/EntityWhiteSparkleFXProvider.java",
    "content": "package logisticspipes.pipefxhandlers.providers;\n\nimport net.minecraft.client.multiplayer.WorldClient;\nimport net.minecraft.client.particle.Particle;\n\nimport logisticspipes.pipefxhandlers.GenericSparkleFactory;\nimport logisticspipes.pipefxhandlers.ParticleProvider;\n\npublic class EntityWhiteSparkleFXProvider implements ParticleProvider {\n\n\t@Override\n\tpublic Particle createGenericParticle(WorldClient world, double x, double y, double z, int amount) {\n\n\t\treturn GenericSparkleFactory.getSparkleInstance(world, x, y, z, ParticleProvider.red, ParticleProvider.green, ParticleProvider.blue, amount);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeBlockRequestTable.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.InventoryCraftResult;\nimport net.minecraft.inventory.SlotCrafting;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.IRecipe;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport net.minecraftforge.event.world.WorldEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.crafting.AutoCraftingInventory;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IRequestWatcher;\nimport logisticspipes.interfaces.IRotationProvider;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.TransportLayer;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.CraftingSetType;\nimport logisticspipes.network.packets.block.RequestRotationPacket;\nimport logisticspipes.network.packets.orderer.OrderWatchRemovePacket;\nimport logisticspipes.network.packets.orderer.OrdererWatchPacket;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.CraftingUtil;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.SimpleStackInventory;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class PipeBlockRequestTable extends PipeItemsRequestLogistics implements ISimpleInventoryEventHandler, IRequestWatcher, IGuiOpenControler, IRotationProvider {\n\n\tpublic SimpleStackInventory diskInv = new SimpleStackInventory(1, \"Disk Slot\", 1);\n\tpublic SimpleStackInventory inv = new SimpleStackInventory(27, \"Crafting Resources\", 64);\n\tpublic ItemIdentifierInventory matrix = new ItemIdentifierInventory(9, \"Crafting Matrix\", 1);\n\tpublic ItemIdentifierInventory resultInv = new ItemIdentifierInventory(1, \"Crafting Result\", 1);\n\tpublic SimpleStackInventory toSortInv = new SimpleStackInventory(1, \"Sorting Slot\", 64);\n\tprivate InventoryCraftResult vanillaResult = new InventoryCraftResult();\n\tprivate IRecipe cache;\n\tprivate EntityPlayerMP fake;\n\tprivate int delay = 0;\n\tprivate int tick = 0;\n\tprivate int rotation;\n\tprivate boolean init = false;\n\n\tprivate PlayerCollectionList localGuiWatcher = new PlayerCollectionList();\n\tpublic Map<Integer, Pair<IResource, LinkedLogisticsOrderList>> watchedRequests = new HashMap<>();\n\tprivate int localLastUsedWatcherId = 0;\n\n\tpublic ItemIdentifier targetType = null;\n\n\tpublic PipeBlockRequestTable(Item item) {\n\t\tsuper(item);\n\t\tmatrix.addListener(this);\n\t}\n\n\t@Override\n\tpublic boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\t//allow using upgrade manager\n\t\tif (MainProxy.isPipeControllerEquipped(entityplayer) && !(entityplayer.isSneaking())) {\n\t\t\treturn false;\n\t\t}\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (settings == null || settings.openGui) {\n\t\t\t\topenGui(entityplayer);\n\t\t\t} else {\n\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void ignoreDisableUpdateEntity() {\n\t\tsuper.ignoreDisableUpdateEntity();\n\t\tif (tick++ == 5) {\n\t\t\tgetWorld().markBlockRangeForRenderUpdate(getX(), getY(), getZ(), getX(), getY(), getZ());\n\t\t}\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tif (!init) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestRotationPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t\t\t\tinit = true;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tif (tick % 2 == 0 && !localGuiWatcher.isEmpty()) {\n\t\t\tcheckForExpired();\n\t\t\tif (getUpgradeManager().hasCraftingMonitoringUpgrade()) {\n\t\t\t\tfor (Entry<Integer, Pair<IResource, LinkedLogisticsOrderList>> entry : watchedRequests.entrySet()) {\n\t\t\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(OrdererWatchPacket.class).setOrders(entry.getValue().getValue2()).setStack(entry.getValue().getValue1()).setInteger(entry.getKey()).setTilePos(container), localGuiWatcher);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (tick % 20 == 0) {\n\t\t\tcheckForExpired();\n\t\t}\n\t}\n\n\tprivate void checkForExpired() {\n\t\tIterator<Entry<Integer, Pair<IResource, LinkedLogisticsOrderList>>> iter = watchedRequests.entrySet().iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tEntry<Integer, Pair<IResource, LinkedLogisticsOrderList>> entry = iter.next();\n\t\t\tif (isDone(entry.getValue().getValue2())) {\n\t\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(OrderWatchRemovePacket.class).setInteger(entry.getKey()).setTilePos(container), localGuiWatcher);\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate boolean isDone(LinkedLogisticsOrderList orders) {\n\t\tboolean isDone = true;\n\t\tfor (IOrderInfoProvider order : orders) {\n\t\t\tif (!order.isFinished()) {\n\t\t\t\tisDone = false;\n\t\t\t}\n\t\t\tif (!order.getProgresses().isEmpty()) {\n\t\t\t\tisDone = false;\n\t\t\t}\n\t\t}\n\t\tfor (LinkedLogisticsOrderList orderList : orders.getSubOrders()) {\n\t\t\tif (!isDone(orderList)) {\n\t\t\t\tisDone = false;\n\t\t\t}\n\t\t}\n\t\treturn isDone;\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tItemStack stack = toSortInv.getStackInSlot(0);\n\t\tif (!stack.isEmpty()) {\n\t\t\tif (delay > 0) {\n\t\t\t\tdelay--;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tIRoutedItem itemToSend = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);\n\t\t\tSimpleServiceLocator.logisticsManager.assignDestinationFor(itemToSend, getRouter().getSimpleID(), false);\n\t\t\tif (itemToSend.getDestinationUUID() != null) {\n\t\t\t\tEnumFacing dir = getRouteLayer().getOrientationForItem(itemToSend, null);\n\t\t\t\tsuper.queueRoutedItem(itemToSend, dir.getOpposite());\n\t\t\t\tspawnParticle(Particles.OrangeParticle, 4);\n\t\t\t\ttoSortInv.clearInventorySlotContents(0);\n\t\t\t} else {\n\t\t\t\tdelay = 100;\n\t\t\t}\n\t\t} else {\n\t\t\tdelay = 0;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void openGui(EntityPlayer entityplayer) {\n\t\tboolean flag = true;\n\t\tif (!diskInv.getStackInSlot(0).isEmpty()) {\n\t\t\tif (!entityplayer.getHeldItemMainhand().isEmpty() && entityplayer.getHeldItemMainhand().getItem().equals(LPItems.disk)) {\n\t\t\t\tdiskInv.setInventorySlotContents(0, entityplayer.getHeldItemMainhand());\n\t\t\t\tentityplayer.inventory.setInventorySlotContents(entityplayer.inventory.currentItem, ItemStack.EMPTY);\n\t\t\t\tflag = false;\n\t\t\t}\n\t\t}\n\t\tif (flag) {\n\t\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Request_Table_ID, getWorld(), getX(), getY(), getZ());\n\t\t}\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.empty;\n\t}\n\n\t@Override\n\tpublic TextureType getRoutedTexture(EnumFacing connection) {\n\t\treturn Textures.empty_1;\n\t}\n\n\t@Override\n\tpublic TextureType getNonRoutedTexture(EnumFacing connection) {\n\t\treturn Textures.empty_2;\n\t}\n\n\t/*public TextureAtlasSprite getTextureFor(int l) {\n\t\tEnumFacing dir = EnumFacing.byIndex(l);\n\t\t//if (LogisticsPipes.getClientPlayerConfig().isUseNewRenderer()) {\n\t\t\tswitch (dir) {\n\t\t\t\tcase UP:\n\t\t\t\tcase DOWN:\n\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE_NEW_EMPTY;\n\t\t\t\tdefault:\n\t\t\t\t\tif (container.renderState.pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\t\t\tif (container.renderState.textureMatrix.getTextureIndex(dir) == 1) {\n\t\t\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE_NEW_ROUTED;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE_NEW_UNROUTED;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE_NEW_EMPTY;\n\t\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tswitch (dir) {\n\t\t\t\tcase UP:\n\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE[0];\n\t\t\t\tcase DOWN:\n\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE[1];\n\t\t\t\tdefault:\n\t\t\t\t\tif (container.renderState.pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\t\t\tif (container.renderState.textureMatrix.getTextureIndex(dir) == 1) {\n\t\t\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE[2];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE[3];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn Textures.LOGISTICS_REQUEST_TABLE[4];\n\t\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}*/\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tinv.dropContents(getWorld(), getPos());\n\t\t\ttoSortInv.dropContents(getWorld(), getPos());\n\t\t\tdiskInv.dropContents(getWorld(), getPos());\n\t\t}\n\t}\n\n\tpublic void cacheRecipe() {\n\t\tItemIdentifier oldTargetType = targetType;\n\t\tcache = null;\n\t\tresultInv.clearInventorySlotContents(0);\n\t\tAutoCraftingInventory craftInv = new AutoCraftingInventory(null);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t}\n\t\tList<IRecipe> list = new ArrayList<>();\n\t\tfor (IRecipe r : CraftingUtil.getRecipeList()) {\n\t\t\tif (r.matches(craftInv, getWorld())) {\n\t\t\t\tlist.add(r);\n\t\t\t}\n\t\t}\n\t\tif (list.size() == 1) {\n\t\t\tcache = list.get(0);\n\t\t\tresultInv.setInventorySlotContents(0, cache.getCraftingResult(craftInv));\n\t\t\ttargetType = null;\n\t\t} else if (list.size() > 1) {\n\t\t\tif (targetType != null) {\n\t\t\t\tfor (IRecipe recipe : list) {\n\t\t\t\t\tcraftInv = new AutoCraftingInventory(null);\n\t\t\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t\t\t\t}\n\t\t\t\t\tItemStack result = recipe.getCraftingResult(craftInv);\n\t\t\t\t\tif (targetType == ItemIdentifier.get(result)) {\n\t\t\t\t\t\tresultInv.setInventorySlotContents(0, result);\n\t\t\t\t\t\tcache = recipe;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (cache == null) {\n\t\t\t\tcache = list.get(0);\n\t\t\t\tItemStack result = cache.getCraftingResult(craftInv);\n\t\t\t\tresultInv.setInventorySlotContents(0, result);\n\t\t\t\ttargetType = ItemIdentifier.get(result);\n\t\t\t}\n\t\t} else {\n\t\t\ttargetType = null;\n\t\t}\n\t\tif (targetType != oldTargetType && !localGuiWatcher.isEmpty() && getWorld() != null && MainProxy.isServer(getWorld())) {\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(CraftingSetType.class).setTargetType(targetType).setTilePos(container), localGuiWatcher);\n\t\t}\n\t}\n\n\tpublic void cycleRecipe(boolean down) {\n\t\tcacheRecipe();\n\t\tif (targetType == null) {\n\t\t\treturn;\n\t\t}\n\t\tcache = null;\n\t\tAutoCraftingInventory craftInv = new AutoCraftingInventory(null);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t}\n\t\tList<IRecipe> list = new ArrayList<>();\n\t\tfor (IRecipe r : CraftingUtil.getRecipeList()) {\n\t\t\tif (r.matches(craftInv, getWorld())) {\n\t\t\t\tlist.add(r);\n\t\t\t}\n\t\t}\n\t\tif (list.size() > 1) {\n\t\t\tboolean found = false;\n\t\t\tIRecipe prev = null;\n\t\t\tfor (IRecipe recipe : list) {\n\t\t\t\tif (found) {\n\t\t\t\t\tcache = recipe;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcraftInv = new AutoCraftingInventory(null);\n\t\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t\t\t}\n\t\t\t\tif (targetType == ItemIdentifier.get(recipe.getCraftingResult(craftInv))) {\n\t\t\t\t\tif (down) {\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (prev == null) {\n\t\t\t\t\t\t\tcache = list.get(list.size() - 1);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcache = prev;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tprev = recipe;\n\t\t\t}\n\t\t\tif (cache == null) {\n\t\t\t\tcache = list.get(0);\n\t\t\t}\n\t\t\tcraftInv = new AutoCraftingInventory(null);\n\t\t\tfor (int i = 0; i < 9; i++) {\n\t\t\t\tcraftInv.setInventorySlotContents(i, matrix.getStackInSlot(i));\n\t\t\t}\n\t\t\ttargetType = ItemIdentifier.get(cache.getCraftingResult(craftInv));\n\t\t}\n\t\tif (!localGuiWatcher.isEmpty() && getWorld() != null && MainProxy.isServer(getWorld())) {\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(CraftingSetType.class).setTargetType(targetType).setTilePos(container), localGuiWatcher);\n\t\t}\n\t\tcacheRecipe();\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getOutput(boolean oreDict) {\n\t\tif (cache == null) {\n\t\t\tcacheRecipe();\n\t\t\tif (cache == null) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t}\n\t\tif (resultInv.getIDStackInSlot(0) == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\n\t\tint[] toUse = new int[9];\n\t\tint[] used = new int[inv.getSizeInventory()];\n\t\touter:\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tItemStack item = matrix.getStackInSlot(i);\n\t\t\tif (item.isEmpty()) {\n\t\t\t\ttoUse[i] = -1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemIdentifier ident = ItemIdentifier.get(item);\n\t\t\tfor (int j = 0; j < inv.getSizeInventory(); j++) {\n\t\t\t\titem = inv.getStackInSlot(j);\n\t\t\t\tif (item.isEmpty()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tItemIdentifier withIdent = ItemIdentifier.get(item);\n\t\t\t\tif (ident.equalsForCrafting(withIdent)) {\n\t\t\t\t\tif (item.getCount() > used[j]) {\n\t\t\t\t\t\tused[j]++;\n\t\t\t\t\t\ttoUse[i] = j;\n\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (oreDict) {\n\t\t\t\t\tif (ident.getDictIdentifiers() != null && withIdent.getDictIdentifiers() != null && ident.getDictIdentifiers().canMatch(withIdent.getDictIdentifiers(), true, false)) {\n\t\t\t\t\t\tif (item.getCount() > used[j]) {\n\t\t\t\t\t\t\tused[j]++;\n\t\t\t\t\t\t\ttoUse[i] = j;\n\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t//Not enough material\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tAutoCraftingInventory crafter = new AutoCraftingInventory(null);//TODO\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tint j = toUse[i];\n\t\t\tif (j != -1) {\n\t\t\t\tcrafter.setInventorySlotContents(i, inv.getStackInSlot(j));\n\t\t\t}\n\t\t}\n\t\tif (!cache.matches(crafter, getWorld())) {\n\t\t\treturn ItemStack.EMPTY; //Fix MystCraft\n\t\t}\n\t\tItemStack result = cache.getCraftingResult(crafter);\n\t\tif (result.isEmpty()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tif (!resultInv.getIDStackInSlot(0).getItem().equalsWithoutNBT(ItemIdentifier.get(result))) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tcrafter = new AutoCraftingInventory(null);//TODO\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tint j = toUse[i];\n\t\t\tif (j != -1) {\n\t\t\t\tcrafter.setInventorySlotContents(i, inv.decrStackSize(j, 1));\n\t\t\t}\n\t\t}\n\t\tresult = cache.getCraftingResult(crafter);\n\t\tif (fake == null) {\n\t\t\tfake = MainProxy.getFakePlayer(getWorld());\n\t\t}\n\t\tresult = result.copy();\n\n\t\tSlotCrafting craftingSlot = new SlotCrafting(fake, crafter, resultInv, 0, 0, 0) {\n\n\t\t\t@Override\n\t\t\tprotected void onCrafting(@Nonnull ItemStack stack) {\n\t\t\t\tIInventory tmp = this.inventory;\n\t\t\t\tvanillaResult.setRecipeUsed(cache);\n\t\t\t\tthis.inventory = vanillaResult;\n\t\t\t\tsuper.onCrafting(stack);\n\t\t\t\tthis.inventory = tmp;\n\t\t\t}\n\t\t};\n\t\tresult = craftingSlot.onTake(fake, result);\n\t\tfor (int i = 0; i < 9; i++) {\n\t\t\tItemStack left = crafter.getStackInSlot(i);\n\t\t\tcrafter.setInventorySlotContents(i, ItemStack.EMPTY);\n\t\t\tif (!left.isEmpty()) {\n\t\t\t\tleft.setCount(inv.addCompressed(left, false));\n\t\t\t\tif (left.getCount() > 0) {\n\t\t\t\t\tItemIdentifierInventory.dropItems(getWorld(), left, getX(), getY(), getZ());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < fake.inventory.getSizeInventory(); i++) {\n\t\t\tItemStack left = fake.inventory.getStackInSlot(i);\n\t\t\tfake.inventory.setInventorySlotContents(i, ItemStack.EMPTY);\n\t\t\tif (!left.isEmpty()) {\n\t\t\t\tleft.setCount(inv.addCompressed(left, false));\n\t\t\t\tif (left.getCount() > 0) {\n\t\t\t\t\tItemIdentifierInventory.dropItems(getWorld(), left, getX(), getY(), getZ());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getResultForClick() {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tItemStack result = getOutput(true);\n\t\t\tif (result.isEmpty()) {\n\t\t\t\tresult = getOutput(false);\n\t\t\t}\n\t\t\tif (result.isEmpty()) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t\tresult.setCount(inv.addCompressed(result, false));\n\t\t\tif (result.getCount() > 0) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tif (inventory == matrix) {\n\t\t\tcacheRecipe();\n\t\t}\n\t}\n\n\tpublic void handleNEIRecipePacket(NonNullList<ItemStack> content) {\n\t\tif (matrix.getSizeInventory() != content.size()) throw new IllegalStateException(\"Different sizes of matrix and inventory from packet\");\n\t\tfor (int i = 0; i < content.size(); i++) {\n\t\t\tmatrix.setInventorySlotContents(i, content.get(i));\n\t\t}\n\t\tcacheRecipe();\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tsuper.readFromNBT(par1nbtTagCompound);\n\t\tinv.readFromNBT(par1nbtTagCompound, \"inv\");\n\t\tmatrix.readFromNBT(par1nbtTagCompound, \"matrix\");\n\t\ttoSortInv.readFromNBT(par1nbtTagCompound, \"toSortInv\");\n\t\tdiskInv.readFromNBT(par1nbtTagCompound, \"diskInv\");\n\t\trotation = par1nbtTagCompound.getInteger(\"blockRotation\");\n\t\t//TODO NPEs on world load\n\t\t//cacheRecipe();\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound par1nbtTagCompound) {\n\t\tsuper.writeToNBT(par1nbtTagCompound);\n\t\tinv.writeToNBT(par1nbtTagCompound, \"inv\");\n\t\tmatrix.writeToNBT(par1nbtTagCompound, \"matrix\");\n\t\ttoSortInv.writeToNBT(par1nbtTagCompound, \"toSortInv\");\n\t\tdiskInv.writeToNBT(par1nbtTagCompound, \"diskInv\");\n\t\tpar1nbtTagCompound.setInteger(\"blockRotation\", rotation);\n\t}\n\n\t@Override\n\tpublic boolean isOnSameContainer(CoreRoutedPipe other) {\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic TransportLayer getTransportLayer() {\n\t\tif (_transportLayer == null) {\n\t\t\t_transportLayer = new TransportLayer() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void handleItem(IRoutedItem item) {\n\t\t\t\t\tPipeBlockRequestTable.this.notifyOfItemArival(item.getInfo());\n\t\t\t\t\tif (item.getItemIdentifierStack() != null) {\n\t\t\t\t\t\tItemIdentifierStack stack = item.getItemIdentifierStack();\n\t\t\t\t\t\tstack.setStackSize(inv.addCompressed(stack.makeNormalStack(), false));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic EnumFacing itemArrived(IRoutedItem item, EnumFacing denied) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean stillWantItem(IRoutedItem item) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\treturn _transportLayer;\n\t}\n\n\t@Override\n\tpublic void handleOrderList(IResource stack, LinkedLogisticsOrderList orders) {\n\t\tif (!getUpgradeManager().hasCraftingMonitoringUpgrade()) {\n\t\t\treturn;\n\t\t}\n\t\torders.setWatched();\n\t\twatchedRequests.put(++localLastUsedWatcherId, new Pair<>(stack, orders));\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(OrdererWatchPacket.class).setOrders(orders).setStack(stack).setInteger(localLastUsedWatcherId).setTilePos(container), localGuiWatcher);\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OrderWatchRemovePacket.class).setInteger(-1).setTilePos(container), player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(CraftingSetType.class).setTargetType(targetType).setTilePos(container), player);\n\t\tlocalGuiWatcher.add(player);\n\t\tfor (Entry<Integer, Pair<IResource, LinkedLogisticsOrderList>> entry : watchedRequests.entrySet()) {\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OrdererWatchPacket.class).setOrders(entry.getValue().getValue2()).setStack(entry.getValue().getValue1()).setInteger(entry.getKey()).setTilePos(container), player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tlocalGuiWatcher.remove(player);\n\t}\n\n\t@Override\n\tpublic void handleClientSideListInfo(int id, IResource stack, LinkedLogisticsOrderList orders) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\twatchedRequests.put(id, new Pair<>(stack, orders));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleClientSideRemove(int id) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tif (id == -1) {\n\t\t\t\twatchedRequests.clear();\n\t\t\t} else {\n\t\t\t\twatchedRequests.remove(id);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getDisk() {\n\t\treturn diskInv.getStackInSlot(0);\n\t}\n\n\t@Override\n\tpublic int getRotation() {\n\t\treturn rotation;\n\t}\n\n\t@Override\n\tpublic void setRotation(int rotation) {\n\t\tthis.rotation = rotation;\n\t}\n\n\t@Override\n\tpublic boolean isMultipartAllowedInPipe() {\n\t\treturn false;\n\t}\n\n\t@SubscribeEvent\n\tpublic void onWorldUnload(WorldEvent.Unload worldEvent) {\n\t\tif (fake.world == worldEvent.getWorld())\n\t\t\tfake = null;\n\t}\n\n\t@Override\n\tpublic boolean isPipeBlock() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeFluidExtractor.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport logisticspipes.interfaces.ITankUtil;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.FluidIdentifierStack;\n\npublic class PipeFluidExtractor extends PipeFluidInsertion {\n\n\tprivate int[] liquidToExtract = new int[6];\n\n\tprivate static final int flowRate = 500;\n\tprivate static final int energyPerFlow = 5;\n\n\tpublic PipeFluidExtractor(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (!isNthTick(10)) {\n\t\t\treturn;\n\t\t}\n\t\tPipeFluidUtil.INSTANCE.getAdjacentTanks(this, false)\n\t\t\t\t.forEach(tankData -> extractFrom(tankData.getValue2(), tankData.getValue1().getDirection()));\n\t}\n\n\tprivate void extractFrom(ITankUtil container, EnumFacing side) {\n\t\tint sideID = side.ordinal();\n\t\tFluidStack contained = ((PipeFluidTransportLogistics) transport).getTankProperties(side)[0].getContents();\n\t\tint amountMissing = ((PipeFluidTransportLogistics) transport).getSideCapacity() - (contained != null ? contained.amount : 0);\n\t\tif (liquidToExtract[sideID] < Math.min(PipeFluidExtractor.flowRate, amountMissing)) {\n\t\t\tif (this.useEnergy(PipeFluidExtractor.energyPerFlow)) {\n\t\t\t\tliquidToExtract[sideID] += Math.min(PipeFluidExtractor.flowRate, amountMissing);\n\t\t\t}\n\t\t}\n\t\tFluidIdentifierStack extracted = container.drain(Math.min(liquidToExtract[sideID], PipeFluidExtractor.flowRate), false);\n\n\t\tint inserted = 0;\n\t\tif (extracted != null) {\n\t\t\tinserted = ((PipeFluidTransportLogistics) transport).fill(side, extracted.makeFluidStack(), true);\n\t\t\tcontainer.drain(inserted, true);\n\t\t}\n\t\tliquidToExtract[sideID] -= inserted;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tnbttagcompound.setIntArray(\"liquidToExtract\", liquidToExtract);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tliquidToExtract = nbttagcompound.getIntArray(\"liquidToExtract\");\n\t\tif (liquidToExtract.length < 6) {\n\t\t\tliquidToExtract = new int[6];\n\t\t}\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUID_EXTRACTOR;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeFluidInsertion.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.FluidSinkReply;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class PipeFluidInsertion extends FluidRoutedPipe {\n\n\tprivate final List<Pair<Integer, Integer>> localJamList = new ArrayList<>();\n\tprivate int[] nextSendMax = new int[EnumFacing.VALUES.length];\n\tprivate int[] nextSendMin = new int[EnumFacing.VALUES.length];\n\n\tpublic PipeFluidInsertion(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tList<Integer> tempJamList = new ArrayList<>();\n\t\tif (!localJamList.isEmpty()) {\n\t\t\tList<Pair<Integer, Integer>> toRemove = new ArrayList<>();\n\t\t\tfor (Pair<Integer, Integer> part : localJamList) {\n\t\t\t\tpart.setValue2(part.getValue2() - 1);\n\t\t\t\tif (part.getValue2() <= 0) {\n\t\t\t\t\ttoRemove.add(part);\n\t\t\t\t} else {\n\t\t\t\t\ttempJamList.add(part.getValue1());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!toRemove.isEmpty()) {\n\t\t\t\tlocalJamList.removeAll(toRemove);\n\t\t\t}\n\t\t}\n\t\tPipeFluidTransportLogistics transport = (PipeFluidTransportLogistics) this.transport;\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tFluidStack stack = transport.sideTanks[dir.ordinal()].getFluid();\n\t\t\tif (stack == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstack = stack.copy();\n\n\t\t\tif (nextSendMax[dir.ordinal()] > 0 && stack.amount < transport.sideTanks[dir.ordinal()].getCapacity()) {\n\t\t\t\tnextSendMax[dir.ordinal()]--;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (nextSendMin[dir.ordinal()] > 0) {\n\t\t\t\tnextSendMin[dir.ordinal()]--;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tPair<Integer, FluidSinkReply> result = SimpleServiceLocator.logisticsFluidManager.getBestReply(FluidIdentifierStack.getFromStack(stack), getRouter(), tempJamList);\n\t\t\tif (result == null || result.getValue2().sinkAmount <= 0) {\n\t\t\t\tnextSendMax[dir.ordinal()] = 100;\n\t\t\t\tnextSendMin[dir.ordinal()] = 10;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!useEnergy((int) (0.01 * result.getValue2().getSinkAmountInt()))) {\n\t\t\t\tnextSendMax[dir.ordinal()] = 100;\n\t\t\t\tnextSendMin[dir.ordinal()] = 10;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tFluidStack toSend = transport.sideTanks[dir.ordinal()].drain(result.getValue2().getSinkAmountInt(), true);\n\t\t\tItemIdentifierStack liquidContainer = SimpleServiceLocator.logisticsFluidManager.getFluidContainer(FluidIdentifierStack.getFromStack(toSend));\n\t\t\tIRoutedItem routed = SimpleServiceLocator.routedItemHelper.createNewTravelItem(liquidContainer);\n\t\t\trouted.setDestination(result.getValue1());\n\t\t\trouted.setTransportMode(TransportMode.Passive);\n\t\t\tthis.queueRoutedItem(routed, dir);\n\t\t\tnextSendMax[dir.ordinal()] = 100;\n\t\t\tnextSendMin[dir.ordinal()] = 5;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.writeToNBT(tag);\n\t\ttag.setIntArray(\"nextSendMax\", nextSendMax);\n\t\ttag.setIntArray(\"nextSendMin\", nextSendMin);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\tnextSendMax = tag.getIntArray(\"nextSendMax\");\n\t\tif (nextSendMax.length < 6) {\n\t\t\tnextSendMax = new int[6];\n\t\t}\n\t\tnextSendMin = tag.getIntArray(\"nextSendMin\");\n\t\tif (nextSendMin.length < 6) {\n\t\t\tnextSendMin = new int[6];\n\t\t}\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUID_INSERTION;\n\t}\n\n\t@Override\n\tpublic boolean canInsertToTanks() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canInsertFromSideToTanks() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canReceiveFluid() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeFluidProvider.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport logisticspipes.interfaces.ISpecialTankAccessHandler;\nimport logisticspipes.interfaces.ISpecialTankUtil;\nimport logisticspipes.interfaces.ITankUtil;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IProvideFluids;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.request.resources.FluidResource;\nimport logisticspipes.routing.FluidLogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.routing.order.LogisticsFluidOrder;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\n\npublic class PipeFluidProvider extends FluidRoutedPipe implements IProvideFluids {\n\n\tpublic PipeFluidProvider(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (!getFluidOrderManager().hasOrders(ResourceType.PROVIDER) || !isNthTick(6)) {\n\t\t\treturn;\n\t\t}\n\n\t\tLogisticsFluidOrder order = getFluidOrderManager().peekAtTopRequest(ResourceType.PROVIDER);\n\t\tAtomicInteger amountToSend = new AtomicInteger();\n\t\tAtomicInteger attemptedAmount = new AtomicInteger();\n\t\tamountToSend.set(Math.min(order.getAmount(), 5000));\n\t\tattemptedAmount.set(Math.min(order.getAmount(), 5000));\n\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> pair : PipeFluidUtil.INSTANCE.getAdjacentTanks(this, false)) {\n\t\t\tif (amountToSend.get() <= 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tboolean fallback = true;\n\t\t\tif (pair.getValue2() instanceof ISpecialTankUtil) {\n\t\t\t\tISpecialTankUtil util = (ISpecialTankUtil) pair.getValue2();\n\t\t\t\tfallback = false;\n\t\t\t\tISpecialTankAccessHandler handler = util.getSpecialHandler();\n\t\t\t\tFluidStack drained = handler.drainFrom(pair.getValue1().getTileEntity(), order.getFluid(), amountToSend.get(), false);\n\t\t\t\tif (drained != null && drained.amount > 0 && order.getFluid().equals(FluidIdentifier.get(drained))) {\n\t\t\t\t\tdrained = handler.drainFrom(pair.getValue1().getTileEntity(), order.getFluid(), amountToSend.get(), true);\n\t\t\t\t\tint amount = drained.amount;\n\t\t\t\t\tamountToSend.addAndGet(-amount);\n\t\t\t\t\tItemIdentifierStack stack = SimpleServiceLocator.logisticsFluidManager.getFluidContainer(FluidIdentifierStack.getFromStack(drained));\n\t\t\t\t\tIRoutedItem item = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);\n\t\t\t\t\titem.setDestination(order.getRouter().getSimpleID());\n\t\t\t\t\titem.setTransportMode(TransportMode.Active);\n\t\t\t\t\tthis.queueRoutedItem(item, pair.getValue1().getDirection());\n\t\t\t\t\tgetFluidOrderManager().sendSuccessfull(amount, false, item);\n\t\t\t\t\tif (amountToSend.get() <= 0) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\tif (pair.getValue2().containsTanks()) {\n\t\t\t\t\tpair.getValue2().tanks().map(tank -> FluidIdentifierStack.getFromStack(tank.getContents())).forEach(fluidStack -> {\n\t\t\t\t\t\tif (amountToSend.get() <= 0) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (fluidStack != null && fluidStack.getFluid() != null) {\n\t\t\t\t\t\t\tif (order.getFluid().equals(fluidStack.getFluid())) {\n\t\t\t\t\t\t\t\tint amount = Math.min(fluidStack.getAmount(), amountToSend.get());\n\t\t\t\t\t\t\t\tFluidIdentifierStack drained = pair.getValue2().drain(amount, false);\n\t\t\t\t\t\t\t\tif (drained != null && drained.getAmount() > 0 && order.getFluid().equals(drained.getFluid())) {\n\t\t\t\t\t\t\t\t\tdrained = pair.getValue2().drain(amount, true);\n\t\t\t\t\t\t\t\t\twhile (drained.getAmount() < amountToSend.get()) {\n\t\t\t\t\t\t\t\t\t\tFluidIdentifierStack addition = pair.getValue2().drain(amountToSend.get() - drained.getAmount(), false);\n\t\t\t\t\t\t\t\t\t\tif (addition != null && addition.getAmount() > 0 && order.getFluid().equals(addition.getFluid())) {\n\t\t\t\t\t\t\t\t\t\t\taddition = pair.getValue2().drain(amountToSend.get() - drained.getAmount(), true);\n\t\t\t\t\t\t\t\t\t\t\tdrained.raiseAmount(addition.getAmount());\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tamount = drained.getAmount();\n\t\t\t\t\t\t\t\t\tamountToSend.addAndGet(-amount);\n\t\t\t\t\t\t\t\t\tItemIdentifierStack stack = SimpleServiceLocator.logisticsFluidManager.getFluidContainer(drained);\n\t\t\t\t\t\t\t\t\tIRoutedItem item = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);\n\t\t\t\t\t\t\t\t\titem.setDestination(order.getRouter().getSimpleID());\n\t\t\t\t\t\t\t\t\titem.setTransportMode(TransportMode.Active);\n\t\t\t\t\t\t\t\t\tqueueRoutedItem(item, pair.getValue1().getDirection());\n\t\t\t\t\t\t\t\t\tgetFluidOrderManager().sendSuccessfull(amount, false, item);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (amountToSend.get() >= attemptedAmount.get()) {\n\t\t\tgetFluidOrderManager().sendFailed();\n\t\t}\n\t}\n\n\t@Override\n\tpublic Map<FluidIdentifier, Integer> getAvailableFluids() {\n\t\tMap<FluidIdentifier, Integer> map = new HashMap<>();\n\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> pair : PipeFluidUtil.INSTANCE.getAdjacentTanks(this, false)) {\n\t\t\tboolean fallback = true;\n\t\t\tif (pair.getValue2() instanceof ISpecialTankUtil) {\n\t\t\t\tfinal ISpecialTankUtil util = (ISpecialTankUtil) pair.getValue2();\n\t\t\t\tfallback = false;\n\t\t\t\tISpecialTankAccessHandler handler = util.getSpecialHandler();\n\t\t\t\tTileEntity tile = util.getTileEntity();\n\t\t\t\tMap<FluidIdentifier, Long> tmp = handler.getAvailableLiquid(tile);\n\t\t\t\tfor (Entry<FluidIdentifier, Long> entry : tmp.entrySet()) {\n\t\t\t\t\tif (map.containsKey(entry.getKey())) {\n\t\t\t\t\t\tlong addition = ((long) map.get(entry.getKey())) + entry.getValue();\n\t\t\t\t\t\tmap.put(entry.getKey(), addition > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) addition);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmap.put(entry.getKey(), entry.getValue() > Integer.MAX_VALUE ? Integer.MAX_VALUE : entry.getValue().intValue());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\tif (pair.getValue2().containsTanks()) {\n\t\t\t\t\tpair.getValue2().tanks().map(tank -> FluidIdentifierStack.getFromStack(tank.getContents())).forEach(liquid -> {\n\t\t\t\t\t\tif (liquid != null && liquid.getFluid() != null) {\n\t\t\t\t\t\t\tFluidIdentifier ident = liquid.getFluid();\n\t\t\t\t\t\t\tif (pair.getValue2().canDrain(ident)) {\n\t\t\t\t\t\t\t\tif (pair.getValue2().drain(ident.makeFluidIdentifierStack(1), false) != null) {\n\t\t\t\t\t\t\t\t\tif (map.containsKey(ident)) {\n\t\t\t\t\t\t\t\t\t\tlong addition = ((long) map.get(ident)) + liquid.getAmount();\n\t\t\t\t\t\t\t\t\t\tmap.put(ident, addition > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) addition);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tmap.put(ident, liquid.getAmount());\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tMap<FluidIdentifier, Integer> result = new HashMap<>();\n\t\t//Reduce what has been reserved, add.\n\t\tfor (Entry<FluidIdentifier, Integer> fluid : map.entrySet()) {\n\t\t\tint remaining = fluid.getValue() - getFluidOrderManager().totalFluidsCountInOrders(fluid.getKey());\n\t\t\tif (remaining < 1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tresult.put(fluid.getKey(), remaining);\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUID_PROVIDER;\n\t}\n\n\t@Override\n\tpublic void canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filter) {\n\t\tif (tree.isDone()) {\n\t\t\treturn;\n\t\t}\n\t\tif (!(tree.getRequestType() instanceof FluidResource)) {\n\t\t\treturn;\n\t\t}\n\t\tFluidIdentifier fluid = ((FluidResource) tree.getRequestType()).getFluid();\n\t\tAtomicInteger containedAmount = new AtomicInteger(0);\n\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> pair : PipeFluidUtil.INSTANCE.getAdjacentTanks(this, false)) {\n\t\t\tboolean fallback = true;\n\t\t\tif (pair.getValue2() instanceof ISpecialTankUtil) {\n\t\t\t\tfinal ISpecialTankUtil util = (ISpecialTankUtil) pair.getValue2();\n\t\t\t\tfallback = false;\n\t\t\t\tISpecialTankAccessHandler handler = util.getSpecialHandler();\n\t\t\t\tTileEntity tile = util.getTileEntity();\n\t\t\t\tMap<FluidIdentifier, Long> map = handler.getAvailableLiquid(tile);\n\t\t\t\tif (map.containsKey(fluid)) {\n\t\t\t\t\tlong addition = (containedAmount.get()) + map.get(fluid);\n\t\t\t\t\tcontainedAmount.set(addition > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) addition);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\tif (pair.getValue2().containsTanks()) {\n\t\t\t\t\tpair.getValue2().tanks().map(tank -> FluidIdentifierStack.getFromStack(tank.getContents())).forEach(liquid -> {\n\t\t\t\t\t\tif (liquid != null && liquid.getFluid() != null) {\n\t\t\t\t\t\t\tif (fluid.equals(liquid.getFluid())) {\n\t\t\t\t\t\t\t\tif (pair.getValue2().canDrain(liquid.getFluid())) {\n\t\t\t\t\t\t\t\t\tif (pair.getValue2().drain(liquid.getFluid().makeFluidIdentifierStack(1), false) != null) {\n\t\t\t\t\t\t\t\t\t\tlong addition = ((long) containedAmount.get()) + liquid.getAmount();\n\t\t\t\t\t\t\t\t\t\tcontainedAmount.set(addition > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) addition);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tFluidLogisticsPromise promise = new FluidLogisticsPromise();\n\t\tpromise.liquid = fluid;\n\t\tpromise.amount = Math.min(tree.getMissingAmount(), containedAmount.get() - root.getAllPromissesFor(this, fluid.getItemIdentifier()));\n\t\tpromise.sender = this;\n\t\tpromise.type = ResourceType.PROVIDER;\n\t\tif (promise.amount > 0) {\n\t\t\ttree.addPromise(promise);\n\t\t}\n\t}\n\n\t@Override\n\tpublic IOrderInfoProvider fullFill(FluidLogisticsPromise promise, IRequestFluid destination, ResourceType type, IAdditionalTargetInformation info) {\n\t\treturn getFluidOrderManager().addOrder(promise, destination, type, info);\n\t}\n\n\t@Override\n\tpublic boolean canInsertToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean canInsertFromSideToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\t//work in progress, currently not active code.\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> pair : PipeFluidUtil.INSTANCE.getAdjacentTanks(this, false)) {\n\t\t\tboolean fallback = true;\n\t\t\tif (pair.getValue2() instanceof ISpecialTankUtil) {\n\t\t\t\tfinal ISpecialTankUtil util = (ISpecialTankUtil) pair.getValue2();\n\t\t\t\tfallback = false;\n\t\t\t\tISpecialTankAccessHandler handler = util.getSpecialHandler();\n\t\t\t\tTileEntity tile = util.getTileEntity();\n\t\t\t\thandler.getAvailableLiquid(tile).keySet().stream()\n\t\t\t\t\t\t.map(FluidIdentifier::getItemIdentifier)\n\t\t\t\t\t\t.forEach(itemIdentifiers::add);\n\t\t\t}\n\t\t\tif (fallback) {\n\t\t\t\tif (pair.getValue2().containsTanks()) {\n\t\t\t\t\tpair.getValue2().tanks().map(tank -> FluidIdentifierStack.getFromStack(tank.getContents())).forEach(liquid -> {\n\t\t\t\t\t\tif (liquid != null && liquid.getFluid() != null) {\n\t\t\t\t\t\t\tif (pair.getValue2().canDrain(liquid.getFluid())) {\n\t\t\t\t\t\t\t\tif (pair.getValue2().drain(1, false) != null) {\n\t\t\t\t\t\t\t\t\tFluidIdentifier ident = liquid.getFluid();\n\t\t\t\t\t\t\t\t\titemIdentifiers.add(ident.getItemIdentifier());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean canReceiveFluid() {\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeFluidRequestLogistics.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.FluidIdentifier;\n\npublic class PipeFluidRequestLogistics extends FluidRoutedPipe implements IRequestFluid {\n\n\tpublic PipeFluidRequestLogistics(Item item) {\n\t\tsuper(item);\n\t}\n\n\tpublic void openGui(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Fluid_Orderer_ID, getWorld(), getX(), getY(), getZ());\n\t}\n\n\t@Override\n\tpublic boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (settings == null || settings.openRequest) {\n\t\t\t\topenGui(entityplayer);\n\t\t\t} else {\n\t\t\t\tentityplayer.sendMessage(new TextComponentString(\"Permission denied\"));\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUID_REQUEST;\n\t}\n\n\t@Override\n\tpublic void sendFailed(FluidIdentifier value1, Integer value2) {\n\t\t//Request Pipe doesn't handle this.\n\t}\n\n\t@Override\n\tpublic boolean canInsertToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean canInsertFromSideToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean canReceiveFluid() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeFluidSatellite.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.gui.hud.HUDSatellite;\nimport logisticspipes.interfaces.IChestContentReceiver;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.interfaces.routing.IRequireReliableFluidTransport;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleSatellite;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.hud.ChestContent;\nimport logisticspipes.network.packets.hud.HUDStartWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopWatchingPacket;\nimport logisticspipes.network.packets.satpipe.SyncSatelliteNamePacket;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.SatellitePipe;\n\npublic class PipeFluidSatellite extends FluidRoutedPipe implements IRequestFluid, IRequireReliableFluidTransport, IHeadUpDisplayRendererProvider, IChestContentReceiver, SatellitePipe {\n\n\t// from baseLogicLiquidSatellite\n\tpublic static final Set<PipeFluidSatellite> AllSatellites = new HashSet<>();\n\n\t// called only on server shutdown\n\tpublic static void cleanup() {\n\t\tPipeFluidSatellite.AllSatellites.clear();\n\t}\n\n\tpublic final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final List<ItemIdentifierStack> itemList = new LinkedList<>();\n\tprivate final List<ItemIdentifierStack> oldList = new LinkedList<>();\n\tprivate final HUDSatellite HUD = new HUDSatellite(this);\n\tprotected final Map<FluidIdentifier, Integer> _lostItems = new HashMap<>();\n\tprivate final ModuleSatellite moduleSatellite;\n\n\t@Getter\n\tprivate String satellitePipeName = \"\";\n\n\tpublic PipeFluidSatellite(Item item) {\n\t\tsuper(item);\n\t\tthrottleTime = 40;\n\t\tmoduleSatellite = new ModuleSatellite();\n\t\tmoduleSatellite.registerHandler(this, this);\n\t\tmoduleSatellite.registerPosition(LogisticsModule.ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Override\n\tpublic boolean canInsertFromSideToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean canInsertToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUID_SATELLITE;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn moduleSatellite;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (isNthTick(20) && localModeWatchers.size() > 0) {\n\t\t\tupdateInv(false);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void sendFailed(FluidIdentifier liquid, Integer amount) {\n\t\tliquidLost(liquid, amount);\n\t}\n\n\tprivate void updateInv(boolean force) {\n\t\titemList.clear();\n\t\titemList.addAll(PipeFluidUtil.INSTANCE.fluidsToItemList(this));\n\n\t\tif (!itemList.equals(oldList) || force) {\n\t\t\toldList.clear();\n\t\t\toldList.addAll(itemList);\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(ChestContent.class).setIdentList(itemList).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), localModeWatchers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setReceivedChestContent(Collection<ItemIdentifierStack> list) {\n\t\titemList.clear();\n\t\titemList.addAll(list);\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tlocalModeWatchers.add(player);\n\t\t\tfinal ModernPacket packet = PacketHandler.getPacket(SyncSatelliteNamePacket.class).setString((this).satellitePipeName).setPosX(getX()).setPosY(getY()).setPosZ(getZ());\n\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\tupdateInv(true);\n\t\t} else {\n\t\t\tsuper.playerStartWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tsuper.playerStopWatching(player, mode);\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tif (nbttagcompound.hasKey(\"satelliteid\")) {\n\t\t\tint satelliteId = nbttagcompound.getInteger(\"satelliteid\");\n\t\t\tsatellitePipeName = Integer.toString(satelliteId);\n\t\t} else {\n\t\t\tsatellitePipeName = nbttagcompound.getString(\"satellitePipeName\");\n\t\t}\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tensureAllSatelliteStatus();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tnbttagcompound.setString(\"satellitePipeName\", satellitePipeName);\n\t\tsuper.writeToNBT(nbttagcompound);\n\t}\n\n\tpublic void ensureAllSatelliteStatus() {\n\t\tif (satellitePipeName.isEmpty()) {\n\t\t\tPipeFluidSatellite.AllSatellites.remove(this);\n\t\t} else {\n\t\t\tPipeFluidSatellite.AllSatellites.add(this);\n\t\t}\n\t}\n\n\tpublic void updateWatchers() {\n\t\tfinal LogisticsTileGenericPipe container = Objects.requireNonNull(getContainer());\n\t\tCoordinatesPacket packet = PacketHandler.getPacket(SyncSatelliteNamePacket.class)\n\t\t\t\t.setString(satellitePipeName)\n\t\t\t\t.setTilePos(container);\n\t\tMainProxy.sendToPlayerList(packet, localModeWatchers);\n\t\tMainProxy.sendPacketToAllWatchingChunk(container, packet);\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tPipeFluidSatellite.AllSatellites.remove(this);\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\t// Send the satellite id when opening gui\n\t\tfinal ModernPacket packet = PacketHandler.getPacket(SyncSatelliteNamePacket.class).setString(satellitePipeName).setPosX(getX()).setPosY(getY()).setPosZ(getZ());\n\t\tMainProxy.sendPacketToPlayer(packet, entityplayer);\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_SatellitePipe_ID, getWorld(), getX(), getY(), getZ());\n\t}\n\n\t@Override\n\tpublic void throttledUpdateEntity() {\n\t\tsuper.throttledUpdateEntity();\n\t\tif (_lostItems.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tfinal Iterator<Entry<FluidIdentifier, Integer>> iterator = _lostItems.entrySet().iterator();\n\t\twhile (iterator.hasNext()) {\n\t\t\tEntry<FluidIdentifier, Integer> stack = iterator.next();\n\t\t\tint received = RequestTree.requestFluidPartial(stack.getKey(), stack.getValue(), this, null);\n\n\t\t\tif (received > 0) {\n\t\t\t\tif (received == stack.getValue()) {\n\t\t\t\t\titerator.remove();\n\t\t\t\t} else {\n\t\t\t\t\tstack.setValue(stack.getValue() - received);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void liquidLost(FluidIdentifier item, int amount) {\n\t\tif (_lostItems.containsKey(item)) {\n\t\t\t_lostItems.put(item, _lostItems.get(item) + amount);\n\t\t} else {\n\t\t\t_lostItems.put(item, amount);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void liquidArrived(FluidIdentifier item, int amount) {}\n\n\t@Override\n\tpublic void liquidNotInserted(FluidIdentifier item, int amount) {\n\t\tliquidLost(item, amount);\n\t}\n\n\t@Override\n\tpublic boolean canReceiveFluid() {\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Set<SatellitePipe> getSatellitesOfType() {\n\t\treturn Collections.unmodifiableSet(AllSatellites);\n\t}\n\n\t@Override\n\tpublic void setSatellitePipeName(@Nonnull String satellitePipeName) {\n\t\tthis.satellitePipeName = satellitePipeName;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<ItemIdentifierStack> getItemList() {\n\t\treturn itemList;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeFluidSupplierMk2.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport net.minecraftforge.fluids.FluidTank;\n\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.interfaces.routing.IRequireReliableFluidTransport;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.FluidSupplierAmount;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class PipeFluidSupplierMk2 extends FluidRoutedPipe implements IRequestFluid, IRequireReliableFluidTransport {\n\n\tprivate boolean _lastRequestFailed = false;\n\n\tpublic enum MinMode {\n\t\tNONE(0),\n\t\tONEBUCKET(1000),\n\t\tTWOBUCKET(2000),\n\t\tFIVEBUCKET(5000);\n\n\t\t@Getter\n\t\tprivate final int amount;\n\n\t\tMinMode(int amount) {\n\t\t\tthis.amount = amount;\n\t\t}\n\t}\n\n\tpublic PipeFluidSupplierMk2(Item item) {\n\t\tsuper(item);\n\t\tthrottleTime = 100;\n\t}\n\n\t@Override\n\tpublic void sendFailed(FluidIdentifier value1, Integer value2) {\n\t\tliquidLost(value1, value2);\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Fast;\n\t}\n\n\t@Override\n\tpublic boolean canInsertFromSideToTanks() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean canInsertToTanks() {\n\t\treturn true;\n\t}\n\n\t/* TRIGGER INTERFACE */\n\tpublic boolean isRequestFailed() {\n\t\treturn _lastRequestFailed;\n\t}\n\n\tpublic void setRequestFailed(boolean value) {\n\t\t_lastRequestFailed = value;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUIDSUPPLIER_MK2_TEXTURE;\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t//from PipeFluidSupplierMk2\n\tprivate ItemIdentifierInventory dummyInventory = new ItemIdentifierInventory(1, \"Fluid to keep stocked\", 127, true);\n\tprivate int amount = 0;\n\n\tprivate final Map<FluidIdentifier, Integer> _requestedItems = new HashMap<>();\n\n\tprivate boolean _requestPartials = false;\n\tprivate MinMode _bucketMinimum = MinMode.ONEBUCKET;\n\n\t@Override\n\tpublic void throttledUpdateEntity() {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tif (MainProxy.isClient(Objects.requireNonNull(container).getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tsuper.throttledUpdateEntity();\n\t\tif (dummyInventory.getIDStackInSlot(0) == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tPipeFluidUtil.INSTANCE.getAdjacentTanks(this, false).forEach(fluidHandlerDirectionPair -> {\n\t\t\tif (!fluidHandlerDirectionPair.getValue2().containsTanks()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t//How much do I want?\n\t\t\tMap<FluidIdentifier, Integer> wantFluids = new HashMap<>();\n\t\t\tItemIdentifierStack stack = dummyInventory.getIDStackInSlot(0);\n\t\t\tif (stack == null) return;\n\t\t\tFluidIdentifier fIdent = FluidIdentifier.get(stack.getItem());\n\t\t\twantFluids.put(fIdent, amount);\n\n\t\t\t//How much do I have?\n\t\t\tHashMap<FluidIdentifier, Integer> haveFluids = new HashMap<>();\n\n\t\t\t//Check what is inside the connected tank\n\t\t\tfluidHandlerDirectionPair.getValue2().tanks()\n\t\t\t\t\t.map(tank -> FluidIdentifierStack.getFromStack(tank.getContents()))\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.forEach(fluid -> haveFluids.merge(fluid.getFluid(), fluid.getAmount(), Integer::sum));\n\n\t\t\t//What does our sided internal tank have\n\t\t\tint directionOrdinal = fluidHandlerDirectionPair.getValue1().getDirection().ordinal();\n\t\t\tif (directionOrdinal < ((PipeFluidTransportLogistics) transport).sideTanks.length) {\n\t\t\t\tFluidTank sideTank = ((PipeFluidTransportLogistics) transport).sideTanks[directionOrdinal];\n\t\t\t\tif (sideTank != null && sideTank.getFluid() != null && wantFluids.containsKey(FluidIdentifier.get(sideTank.getFluid()))) {\n\t\t\t\t\thaveFluids.merge(FluidIdentifier.get(sideTank.getFluid()), sideTank.getFluid().amount, Integer::sum);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//What does our center internal tank have\n\t\t\tFluidTank centerTank = ((PipeFluidTransportLogistics) transport).internalTank;\n\t\t\tif (centerTank != null && centerTank.getFluid() != null && wantFluids.containsKey(FluidIdentifier.get(centerTank.getFluid()))) {\n\t\t\t\thaveFluids.merge(FluidIdentifier.get(centerTank.getFluid()), centerTank.getFluid().amount, Integer::sum);\n\t\t\t}\n\n\t\t\t//HashMap<Integer, Integer> needFluids = new HashMap<Integer, Integer>();\n\t\t\t//Reduce what I have and what have been requested already\n\t\t\tfor (Entry<FluidIdentifier, Integer> liquidId : wantFluids.entrySet()) {\n\t\t\t\tInteger haveCount = haveFluids.get(liquidId.getKey());\n\t\t\t\tif (haveCount != null) {\n\t\t\t\t\tliquidId.setValue(liquidId.getValue() - haveCount);\n\t\t\t\t}\n\t\t\t\t//@formatter:off\n\t\t\t\t\t\t_requestedItems.entrySet().stream()\n\t\t\t\t\t\t\t\t.filter(requestedItem -> requestedItem.getKey().equals(liquidId.getKey()))\n\t\t\t\t\t\t\t\t.forEach(requestedItem -> liquidId.setValue(liquidId.getValue() - requestedItem.getValue()));\n\t\t\t\t\t\t//@formatter:on\n\t\t\t}\n\n\t\t\tsetRequestFailed(false);\n\n\t\t\t//Make request\n\n\t\t\tfor (FluidIdentifier need : wantFluids.keySet()) {\n\t\t\t\tint countToRequest = wantFluids.get(need);\n\t\t\t\tif (countToRequest < 1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (_bucketMinimum.getAmount() != 0 && countToRequest < _bucketMinimum.getAmount()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!useEnergy(11)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tboolean success = false;\n\n\t\t\t\tif (_requestPartials) {\n\t\t\t\t\tcountToRequest = RequestTree.requestFluidPartial(need, countToRequest, this, null);\n\t\t\t\t\tif (countToRequest > 0) {\n\t\t\t\t\t\tsuccess = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsuccess = RequestTree.requestFluid(need, countToRequest, this, null);\n\t\t\t\t}\n\n\t\t\t\tif (success) {\n\t\t\t\t\tInteger currentRequest = _requestedItems.get(need);\n\t\t\t\t\tif (currentRequest == null) {\n\t\t\t\t\t\t_requestedItems.put(need, countToRequest);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_requestedItems.put(need, currentRequest + countToRequest);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsetRequestFailed(true);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tdummyInventory.readFromNBT(nbttagcompound, \"\");\n\t\t_requestPartials = nbttagcompound.getBoolean(\"requestpartials\");\n\t\tamount = nbttagcompound.getInteger(\"amount\");\n\t\t_bucketMinimum = MinMode.values()[nbttagcompound.getByte(\"_bucketMinimum\")];\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tdummyInventory.writeToNBT(nbttagcompound, \"\");\n\t\tnbttagcompound.setBoolean(\"requestpartials\", _requestPartials);\n\t\tnbttagcompound.setInteger(\"amount\", amount);\n\t\tnbttagcompound.setByte(\"_bucketMinimum\", (byte) _bucketMinimum.ordinal());\n\t}\n\n\tprivate void decreaseRequested(FluidIdentifier liquid, int remaining) {\n\t\t//see if we can get an exact match\n\t\tInteger count = _requestedItems.get(liquid);\n\t\tif (count != null) {\n\t\t\t_requestedItems.put(liquid, Math.max(0, count - remaining));\n\t\t\tremaining -= count;\n\t\t}\n\t\tif (remaining <= 0) {\n\t\t\treturn;\n\t\t}\n\t\t//still remaining... was from fuzzyMatch on a crafter\n\t\tfor (Entry<FluidIdentifier, Integer> e : _requestedItems.entrySet()) {\n\t\t\tif (e.getKey().equals(liquid)) {\n\t\t\t\tint expected = e.getValue();\n\t\t\t\te.setValue(Math.max(0, expected - remaining));\n\t\t\t\tremaining -= expected;\n\t\t\t}\n\t\t\tif (remaining <= 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t//we have no idea what this is, log it.\n\t\tdebug.log(\"liquid supplier got unexpected item \" + liquid.toString());\n\t}\n\n\t@Override\n\tpublic void liquidLost(FluidIdentifier item, int amount) {\n\t\tdecreaseRequested(item, amount);\n\t}\n\n\t@Override\n\tpublic void liquidArrived(FluidIdentifier item, int amount) {\n\t\tdecreaseRequested(item, amount);\n\t\tdelayThrottle();\n\t}\n\n\t@Override\n\tpublic void liquidNotInserted(FluidIdentifier item, int amount) {}\n\n\tpublic boolean isRequestingPartials() {\n\t\treturn _requestPartials;\n\t}\n\n\tpublic void setRequestingPartials(boolean value) {\n\t\t_requestPartials = value;\n\t}\n\n\tpublic MinMode getMinMode() {\n\t\treturn _bucketMinimum;\n\t}\n\n\tpublic void setMinMode(MinMode value) {\n\t\t_bucketMinimum = value;\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_FluidSupplier_MK2_ID, getWorld(), getX(), getY(), getZ());\n\t}\n\n\tpublic IInventory getDummyInventory() {\n\t\treturn dummyInventory;\n\t}\n\n\tpublic int getAmount() {\n\t\treturn amount;\n\t}\n\n\tpublic void setAmount(int amount) {\n\t\tif (MainProxy.isClient(Objects.requireNonNull(container).getWorld())) {\n\t\t\tthis.amount = amount;\n\t\t}\n\t}\n\n\tpublic void changeFluidAmount(int change, EntityPlayer player) {\n\t\tamount += change;\n\t\tif (amount <= 0) {\n\t\t\tamount = 0;\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(FluidSupplierAmount.class).setInteger(amount).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), player);\n\t}\n\n\t@Override\n\tpublic boolean canReceiveFluid() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsBasicLogistics.java",
    "content": "/*\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.Collection;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.PipeTransportLogistics;\nimport logisticspipes.utils.OrientationsUtil;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class PipeItemsBasicLogistics extends CoreRoutedPipe {\n\n\tprivate final ModuleItemSink itemSinkModule;\n\n\tpublic PipeItemsBasicLogistics(Item item) {\n\t\tsuper(new PipeTransportLogistics(true) {\n\n\t\t\t@Override\n\t\t\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing dir) {\n\t\t\t\tif (super.canPipeConnect(tile, dir)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (tile instanceof LogisticsSecurityTileEntity) {\n\t\t\t\t\tEnumFacing ori = OrientationsUtil.getOrientationOfTilewithTile(container, tile);\n\t\t\t\t\treturn ori != null && ori != EnumFacing.DOWN && ori != EnumFacing.UP;\n\t\t\t\t}\n\t\t\t\tif (tile instanceof LogisticsProgramCompilerTileEntity) {\n\t\t\t\t\tEnumFacing ori = OrientationsUtil.getOrientationOfTilewithTile(container, tile);\n\t\t\t\t\treturn ori != null && ori != EnumFacing.DOWN;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}, item);\n\t\titemSinkModule = new ModuleItemSink();\n\t\titemSinkModule.registerHandler(this, this);\n\t\titemSinkModule.registerPosition(LogisticsModule.ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Override\n\tpublic TextureType getNonRoutedTexture(EnumFacing connection) {\n\t\tif (isSecurityProvider(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_SECURITY_TEXTURE;\n\t\t}\n\t\treturn super.getNonRoutedTexture(connection);\n\t}\n\n\t@Override\n\tpublic boolean isLockedExit(EnumFacing orientation) {\n\t\tif (isPowerJunction(orientation) || isSecurityProvider(orientation)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn super.isLockedExit(orientation);\n\t}\n\n\tprivate boolean isPowerJunction(EnumFacing ori) {\n\t\tTileEntity tilePipe = container.getTile(ori);\n\t\tif (tilePipe == null || !container.canPipeConnect(tilePipe, ori)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn tilePipe instanceof LogisticsPowerJunctionTileEntity;\n\t}\n\n\tprivate boolean isSecurityProvider(EnumFacing ori) {\n\t\tTileEntity tilePipe = container.getTile(ori);\n\t\tif (tilePipe == null || !container.canPipeConnect(tilePipe, ori)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn tilePipe instanceof LogisticsSecurityTileEntity;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_TEXTURE;\n\t}\n\n\t@Override\n\tpublic @Nonnull ModuleItemSink getLogisticsModule() {\n\t\treturn itemSinkModule;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic void setTile(TileEntity tile) {\n\t\tsuper.setTile(tile);\n\t\titemSinkModule.registerPosition(ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tif (!itemSinkModule.isDefaultRoute()) {\n\t\t\titemSinkModule.collectSpecificInterests(itemIdentifiers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn itemSinkModule.isDefaultRoute();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsCraftingLogistics.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.Item;\n\nimport logisticspipes.gui.hud.HUDCrafting;\nimport logisticspipes.interfaces.IChangeListener;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.interfaces.IOrderManagerContentReceiver;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.interfaces.routing.IRequireReliableTransport;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.hud.HUDStartWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopWatchingPacket;\nimport logisticspipes.network.packets.orderer.OrdererManagerContent;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.signs.CraftingPipeSign;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.request.ICraftingTemplate;\nimport logisticspipes.request.IPromise;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.routing.order.LogisticsItemOrderManager;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.IHavePriority;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\n@CCType(name = \"LogisticsPipes:Crafting\")\npublic class PipeItemsCraftingLogistics extends CoreRoutedPipe implements ICraftItems, IRequireReliableTransport, IHeadUpDisplayRendererProvider, IChangeListener, IOrderManagerContentReceiver, IHavePriority {\n\n\tprotected final ModuleCrafter craftingModule;\n\n\tpublic final LinkedList<ItemIdentifierStack> oldList = new LinkedList<>();\n\tpublic final LinkedList<ItemIdentifierStack> displayList = new LinkedList<>();\n\tpublic final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final HUDCrafting HUD = new HUDCrafting(this);\n\n\tprivate boolean doContentUpdate = true;\n\n\tpublic PipeItemsCraftingLogistics(Item item) {\n\t\tsuper(item);\n\t\tcraftingModule = new ModuleCrafter();\n\t\tcraftingModule.registerHandler(this, this);\n\t\tcraftingModule.registerPosition(ModulePositionType.IN_PIPE, 0);\n\t\tthrottleTime = 40;\n\t\t_orderItemManager = new LogisticsItemOrderManager(this, this); // null by default when not needed\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\twhile (_orderItemManager.hasOrders(ResourceType.CRAFTING, ResourceType.EXTRA)) {\n\t\t\t_orderItemManager.sendFailed();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (doContentUpdate) {\n\t\t\tcheckContentUpdate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_CRAFTER_TEXTURE;\n\t}\n\n\t@Override\n\tpublic void canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filters) {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tcraftingModule.canProvide(tree, root, filters);\n\n\t}\n\n\t@Override\n\tpublic ICraftingTemplate addCrafting(IResource toCraft) {\n\n\t\tif (!isEnabled()) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn craftingModule.addCrafting(toCraft);\n\t}\n\n\t@Override\n\tpublic LogisticsOrder fullFill(LogisticsPromise promise, IRequestItems destination, IAdditionalTargetInformation info) {\n\t\treturn craftingModule.fullFill(promise, destination, info);\n\t}\n\n\t@Override\n\tpublic void registerExtras(IPromise promise) {\n\t\tcraftingModule.registerExtras(promise);\n\t}\n\n\t@Override\n\tpublic void getAllItems(Map<ItemIdentifier, Integer> list, List<IFilter> filters) {\n\t\tcraftingModule.getAllItems(list, filters);\n\t}\n\n\t@Override\n\tpublic boolean canCraft(IResource toCraft) {\n\t\treturn craftingModule.canCraft(toCraft);\n\t}\n\n\t@Override\n\t@Deprecated\n\tpublic List<ItemIdentifierStack> getCraftedItems() {\n\t\treturn craftingModule.getCraftedItems();\n\t}\n\n\t@Override\n\tpublic @Nonnull ModuleCrafter getLogisticsModule() {\n\t\treturn craftingModule;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic int getTodo() {\n\t\treturn _orderItemManager.totalAmountCountInAllOrders();\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tlocalModeWatchers.add(player);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OrdererManagerContent.class).setIdentList(oldList).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), player);\n\t\t\tcraftingModule.startWatching(player);\n\t\t} else {\n\t\t\tsuper.playerStartWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tsuper.playerStopWatching(player, mode);\n\t\tlocalModeWatchers.remove(player);\n\t\tcraftingModule.stopWatching(player);\n\t}\n\n\t@Override\n\tpublic void listenedChanged() {\n\t\tdoContentUpdate = true;\n\t}\n\n\tprivate void checkContentUpdate() {\n\t\tdoContentUpdate = false;\n\t\tLinkedList<ItemIdentifierStack> all = _orderItemManager.getContentList(getWorld());\n\t\tif (!oldList.equals(all)) {\n\t\t\toldList.clear();\n\t\t\toldList.addAll(all);\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(OrdererManagerContent.class).setIdentList(all).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), localModeWatchers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setOrderManagerContent(Collection<ItemIdentifierStack> list) {\n\t\tdisplayList.clear();\n\t\tdisplayList.addAll(list);\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic double getLoadFactor() {\n\t\treturn (_orderItemManager.totalAmountCountInAllOrders() + 63.0) / 64.0;\n\t}\n\n\t/* ComputerCraftCommands */\n\t@CCCommand(description = \"Imports the crafting recipe from the connected machine/crafter\")\n\t@CCQueued()\n\tpublic void reimport() {\n\t\tcraftingModule.importFromCraftingTable(null);\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tcraftingModule.collectSpecificInterests(itemIdentifiers);\n\t}\n\n\t@Override\n\tpublic int getPriority() {\n\t\treturn craftingModule.priority.getValue();\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tcraftingModule.itemArrived(item, info);\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tcraftingModule.itemLost(item, info);\n\t}\n\n\tpublic IInventory getDummyInventory() {\n\t\treturn craftingModule.dummyInventory;\n\t}\n\n\tpublic boolean hasCraftingSign() {\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (signItem[i] instanceof CraftingPipeSign) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsFirewall.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.BitSet;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.FireWallFlag;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class PipeItemsFirewall extends CoreRoutedPipe {\n\n\tpublic ItemIdentifierInventory inv = new ItemIdentifierInventory(6 * 6, \"Filter Inv\", 1);\n\tprivate boolean blockProvider = false;\n\tprivate boolean blockCrafter = false;\n\tprivate boolean blockSorting = false;\n\tprivate boolean blockPower = true;\n\tprivate boolean isBlocking = true;\n\tprivate IFilter filter = null;\n\n\tpublic PipeItemsFirewall(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_FIREWALL, getWorld(), getX(), getY(), getZ());\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(FireWallFlag.class).setFlags(getFlags()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), entityplayer);\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tinv.writeToNBT(nbttagcompound);\n\t\tnbttagcompound.setBoolean(\"blockProvider\", blockProvider);\n\t\tnbttagcompound.setBoolean(\"blockCrafer\", blockCrafter);\n\t\tnbttagcompound.setBoolean(\"blockSorting\", blockSorting);\n\t\tnbttagcompound.setBoolean(\"blockPower\", blockPower);\n\t\tnbttagcompound.setBoolean(\"isBlocking\", isBlocking);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tinv.readFromNBT(nbttagcompound);\n\t\tblockProvider = nbttagcompound.getBoolean(\"blockProvider\");\n\t\tblockCrafter = nbttagcompound.getBoolean(\"blockCrafer\");\n\t\tblockSorting = nbttagcompound.getBoolean(\"blockSorting\");\n\t\tif (nbttagcompound.hasKey(\"blockPower\")) {\n\t\t\tblockPower = nbttagcompound.getBoolean(\"blockPower\");\n\t\t}\n\t\tisBlocking = nbttagcompound.getBoolean(\"isBlocking\");\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_FIREWALL_TEXTURE;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\tpublic IFilter getFilter() {\n\t\tif (filter == null) {\n\t\t\tfilter = new IFilter() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isBlocked() {\n\t\t\t\t\treturn isBlocking;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isFilteredItem(ItemIdentifier item) {\n\t\t\t\t\treturn inv.containsUndamagedExcludeNBTItem(item.getIgnoringNBT().getUndamaged());\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean blockProvider() {\n\t\t\t\t\treturn blockProvider;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean blockCrafting() {\n\t\t\t\t\treturn blockCrafter;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean blockRouting() {\n\t\t\t\t\treturn blockSorting;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean blockPower() {\n\t\t\t\t\treturn blockPower;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic int hashCode() {\n\t\t\t\t\treturn PipeItemsFirewall.this.hashCode();\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic String toString() {\n\t\t\t\t\treturn super.toString() + \" (\" + PipeItemsFirewall.this.getX() + \", \" + PipeItemsFirewall.this.getY() + \", \" + PipeItemsFirewall.this.getZ() + \")\";\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic DoubleCoordinates getLPPosition() {\n\t\t\t\t\treturn PipeItemsFirewall.this.getLPPosition();\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isFilteredItem(IResource resultItem) {\n\t\t\t\t\tfor (Pair<ItemIdentifierStack, Integer> pair : inv) {\n\t\t\t\t\t\tItemIdentifierStack stack = pair.getValue1();\n\t\t\t\t\t\tif (stack != null && resultItem.matches(stack.getItem(), IResource.MatchSettings.NORMAL)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\treturn filter;\n\t}\n\n\tpublic boolean isBlockProvider() {\n\t\treturn blockProvider;\n\t}\n\n\tpublic void setBlockProvider(boolean blockProvider) {\n\t\tthis.blockProvider = blockProvider;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FireWallFlag.class).setFlags(getFlags()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\tpublic boolean isBlockCrafter() {\n\t\treturn blockCrafter;\n\t}\n\n\tpublic void setBlockCrafter(boolean blockCrafter) {\n\t\tthis.blockCrafter = blockCrafter;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FireWallFlag.class).setFlags(getFlags()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\tpublic boolean isBlockSorting() {\n\t\treturn blockSorting;\n\t}\n\n\tpublic void setBlockSorting(boolean blockSorting) {\n\t\tthis.blockSorting = blockSorting;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FireWallFlag.class).setFlags(getFlags()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\tpublic boolean isBlockPower() {\n\t\treturn blockPower;\n\t}\n\n\tpublic void setBlockPower(boolean blockPower) {\n\t\tthis.blockPower = blockPower;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FireWallFlag.class).setFlags(getFlags()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\tpublic boolean isBlocking() {\n\t\treturn isBlocking;\n\t}\n\n\tpublic void setBlocking(boolean isBlocking) {\n\t\tthis.isBlocking = isBlocking;\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(FireWallFlag.class).setFlags(getFlags()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\tprivate BitSet getFlags() {\n\t\tBitSet flags = new BitSet();\n\t\tflags.set(0, blockProvider);\n\t\tflags.set(1, blockCrafter);\n\t\tflags.set(2, blockSorting);\n\t\tflags.set(3, blockPower);\n\t\tflags.set(4, isBlocking);\n\t\treturn flags;\n\t}\n\n\tpublic void setFlags(BitSet flags) {\n\t\tblockProvider = flags.get(0);\n\t\tblockCrafter = flags.get(1);\n\t\tblockSorting = flags.get(2);\n\t\tblockPower = flags.get(3);\n\t\tisBlocking = flags.get(4);\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsFluidSupplier.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fluids.FluidStack;\nimport net.minecraftforge.fluids.FluidUtil;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITankUtil;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.interfaces.routing.IRequireReliableTransport;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.transport.PipeTransportLogistics;\nimport logisticspipes.utils.CacheHolder.CacheTypes;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\npublic class PipeItemsFluidSupplier extends CoreRoutedPipe implements IRequestItems, IRequireReliableTransport {\n\n\tprivate boolean _lastRequestFailed = false;\n\tprivate boolean _requestPartials = false;\n\n\tprivate ItemIdentifierInventory dummyInventory = new ItemIdentifierInventory(9, \"Fluids to keep stocked\", 127);\n\n\tprivate final HashMap<ItemIdentifier, Integer> _requestedItems = new HashMap<>();\n\n\tpublic PipeItemsFluidSupplier(Item item) {\n\t\tsuper(new PipeTransportLogistics(true) {\n\n\t\t\t@Override\n\t\t\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing dir) {\n\t\t\t\tif (super.canPipeConnect(tile, dir)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tITankUtil tank = PipeFluidUtil.INSTANCE.getTankUtilForTE(tile, dir.getOpposite());\n\t\t\t\treturn tank != null && tank.containsTanks();\n\t\t\t}\n\t\t}, item);\n\n\t\tthrottleTime = 100;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_LIQUIDSUPPLIER_TEXTURE;\n\t}\n\n\t/* TRIGGER INTERFACE */\n\tpublic boolean isRequestFailed() {\n\t\treturn _lastRequestFailed;\n\t}\n\n\tpublic void setRequestFailed(boolean value) {\n\t\t_lastRequestFailed = value;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Fast;\n\t}\n\n\tpublic void endReached(LPTravelingItemServer data, TileEntity tile) {\n\t\tgetCacheHolder().trigger(CacheTypes.Inventory);\n\t\ttransport.markChunkModified(tile);\n\t\tnotifyOfItemArival(data.getInfo());\n\t\tEnumFacing orientation = data.output.getOpposite();\n\t\tif (getOriginalUpgradeManager().hasSneakyUpgrade()) {\n\t\t\torientation = getOriginalUpgradeManager().getSneakyOrientation();\n\t\t}\n\t\tITankUtil util = PipeFluidUtil.INSTANCE.getTankUtilForTE(tile, orientation);\n\t\tif (util == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\treturn;\n\t\t}\n\t\tfinal ItemIdentifierStack idStack = data.getItemIdentifierStack();\n\t\tif (idStack == null) {\n\t\t\treturn;\n\t\t}\n\t\tFluidIdentifierStack liquidId = FluidIdentifierStack.getFromStack(FluidUtil.getFluidContained(idStack.makeNormalStack()));\n\t\tif (liquidId == null) {\n\t\t\treturn;\n\t\t}\n\t\twhile (idStack.getStackSize() > 0 && util.fill(liquidId, false) == liquidId.getAmount() && this.useEnergy(5)) {\n\t\t\tutil.fill(liquidId, true);\n\t\t\tidStack.lowerStackSize(1);\n\t\t\tItem item = idStack.getItem().item;\n\t\t\tif (item.hasContainerItem(idStack.makeNormalStack())) {\n\t\t\t\tItem containerItem = Objects.requireNonNull(item.getContainerItem());\n\t\t\t\ttransport.sendItem(new ItemStack(containerItem, 1));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void throttledUpdateEntity() {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tsuper.throttledUpdateEntity();\n\n\t\tfor (NeighborTileEntity<TileEntity> neighbor : getAdjacent().fluidTanks()) {\n\t\t\tfinal ITankUtil tankUtil = LPNeighborTileEntityKt.getTankUtil(neighbor);\n\t\t\tif (tankUtil == null || !tankUtil.containsTanks()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//How much do I want?\n\t\t\tMap<ItemIdentifier, Integer> wantContainers = dummyInventory.getItemsAndCount();\n\t\t\tHashMap<FluidIdentifier, Integer> wantFluids = new HashMap<>();\n\t\t\tfor (Entry<ItemIdentifier, Integer> item : wantContainers.entrySet()) {\n\t\t\t\tItemStack wantItem = item.getKey().unsafeMakeNormalStack(1);\n\t\t\t\tFluidStack liquidStack = FluidUtil.getFluidContained(wantItem);\n\t\t\t\tif (liquidStack == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\twantFluids.put(FluidIdentifier.get(liquidStack), item.getValue() * liquidStack.amount);\n\t\t\t}\n\n\t\t\t//How much do I have?\n\t\t\tHashMap<FluidIdentifier, Integer> haveFluids = new HashMap<>();\n\n\t\t\ttankUtil.tanks()\n\t\t\t\t\t.map(tank -> FluidIdentifierStack.getFromStack(tank.getContents()))\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.forEach(fluid -> {\n\t\t\t\t\t\tif (wantFluids.containsKey(fluid.getFluid())) {\n\t\t\t\t\t\t\thaveFluids.merge(fluid.getFluid(), fluid.getAmount(), Integer::sum);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t//HashMap<Integer, Integer> needFluids = new HashMap<Integer, Integer>();\n\t\t\t//Reduce what I have and what have been requested already\n\t\t\tfor (Entry<FluidIdentifier, Integer> liquidId : wantFluids.entrySet()) {\n\t\t\t\tInteger haveCount = haveFluids.get(liquidId.getKey());\n\t\t\t\tif (haveCount != null) {\n\t\t\t\t\tliquidId.setValue(liquidId.getValue() - haveCount);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (Entry<ItemIdentifier, Integer> requestedItem : _requestedItems.entrySet()) {\n\t\t\t\tItemStack wantItem = requestedItem.getKey().unsafeMakeNormalStack(1);\n\t\t\t\tFluidStack requestedFluidId = FluidUtil.getFluidContained(wantItem);\n\t\t\t\tif (requestedFluidId == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tFluidIdentifier requestedFluid = FluidIdentifier.get(requestedFluidId);\n\t\t\t\tInteger want = wantFluids.get(requestedFluid);\n\t\t\t\tif (want != null) {\n\t\t\t\t\twantFluids.put(requestedFluid, want - requestedItem.getValue() * requestedFluidId.amount);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t((PipeItemsFluidSupplier) Objects.requireNonNull(container).pipe).setRequestFailed(false);\n\n\t\t\t//Make request\n\n\t\t\tfor (ItemIdentifier need : wantContainers.keySet()) {\n\t\t\t\tFluidStack requestedFluidId = FluidUtil.getFluidContained(need.unsafeMakeNormalStack(1));\n\t\t\t\tif (requestedFluidId == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!wantFluids.containsKey(FluidIdentifier.get(requestedFluidId))) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tint countToRequest = wantFluids.get(FluidIdentifier.get(requestedFluidId)) / requestedFluidId.amount;\n\t\t\t\tif (countToRequest < 1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!useEnergy(11)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tboolean success = false;\n\n\t\t\t\tif (_requestPartials) {\n\t\t\t\t\tcountToRequest = RequestTree.requestPartial(need.makeStack(countToRequest), (IRequestItems) container.pipe, null);\n\t\t\t\t\tif (countToRequest > 0) {\n\t\t\t\t\t\tsuccess = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsuccess = RequestTree.request(need.makeStack(countToRequest), (IRequestItems) container.pipe, null, null);\n\t\t\t\t}\n\n\t\t\t\tif (success) {\n\t\t\t\t\tInteger currentRequest = _requestedItems.get(need);\n\t\t\t\t\tif (currentRequest == null) {\n\t\t\t\t\t\t_requestedItems.put(need, countToRequest);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_requestedItems.put(need, currentRequest + countToRequest);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t((PipeItemsFluidSupplier) container.pipe).setRequestFailed(true);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tdummyInventory.readFromNBT(nbttagcompound, \"\");\n\t\t_requestPartials = nbttagcompound.getBoolean(\"requestpartials\");\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tdummyInventory.writeToNBT(nbttagcompound, \"\");\n\t\tnbttagcompound.setBoolean(\"requestpartials\", _requestPartials);\n\t}\n\n\tprivate void decreaseRequested(ItemIdentifierStack item) {\n\t\tint remaining = item.getStackSize();\n\t\t//see if we can get an exact match\n\t\tInteger count = _requestedItems.get(item.getItem());\n\t\tif (count != null) {\n\t\t\t_requestedItems.put(item.getItem(), Math.max(0, count - remaining));\n\t\t\tremaining -= count;\n\t\t}\n\t\tif (remaining <= 0) {\n\t\t\treturn;\n\t\t}\n\t\t//still remaining... was from fuzzyMatch on a crafter\n\t\tfor (Entry<ItemIdentifier, Integer> e : _requestedItems.entrySet()) {\n\t\t\tif (e.getKey().item == item.getItem().item && e.getKey().itemDamage == item.getItem().itemDamage) {\n\t\t\t\tint expected = e.getValue();\n\t\t\t\te.setValue(Math.max(0, expected - remaining));\n\t\t\t\tremaining -= expected;\n\t\t\t}\n\t\t\tif (remaining <= 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t//we have no idea what this is, log it.\n\t\tdebug.log(\"liquid supplier got unexpected item \" + item);\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tdecreaseRequested(item);\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tdecreaseRequested(item);\n\t\tdelayThrottle();\n\t}\n\n\tpublic boolean isRequestingPartials() {\n\t\treturn _requestPartials;\n\t}\n\n\tpublic void setRequestingPartials(boolean value) {\n\t\t_requestPartials = value;\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_FluidSupplier_ID, getWorld(), getX(), getY(), getZ());\n\t}\n\n\t/*** GUI ***/\n\tpublic IItemIdentifierInventory getDummyInventory() {\n\t\treturn dummyInventory;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsInvSysConnector.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.gui.hud.HUDInvSysConnector;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.IOrderManagerContentReceiver;\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.interfaces.routing.IChannelRoutingConnection;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.guis.pipe.InvSysConGuiProvider;\nimport logisticspipes.network.packets.gui.ChannelInformationPacket;\nimport logisticspipes.network.packets.hud.HUDStartWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopWatchingPacket;\nimport logisticspipes.network.packets.orderer.OrdererManagerContent;\nimport logisticspipes.network.packets.pipe.InvSysConResistance;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.TransportInvConnection;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.transactor.ITransactor;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\npublic class PipeItemsInvSysConnector extends CoreRoutedPipe implements IChannelRoutingConnection, IHeadUpDisplayRendererProvider, IOrderManagerContentReceiver,\n\t\tIGuiOpenControler {\n\n\tprivate boolean init = false;\n\tprivate HashMap<ItemIdentifier, List<ItemRoutingInformation>> itemsOnRoute = new HashMap<>();\n\tpublic int resistance;\n\tpublic Set<ItemIdentifierStack> oldList = new TreeSet<>();\n\tpublic final LinkedList<ItemIdentifierStack> displayList = new LinkedList<>();\n\tpublic final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tpublic final PlayerCollectionList localGuiWatchers = new PlayerCollectionList();\n\tprivate HUDInvSysConnector HUD = new HUDInvSysConnector(this);\n\tprivate UUID idBuffer = UUID.randomUUID();\n\n\tprivate UUID connectedChannel;\n\n\tpublic PipeItemsInvSysConnector(Item item) {\n\t\tsuper(new TransportInvConnection(), item);\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (!init) {\n\t\t\tif (hasConnectionUUID()) {\n\t\t\t\tif (!SimpleServiceLocator.connectionManager.addChannelConnection(getConnectionUUID(), getRouter())) {\n\t\t\t\t\tconnectedChannel = null;\n\t\t\t\t\tsendChannelInformationToPlayers();\n\t\t\t\t}\n\t\t\t\tList<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(getRouter());\n\t\t\t\tif (connectedPipes != null) {\n\t\t\t\t\tconnectedPipes.forEach(c -> {\n\t\t\t\t\t\tc.getRouter().update(true, c);\n\t\t\t\t\t\tc.refreshRender(true);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tgetRouter().update(true, this);\n\t\t\t\trefreshRender(true);\n\t\t\t\tinit = true;\n\t\t\t\tidBuffer = getConnectionUUID();\n\t\t\t}\n\t\t}\n\t\tif (init && !hasConnectionUUID()) {\n\t\t\tinit = false;\n\t\t\tList<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(getRouter());\n\t\t\tSimpleServiceLocator.connectionManager.removeChannelConnection(getRouter());\n\t\t\tif (connectedPipes != null) {\n\t\t\t\tconnectedPipes.forEach(c -> {\n\t\t\t\t\tc.getRouter().update(true, c);\n\t\t\t\t\tc.refreshRender(true);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tif (init && idBuffer != null && !idBuffer.equals(getConnectionUUID())) {\n\t\t\tinit = false;\n\t\t\tList<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(getRouter());\n\t\t\tSimpleServiceLocator.connectionManager.removeChannelConnection(getRouter());\n\t\t\tif (connectedPipes != null) {\n\t\t\t\tconnectedPipes.forEach(c -> {\n\t\t\t\t\tc.getRouter().update(true, c);\n\t\t\t\t\tc.refreshRender(true);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tif (itemsOnRoute.size() > 0) {\n\t\t\tcheckConnectedInvs();\n\t\t}\n\t}\n\n\tprivate void checkConnectedInvs() {\n\t\tif (!itemsOnRoute.isEmpty()) { // don't check the inventory if you don't want anything\n\t\t\tfinal boolean shouldUpdate = getAvailableAdjacent().inventories().stream()\n\t\t\t\t\t.anyMatch(neighbor -> {\n\t\t\t\t\t\tfinal IInventoryUtil invUtil = LPNeighborTileEntityKt.getInventoryUtil(neighbor);\n\t\t\t\t\t\treturn invUtil != null &&\n\t\t\t\t\t\t\t\tcontainer.canPipeConnect(neighbor.getTileEntity(), neighbor.getDirection()) &&\n\t\t\t\t\t\t\t\tcheckOneConnectedInv(invUtil, neighbor.getDirection());\n\t\t\t\t\t});\n\n\t\t\tif (shouldUpdate) updateContentListener();\n\t\t}\n\t}\n\n\tprivate boolean checkOneConnectedInv(@Nonnull IInventoryUtil inv, EnumFacing dir) {\n\t\tboolean contentChanged = false;\n\t\tif (!itemsOnRoute.isEmpty()) { // don't check the inventory if you don't want anything\n\t\t\tList<ItemIdentifier> items = new ArrayList<>(itemsOnRoute.keySet());\n\t\t\titems.retainAll(inv.getItems());\n\t\t\tMap<ItemIdentifier, Integer> amounts = null;\n\t\t\tif (!items.isEmpty()) {\n\t\t\t\tamounts = inv.getItemsAndCount();\n\t\t\t}\n\t\t\tfor (ItemIdentifier ident : items) {\n\t\t\t\tif (!amounts.containsKey(ident)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tint itemAmount = amounts.get(ident);\n\t\t\t\tList<ItemRoutingInformation> needs = itemsOnRoute.get(ident);\n\t\t\t\tfor (Iterator<ItemRoutingInformation> iterator = needs.iterator(); iterator.hasNext(); ) {\n\t\t\t\t\tItemRoutingInformation need = iterator.next();\n\t\t\t\t\tif (need.getItem().getStackSize() <= itemAmount) {\n\t\t\t\t\t\tif (!useEnergy(6)) {\n\t\t\t\t\t\t\treturn contentChanged;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tItemStack toSend = inv.getMultipleItems(ident, need.getItem().getStackSize());\n\t\t\t\t\t\tif (toSend.isEmpty()) {\n\t\t\t\t\t\t\treturn contentChanged;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (toSend.getCount() != need.getItem().getStackSize()) {\n\t\t\t\t\t\t\tif (inv instanceof ITransactor) {\n\t\t\t\t\t\t\t\t((ITransactor) inv).add(toSend, dir.getOpposite(), true);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcontainer.getWorld().spawnEntity(ItemIdentifierStack.getFromStack(toSend).makeEntityItem(getWorld(), container.getX(), container.getY(), container.getZ()));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tnew UnsupportedOperationException(\"The extracted amount didn't match the requested one. (\" + inv + \")\").printStackTrace();\n\t\t\t\t\t\t\treturn contentChanged;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsendStack(need, dir);\n\n\t\t\t\t\t\titerator.remove(); // finished with this need, we sent part of a stack, lets see if anyone where needs the current item type.\n\t\t\t\t\t\tcontentChanged = true;\n\t\t\t\t\t\tif (needs.isEmpty()) {\n\t\t\t\t\t\t\titemsOnRoute.remove(ident);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//Refresh Available Items\n\t\t\t\t\t\tamounts = inv.getItemsAndCount();\n\t\t\t\t\t\tif (amounts.containsKey(ident)) {\n\t\t\t\t\t\t\titemAmount = amounts.get(ident);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn contentChanged;\n\t}\n\n\tpublic void sendStack(ItemRoutingInformation info, EnumFacing dir) {\n\t\tIRoutedItem itemToSend = SimpleServiceLocator.routedItemHelper.createNewTravelItem(info);\n\t\tsuper.queueRoutedItem(itemToSend, dir);\n\t\tspawnParticle(Particles.OrangeParticle, 4);\n\t}\n\n\tprivate static UUID testUUID = UUID.randomUUID();\n\n\tprivate UUID getConnectionUUID() {\n\t\treturn connectedChannel;\n\t}\n\n\tprivate boolean hasConnectionUUID() {\n\t\treturn connectedChannel != null;\n\t}\n\n\tpublic Set<ItemIdentifierStack> getExpectedItems() {\n\t\t// got to be a TreeMap, because a TreeSet doesn't have the ability to retrieve the key.\n\t\tSet<ItemIdentifierStack> list = new TreeSet<>();\n\t\tfor (Entry<ItemIdentifier, List<ItemRoutingInformation>> entry : itemsOnRoute.entrySet()) {\n\t\t\tif (entry.getValue().isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemIdentifierStack currentStack = new ItemIdentifierStack(entry.getKey(), 0);\n\t\t\tfor (ItemRoutingInformation e : entry.getValue()) {\n\t\t\t\tcurrentStack.setStackSize(currentStack.getStackSize() + e.getItem().getStackSize());\n\t\t\t}\n\t\t\tlist.add(currentStack);\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\tNewGuiHandler.getGui(InvSysConGuiProvider.class).setTilePos(this.container).open(entityplayer);\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tremovePipeFromChannel();\n\t}\n\n\tprivate void removePipeFromChannel() {\n\t\tif (!stillNeedReplace) {\n\t\t\tList<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(getRouter());\n\t\t\tSimpleServiceLocator.connectionManager.removeChannelConnection(getRouter());\n\t\t\tif (connectedPipes != null) {\n\t\t\t\tconnectedPipes.forEach(c -> c.refreshRender(true));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tremovePipeFromChannel();\n\t\tinit = false;\n\t\tsuper.invalidate();\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tremovePipeFromChannel();\n\t\tinit = false;\n\t\tsuper.onChunkUnload();\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tnbttagcompound.setInteger(\"resistance\", resistance);\n\t\tif (connectedChannel != null) {\n\t\t\tnbttagcompound.setString(\"connectedChannel\", connectedChannel.toString());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tresistance = nbttagcompound.getInteger(\"resistance\");\n\t\tif (nbttagcompound.hasKey(\"connectedChannel\")) {\n\t\t\tconnectedChannel = UUID.fromString(nbttagcompound.getString(\"connectedChannel\"));\n\t\t} else {\n\t\t\tconnectedChannel = null;\n\t\t}\n\t}\n\n\tprivate boolean hasRemoteConnection() {\n\t\treturn hasConnectionUUID() && getWorld() != null && SimpleServiceLocator.connectionManager.hasChannelConnection(getRouter());\n\t}\n\n\tprivate boolean isInventoryConnected(@Nullable TileEntity tileEntityFilter) {\n\t\treturn new WorldCoordinatesWrapper(this.container)\n\t\t\t\t.allNeighborTileEntities().stream()\n\t\t\t\t.anyMatch(neighbor -> (tileEntityFilter == null || neighbor.getTileEntity() == tileEntityFilter) &&\n\t\t\t\t\t\tneighbor.canHandleItems() &&\n\t\t\t\t\t\tthis.container.canPipeConnect(neighbor.getTileEntity(), neighbor.getDirection()));\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\tif (!stillNeedReplace && hasRemoteConnection()) {\n\t\t\tif (isInventoryConnected(null)) {\n\t\t\t\treturn Textures.LOGISTICSPIPE_INVSYSCON_CON_TEXTURE;\n\t\t\t} else {\n\t\t\t\treturn Textures.LOGISTICSPIPE_INVSYSCON_MIS_TEXTURE;\n\t\t\t}\n\t\t}\n\t\treturn Textures.LOGISTICSPIPE_INVSYSCON_DIS_TEXTURE;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Fast;\n\t}\n\n\t@Override\n\tpublic int getConnectionResistance() {\n\t\treturn resistance;\n\t}\n\n\t@Override\n\tpublic void addItem(ItemRoutingInformation info) {\n\t\tif (info.getItem() != null && info.getItem().getStackSize() > 0 && info.destinationint >= 0) {\n\t\t\tItemIdentifier insertedType = info.getItem().getItem();\n\t\t\tList<ItemRoutingInformation> entry = itemsOnRoute.computeIfAbsent(insertedType, k -> new LinkedList<>());\n\t\t\t// linked list as this is almost always very small, but experiences random removal\n\t\t\tentry.add(info);\n\t\t\tupdateContentListener();\n\t\t}\n\t}\n\n\tpublic void handleItemEnterInv(ItemRoutingInformation info, TileEntity tile) {\n\t\tif (info.getItem().getStackSize() == 0) {\n\t\t\treturn; // system.throw(\"why you try to insert empty stack?\");\n\t\t}\n\t\tif (info.destinationint < 0) {\n\t\t\treturn; // The item does not have a destination anymore, maybe the target pipe has been removed... We cannot do anything anymore so just let it be.\n\t\t}\n\t\tif (isInventoryConnected(tile)) {\n\t\t\tif (hasRemoteConnection()) {\n\t\t\t\tList<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(getRouter());\n\t\t\t\tOptional<CoreRoutedPipe> bestConnection = connectedPipes.stream()\n\t\t\t\t\t\t.map(con -> new Triplet<>(\n\t\t\t\t\t\t\t\tcon,\n\t\t\t\t\t\t\t\tcon.getRouter().getExitFor(info.destinationint, info._transportMode == IRoutedItem.TransportMode.Active, info.getItem().getItem()),\n\t\t\t\t\t\t\t\tcon.getRouter().getExitFor(getRouterId(), info._transportMode == IRoutedItem.TransportMode.Active, info.getItem().getItem())\n\t\t\t\t\t\t))\n\t\t\t\t\t\t.filter(triplet -> triplet.getValue2() != null && triplet.getValue3() != null)\n\t\t\t\t\t\t.filter(triplet -> triplet.getValue2().exitOrientation != triplet.getValue3().exitOrientation)\n\t\t\t\t\t\t.min(Comparator.comparing(trip -> trip.getValue2().blockDistance)).map(Pair::getValue1);\n\t\t\t\tif (!bestConnection.isPresent()) {\n\t\t\t\t\tbestConnection = connectedPipes.stream()\n\t\t\t\t\t\t\t.map(con -> new Pair<>(\n\t\t\t\t\t\t\t\t\tcon,\n\t\t\t\t\t\t\t\t\tcon.getRouter().getExitFor(info.destinationint, info._transportMode == IRoutedItem.TransportMode.Active, info.getItem().getItem())\n\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t.filter(triplet -> triplet.getValue2() != null)\n\t\t\t\t\t\t\t.min(Comparator.comparing(trip -> trip.getValue2().blockDistance)).map(Pair::getValue1);\n\t\t\t\t}\n\t\t\t\tif (bestConnection.isPresent() && bestConnection.get() instanceof IChannelRoutingConnection) {\n\t\t\t\t\tIChannelRoutingConnection pipe = (IChannelRoutingConnection) bestConnection.get();\n\t\t\t\t\tpipe.addItem(info);\n\t\t\t\t\tspawnParticle(Particles.OrangeParticle, 4);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\tprivate void updateContentListener() {\n\t\tif (!localModeWatchers.isEmpty()) {\n\t\t\tSet<ItemIdentifierStack> newList = getExpectedItems();\n\t\t\tif (!newList.equals(oldList)) {\n\t\t\t\toldList = newList;\n\t\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(OrdererManagerContent.class).setIdentSet(newList).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), localModeWatchers);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tlocalModeWatchers.add(player);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OrdererManagerContent.class).setIdentSet(getExpectedItems()).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), player);\n\t\t} else {\n\t\t\tsuper.playerStartWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tsuper.playerStopWatching(player, mode);\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void setOrderManagerContent(Collection<ItemIdentifierStack> list) {\n\t\tdisplayList.clear();\n\t\tdisplayList.addAll(list);\n\t}\n\n\tpublic void setChannelFromClient(UUID fromString) {\n\t\tthis.connectedChannel = fromString;\n\t\tsendChannelInformationToPlayers();\n\t}\n\n\t@Override\n\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\tlocalGuiWatchers.add(player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(InvSysConResistance.class).setInteger(this.resistance).setBlockPos(this.getPos()), player);\n\n\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(this.getWorld());\n\t\tOptional<ChannelInformation> channel = manager.getChannels().stream()\n\t\t\t\t.filter(chan -> chan.getChannelIdentifier().equals(getConnectionUUID()))\n\t\t\t\t.findFirst();\n\t\tchannel.ifPresent(chan -> MainProxy.sendPacketToPlayer(PacketHandler.getPacket(ChannelInformationPacket.class).setInformation(chan).setTargeted(true), player));\n\t}\n\n\t@Override\n\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\tlocalGuiWatchers.remove(player);\n\t}\n\n\tprivate void sendChannelInformationToPlayers() {\n\t\tIChannelManager manager = SimpleServiceLocator.channelManagerProvider.getChannelManager(this.getWorld());\n\t\tOptional<ChannelInformation> channel = manager.getChannels().stream()\n\t\t\t\t.filter(chan -> chan.getChannelIdentifier().equals(getConnectionUUID()))\n\t\t\t\t.findFirst();\n\t\tchannel.ifPresent(chan -> MainProxy.sendToPlayerList(PacketHandler.getPacket(ChannelInformationPacket.class).setInformation(chan).setTargeted(true), localGuiWatchers));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsProviderLogistics.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\n\nimport logisticspipes.gui.hud.HUDProvider;\nimport logisticspipes.interfaces.IChestContentReceiver;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.interfaces.IOrderManagerContentReceiver;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.hud.HUDStartWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopWatchingPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class PipeItemsProviderLogistics extends CoreRoutedPipe implements IProvideItems, IHeadUpDisplayRendererProvider, IChestContentReceiver, IOrderManagerContentReceiver {\n\n\tpublic final LinkedList<ItemIdentifierStack> itemListOrderer = new LinkedList<>();\n\tprivate final HUDProvider HUD = new HUDProvider(this);\n\n\t@Nonnull\n\tprotected final ModuleProvider providerModule = new ModuleProvider();\n\n\tpublic ArrayList<ItemIdentifierStack> getDisplayList() {\n\t\treturn providerModule.displayList;\n\t}\n\n\tpublic PipeItemsProviderLogistics(Item item) {\n\t\tsuper(item);\n\t\tproviderModule.registerHandler(this, this);\n\t\tproviderModule.registerPosition(LogisticsModule.ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tproviderModule.onBlockRemoval();\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_PROVIDER_TEXTURE;\n\t}\n\n\t@Override\n\tpublic void canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filters) {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tproviderModule.canProvide(tree, root, filters);\n\t}\n\n\t@Override\n\tpublic LogisticsOrder fullFill(LogisticsPromise promise, IRequestItems destination, IAdditionalTargetInformation info) {\n\t\treturn providerModule.fullFill(promise, destination, info);\n\t}\n\n\t@Override\n\tpublic void getAllItems(Map<ItemIdentifier, Integer> items, List<IFilter> filters) {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tproviderModule.getAllItems(items, filters);\n\t}\n\n\t@Override\n\tpublic @Nonnull ModuleProvider getLogisticsModule() {\n\t\treturn providerModule;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn providerModule.itemSendMode();\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(\n\t\t\t\tPacketHandler.getPacket(HUDStartWatchingPacket.class).setInteger(1 /*TODO*/).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopWatchingPacket.class).setInteger(1 /*TODO*/).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tproviderModule.startWatching(player);\n\t\t} else {\n\t\t\tsuper.playerStartWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tproviderModule.stopWatching(player);\n\t\t} else {\n\t\t\tsuper.playerStopWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setReceivedChestContent(Collection<ItemIdentifierStack> list) {\n\t\tproviderModule.displayList.clear();\n\t\tproviderModule.displayList.ensureCapacity(list.size());\n\t\tproviderModule.displayList.addAll(list);\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void setOrderManagerContent(Collection<ItemIdentifierStack> list) {\n\t\titemListOrderer.clear();\n\t\titemListOrderer.addAll(list);\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\tif (providerModule.isExclusionFilter.getValue() || providerModule.filterInventory.isEmpty()) {\n\t\t\titemIdentifiers.addAll(\n\t\t\t\t\tproviderModule.inventoriesWithMode()\n\t\t\t\t\t\t\t.flatMap(invUtil -> invUtil.getItems().stream())\n\t\t\t\t\t\t\t.filter(item -> !providerModule.filterBlocksItem(item))\n\t\t\t\t\t\t\t.collect(Collectors.toList()));\n\t\t} else {\n\t\t\tproviderModule.collectSpecificInterests(itemIdentifiers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic double getLoadFactor() {\n\t\treturn (_orderItemManager.totalAmountCountInAllOrders() + 63) / 64.0;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsRemoteOrdererLogistics.java",
    "content": "package logisticspipes.pipes;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.items.RemoteOrderer;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\n\npublic class PipeItemsRemoteOrdererLogistics extends CoreRoutedPipe implements IRequestItems {\n\n\tpublic PipeItemsRemoteOrdererLogistics(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_REMOTE_ORDERER_TEXTURE;\n\t}\n\n\t@Override\n\tpublic boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\tif (!entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).isEmpty() && entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).getItem() == LPItems.remoteOrderer) {\n\t\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\t\tif (settings == null || settings.openRequest) {\n\t\t\t\t\tItemStack orderer = entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND);\n\t\t\t\t\tRemoteOrderer.connectToPipe(orderer, this);\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.connectedtopipe\"));\n\t\t\t\t} else {\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsRequestLogistics.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.request.RequestHandler;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\n@CCType(name = \"LogisticsPipes:Request\")\npublic class PipeItemsRequestLogistics extends CoreRoutedPipe implements IRequestItems {\n\n\tprivate final LinkedList<Map<ItemIdentifier, Integer>> _history = new LinkedList<>();\n\n\tpublic PipeItemsRequestLogistics(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_REQUESTER_TEXTURE;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\tpublic void openGui(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Normal_Orderer_ID, getWorld(), getX(), getY(), getZ());\n\t}\n\n\t@Override\n\tpublic boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (settings == null || settings.openRequest) {\n\t\t\t\topenGui(entityplayer);\n\t\t\t} else {\n\t\t\t\tentityplayer.sendMessage(new TextComponentString(\"Permission denied\"));\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (getWorld().getTotalWorldTime() % 1200 == 0) {\n\t\t\t_history.addLast(SimpleServiceLocator.logisticsManager.getAvailableItems(getRouter().getIRoutersByCost()));\n\t\t\tif (_history.size() > 20) {\n\t\t\t\t_history.removeFirst();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@CCCommand(description = \"Requests the given ItemIdentifierStack\")\n\t@CCQueued\n\tpublic Object[] makeRequest(ItemIdentifierStack stack) throws Exception {\n\t\treturn makeRequest(stack.getItem(), Double.valueOf(stack.getStackSize()), false);\n\t}\n\n\t@CCCommand(description = \"Requests the given ItemIdentifierStack\")\n\t@CCQueued\n\tpublic Object[] makeRequest(ItemIdentifierStack stack, Boolean forceCrafting) throws Exception {\n\t\treturn makeRequest(stack.getItem(), Double.valueOf(stack.getStackSize()), forceCrafting);\n\t}\n\n\t@CCCommand(description = \"Requests the given ItemIdentifier with the given amount\")\n\t@CCQueued\n\tpublic Object[] makeRequest(ItemIdentifier item, Double amount) throws Exception {\n\t\treturn makeRequest(item, amount, false);\n\t}\n\n\t@CCCommand(description = \"Requests the given ItemIdentifier with the given amount\")\n\t@CCQueued\n\tpublic Object[] makeRequest(ItemIdentifier item, Double amount, Boolean forceCrafting) throws Exception {\n\t\tif (forceCrafting == null) {\n\t\t\tforceCrafting = false;\n\t\t}\n\t\tif (item == null) {\n\t\t\tthrow new Exception(\"Invalid ItemIdentifier\");\n\t\t}\n\t\treturn RequestHandler.computerRequest(item.makeStack((int) Math.floor(amount)), this, forceCrafting);\n\t}\n\n\t@CCCommand(description = \"Asks for all available ItemIdentifier inside the Logistics Network\")\n\t@CCQueued\n\tpublic List<Pair<ItemIdentifier, Integer>> getAvailableItems() {\n\t\tMap<ItemIdentifier, Integer> items = SimpleServiceLocator.logisticsManager.getAvailableItems(getRouter().getIRoutersByCost());\n\t\tList<Pair<ItemIdentifier, Integer>> list = new LinkedList<>();\n\t\tfor (Entry<ItemIdentifier, Integer> item : items.entrySet()) {\n\t\t\tint amount = item.getValue();\n\t\t\tlist.add(new Pair<>(item.getKey(), amount));\n\t\t}\n\t\treturn list;\n\t}\n\n\t@CCCommand(description = \"Asks for all craftable ItemIdentifier inside the Logistics Network\")\n\t@CCQueued\n\tpublic List<ItemIdentifier> getCraftableItems() {\n\t\treturn SimpleServiceLocator.logisticsManager.getCraftableItems(getRouter().getIRoutersByCost());\n\t}\n\n\t@CCCommand(description = \"Asks for the amount of an ItemIdentifier Id inside the Logistics Network\")\n\t@CCQueued\n\tpublic int getItemAmount(ItemIdentifier item) throws Exception {\n\t\tMap<ItemIdentifier, Integer> items = SimpleServiceLocator.logisticsManager.getAvailableItems(getRouter().getIRoutersByCost());\n\t\tif (item == null) {\n\t\t\tthrow new Exception(\"Invalid ItemIdentifierID\");\n\t\t}\n\t\tif (items.containsKey(item)) {\n\t\t\treturn items.get(item);\n\t\t}\n\t\treturn 0;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsRequestLogisticsMk2.java",
    "content": "package logisticspipes.pipes;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\n\npublic class PipeItemsRequestLogisticsMk2 extends PipeItemsRequestLogistics {\n\n\t@Nonnull\n\tprivate ItemStack disk = ItemStack.EMPTY;\n\n\tpublic PipeItemsRequestLogisticsMk2(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\t//allow using upgrade manager\n\t\tif (MainProxy.isPipeControllerEquipped(entityplayer) && !(entityplayer.isSneaking())) {\n\t\t\treturn false;\n\t\t}\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (settings == null || settings.openGui) {\n\t\t\t\topenGui(entityplayer);\n\t\t\t} else {\n\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void openGui(EntityPlayer entityplayer) {\n\t\tboolean flag = true;\n\t\tif (disk.isEmpty()) {\n\t\t\tif (!entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).isEmpty() && entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).getItem().equals(LPItems.disk)) {\n\t\t\t\tdisk = entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND);\n\t\t\t\tentityplayer.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, ItemStack.EMPTY);\n\t\t\t\tflag = false;\n\t\t\t}\n\t\t}\n\t\tif (flag) {\n\t\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Normal_Mk2_Orderer_ID, getWorld(), getX(), getY(), getZ());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tif (!disk.isEmpty()) {\n\t\t\tNBTTagCompound itemNBT = new NBTTagCompound();\n\t\t\tdisk.writeToNBT(itemNBT);\n\t\t\tnbttagcompound.setTag(\"Disk\", itemNBT);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tif (nbttagcompound.hasKey(\"Disk\")) {\n\t\t\tNBTTagCompound item = nbttagcompound.getCompoundTag(\"Disk\");\n\t\t\tdisk = ItemStackLoader.loadAndFixItemStackFromNBT(item);\n\t\t}\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_REQUESTERMK2_TEXTURE;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getDisk() {\n\t\treturn disk;\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tdropDisk();\n\t\t}\n\t}\n\n\tpublic void dropDisk() {\n\t\tif (!disk.isEmpty()) {\n\t\t\tEntityItem item = new EntityItem(getWorld(), getX(), getY(), getZ(), disk);\n\t\t\tgetWorld().spawnEntity(item);\n\t\t\tdisk = ItemStack.EMPTY;\n\t\t}\n\t}\n\n\tpublic void setDisk(@Nonnull ItemStack itemstack) {\n\t\tdisk = itemstack;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsSatelliteLogistics.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.WeakHashMap;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.gui.hud.HUDSatellite;\nimport logisticspipes.interfaces.IChestContentReceiver;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.interfaces.routing.IRequireReliableTransport;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleSatellite;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.hud.ChestContent;\nimport logisticspipes.network.packets.hud.HUDStartWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopWatchingPacket;\nimport logisticspipes.network.packets.satpipe.SyncSatelliteNamePacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.SatellitePipe;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\n\npublic class PipeItemsSatelliteLogistics extends CoreRoutedPipe implements IRequestItems, IRequireReliableTransport, IHeadUpDisplayRendererProvider, IChestContentReceiver, SatellitePipe {\n\n\tpublic static final Set<PipeItemsSatelliteLogistics> AllSatellites = Collections.newSetFromMap(new WeakHashMap<>());\n\n\t// called only on server shutdown\n\tpublic static void cleanup() {\n\t\tPipeItemsSatelliteLogistics.AllSatellites.clear();\n\t}\n\n\tpublic final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final LinkedList<ItemIdentifierStack> itemList = new LinkedList<>();\n\tprivate final HUDSatellite HUD = new HUDSatellite(this);\n\tprotected final LinkedList<ItemIdentifierStack> _lostItems = new LinkedList<>();\n\tprivate final ModuleSatellite moduleSatellite;\n\n\t@Getter\n\tprivate String satellitePipeName = \"\";\n\n\tpublic PipeItemsSatelliteLogistics(Item item) {\n\t\tsuper(item);\n\t\tthrottleTime = 40;\n\t\tmoduleSatellite = new ModuleSatellite();\n\t\tmoduleSatellite.registerHandler(this, this);\n\t\tmoduleSatellite.registerPosition(LogisticsModule.ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_SATELLITE_TEXTURE;\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (isNthTick(20) && localModeWatchers.size() > 0) {\n\t\t\tupdateInv(false);\n\t\t}\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn moduleSatellite;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\tprivate void addToList(ItemIdentifierStack stack) {\n\t\tfor (ItemIdentifierStack ident : itemList) {\n\t\t\tif (ident.getItem().equals(stack.getItem())) {\n\t\t\t\tident.setStackSize(ident.getStackSize() + stack.getStackSize());\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\titemList.addLast(stack);\n\t}\n\n\tprivate void updateInv(boolean force) {\n\t\tArrayList<ItemIdentifierStack> oldList = new ArrayList<>(itemList);\n\t\titemList.clear();\n\t\titemList.addAll(\n\t\t\t\tgetAvailableAdjacent().inventories().stream()\n\t\t\t\t\t\t.map(LPNeighborTileEntityKt::getInventoryUtil)\n\t\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t\t.flatMap(invUtil -> invUtil.getItemsAndCount().entrySet().stream().map(itemIdentifierAndCount -> new ItemIdentifierStack(itemIdentifierAndCount.getKey(), itemIdentifierAndCount.getValue())))\n\t\t\t\t\t\t.collect(Collectors.toList())\n\t\t);\n\t\tif (!oldList.equals(itemList) || force) {\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(ChestContent.class).setIdentList(itemList).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), localModeWatchers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tlocalModeWatchers.add(player);\n\t\t\tfinal ModernPacket packet = PacketHandler.getPacket(SyncSatelliteNamePacket.class).setString(satellitePipeName).setPosX(getX()).setPosY(getY()).setPosZ(getZ());\n\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\tupdateInv(true);\n\t\t} else {\n\t\t\tsuper.playerStartWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tsuper.playerStopWatching(player, mode);\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\t@Override\n\tpublic void setReceivedChestContent(Collection<ItemIdentifierStack> list) {\n\t\titemList.clear();\n\t\titemList.addAll(list);\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn HUD;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tif (nbttagcompound.hasKey(\"satelliteid\")) {\n\t\t\tint satelliteId = nbttagcompound.getInteger(\"satelliteid\");\n\t\t\tsatellitePipeName = Integer.toString(satelliteId);\n\t\t} else {\n\t\t\tsatellitePipeName = nbttagcompound.getString(\"satellitePipeName\");\n\t\t}\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tensureAllSatelliteStatus();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tnbttagcompound.setString(\"satellitePipeName\", satellitePipeName);\n\t\tsuper.writeToNBT(nbttagcompound);\n\t}\n\n\tpublic void ensureAllSatelliteStatus() {\n\t\tif (satellitePipeName.isEmpty()) {\n\t\t\tPipeItemsSatelliteLogistics.AllSatellites.remove(this);\n\t\t}\n\t\tif (!satellitePipeName.isEmpty()) {\n\t\t\tPipeItemsSatelliteLogistics.AllSatellites.add(this);\n\t\t}\n\t}\n\n\tpublic void updateWatchers() {\n\t\tCoordinatesPacket packet = PacketHandler.getPacket(SyncSatelliteNamePacket.class).setString(satellitePipeName).setTilePos(this.getContainer());\n\t\tMainProxy.sendToPlayerList(packet, localModeWatchers);\n\t\tMainProxy.sendPacketToAllWatchingChunk(this.getContainer(), packet);\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tPipeItemsSatelliteLogistics.AllSatellites.remove(this);\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\t// Send the satellite id when opening gui\n\t\tfinal ModernPacket packet = PacketHandler.getPacket(SyncSatelliteNamePacket.class).setString(satellitePipeName).setPosX(getX()).setPosY(getY()).setPosZ(getZ());\n\t\tMainProxy.sendPacketToPlayer(packet, entityplayer);\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_SatellitePipe_ID, getWorld(), getX(), getY(), getZ());\n\t}\n\n\t@Override\n\tpublic void throttledUpdateEntity() {\n\t\tsuper.throttledUpdateEntity();\n\t\tif (_lostItems.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tfinal Iterator<ItemIdentifierStack> iterator = _lostItems.iterator();\n\t\twhile (iterator.hasNext()) {\n\t\t\tItemIdentifierStack stack = iterator.next();\n\t\t\tint received = RequestTree.requestPartial(stack, (CoreRoutedPipe) container.pipe, null);\n\t\t\tif (received > 0) {\n\t\t\t\tif (received == stack.getStackSize()) {\n\t\t\t\t\titerator.remove();\n\t\t\t\t} else {\n\t\t\t\t\tstack.setStackSize(stack.getStackSize() - received);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\t_lostItems.add(item);\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Set<SatellitePipe> getSatellitesOfType() {\n\t\treturn Collections.unmodifiableSet(AllSatellites);\n\t}\n\n\t@Override\n\tpublic void setSatellitePipeName(@Nonnull String satellitePipeName) {\n\t\tthis.satellitePipeName = satellitePipeName;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<ItemIdentifierStack> getItemList() {\n\t\treturn itemList;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsSupplierLogistics.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.Item;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.interfaces.routing.IRequireReliableTransport;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.debug.StatusEntry;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class PipeItemsSupplierLogistics extends CoreRoutedPipe implements IRequestItems, IRequireReliableTransport {\n\n\tprivate final ModuleActiveSupplier supplierModule;\n\n\tpublic PipeItemsSupplierLogistics(Item item) {\n\t\tsuper(item);\n\t\tsupplierModule = new ModuleActiveSupplier();\n\t\tsupplierModule.registerHandler(this, this);\n\t\tsupplierModule.registerPosition(ModulePositionType.IN_PIPE, 0);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_SUPPLIER_TEXTURE;\n\t}\n\n\t/* TRIGGER INTERFACE */\n\tpublic boolean isRequestFailed() {\n\t\treturn supplierModule.isRequestFailed();\n\t}\n\n\t@Override\n\tpublic @Nonnull ModuleActiveSupplier getLogisticsModule() {\n\t\treturn supplierModule;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tsupplierModule.itemLost(item, info);\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tsupplierModule.itemArrived(item, info);\n\t}\n\n\t@Override\n\tpublic void addStatusInformation(List<StatusEntry> status) {\n\t\tsuper.addStatusInformation(status);\n\t\tsupplierModule.addStatusInformation(status);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsSystemDestinationLogistics.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.Objects;\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class PipeItemsSystemDestinationLogistics extends CoreRoutedPipe {\n\n\tpublic ItemIdentifierInventory inv = new ItemIdentifierInventory(1, \"Freq Slot\", 1);\n\n\tpublic PipeItemsSystemDestinationLogistics(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_DESTINATION_TEXTURE;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\tpublic Object getTargetUUID() {\n\t\tfinal ItemIdentifierStack itemIdent = inv.getIDStackInSlot(0);\n\t\tif (itemIdent == null) {\n\t\t\treturn null;\n\t\t}\n\t\tfinal ItemStack stack = itemIdent.makeNormalStack();\n\t\tif (!stack.hasTagCompound()) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!Objects.requireNonNull(stack.getTagCompound()).hasKey(\"UUID\")) {\n\t\t\treturn null;\n\t\t}\n\t\tspawnParticle(Particles.WhiteParticle, 2);\n\t\treturn UUID.fromString(stack.getTagCompound().getString(\"UUID\"));\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tdropFreqCard();\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tinv.writeToNBT(nbttagcompound);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tinv.readFromNBT(nbttagcompound);\n\t}\n\n\tprivate void dropFreqCard() {\n\t\tfinal ItemIdentifierStack itemident = inv.getIDStackInSlot(0);\n\t\tif (itemident == null) {\n\t\t\treturn;\n\t\t}\n\t\tEntityItem item = new EntityItem(getWorld(), getX(), getY(), getZ(), itemident.makeNormalStack());\n\t\tgetWorld().spawnEntity(item);\n\t\tinv.clearInventorySlotContents(0);\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Freq_Card_ID, getWorld(), getX(), getY(), getZ());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeItemsSystemEntranceLogistics.java",
    "content": "package logisticspipes.pipes;\n\nimport java.util.UUID;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.EntrencsTransport;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\npublic class PipeItemsSystemEntranceLogistics extends CoreRoutedPipe {\n\n\tpublic ItemIdentifierInventory inv = new ItemIdentifierInventory(1, \"Freq Slot\", 1);\n\n\tpublic PipeItemsSystemEntranceLogistics(Item item) {\n\t\tsuper(new EntrencsTransport(), item);\n\t\t((EntrencsTransport) transport).pipe = this;\n\t}\n\n\tpublic UUID getLocalFreqUUID() {\n\t\tif (inv.getStackInSlot(0) == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!inv.getStackInSlot(0).hasTagCompound()) {\n\t\t\treturn null;\n\t\t}\n\t\tif (!inv.getStackInSlot(0).getTagCompound().hasKey(\"UUID\")) {\n\t\t\treturn null;\n\t\t}\n\t\tspawnParticle(Particles.WhiteParticle, 2);\n\t\treturn UUID.fromString(inv.getStackInSlot(0).getTagCompound().getString(\"UUID\"));\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_ENTRANCE_TEXTURE;\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\t\tinv.writeToNBT(nbttagcompound);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\t\tinv.readFromNBT(nbttagcompound);\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\tdropFreqCard();\n\t}\n\n\tprivate void dropFreqCard() {\n\t\tif (inv.getStackInSlot(0) == null) {\n\t\t\treturn;\n\t\t}\n\t\tEntityItem item = new EntityItem(getWorld(), getX(), getY(), getZ(), inv.getStackInSlot(0));\n\t\tgetWorld().spawnEntity(item);\n\t\tinv.clearInventorySlotContents(0);\n\t}\n\n\t@Override\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Freq_Card_ID, getWorld(), getX(), getY(), getZ());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeLogisticsChassis.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes;\n\nimport java.util.*;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.config.Configs;\nimport logisticspipes.gui.GuiChassisPipe;\nimport logisticspipes.gui.hud.HudChassisPipe;\nimport logisticspipes.interfaces.*;\nimport logisticspipes.interfaces.routing.*;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.logisticspipes.ChassisTransportLayer;\nimport logisticspipes.logisticspipes.ItemModuleInformationManager;\nimport logisticspipes.logisticspipes.TransportLayer;\nimport logisticspipes.modules.ChassisModule;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.hud.HUDStartWatchingPacket;\nimport logisticspipes.network.packets.hud.HUDStopWatchingPacket;\nimport logisticspipes.network.packets.pipe.ChassisOrientationPacket;\nimport logisticspipes.network.packets.pipe.ChassisPipeModuleContent;\nimport logisticspipes.network.packets.pipe.RequestChassisOrientationPacket;\nimport logisticspipes.network.packets.pipe.SendQueueContent;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.upgrades.ModuleUpgradeManager;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.request.ICraftingTemplate;\nimport logisticspipes.request.IPromise;\nimport logisticspipes.request.RequestTree;\nimport logisticspipes.request.RequestTreeNode;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.routing.order.LogisticsItemOrder;\nimport logisticspipes.routing.order.LogisticsOrder;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.ticks.HudUpdateTick;\nimport logisticspipes.utils.EnumFacingUtil;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.*;\nimport network.rs485.logisticspipes.module.PipeServiceProviderUtilKt;\nimport network.rs485.logisticspipes.pipes.IChassisPipe;\nimport network.rs485.logisticspipes.property.AdjacentProperty;\nimport network.rs485.logisticspipes.property.Property;\nimport network.rs485.logisticspipes.property.PropertyHolder;\nimport network.rs485.logisticspipes.property.SlottedModule;\n\n@CCType(name = \"LogisticsChassiePipe\")\npublic abstract class PipeLogisticsChassis extends CoreRoutedPipe\n\t\timplements ICraftItems, IBufferItems, ISimpleInventoryEventHandler, ISendRoutedItem, IProvideItems,\n\t\tIHeadUpDisplayRendererProvider, ISendQueueContentRecieiver, IChassisPipe, PropertyHolder {\n\n\tprivate final ChassisModule _module;\n\t// FIXME: remove after 1.12\n\tprivate final ItemIdentifierInventory _moduleInventory;\n\tprivate boolean init = false;\n\n\t// HUD\n\tpublic final LinkedList<ItemIdentifierStack> displayList = new LinkedList<>();\n\tpublic final PlayerCollectionList localModeWatchers = new PlayerCollectionList();\n\tprivate final HudChassisPipe hud;\n\n\t@Nonnull\n\tprivate final AdjacentProperty pointedAdjacentProperty = new AdjacentProperty(this, \"pointedAdjacent\");\n\n\tprivate final List<Property<?>> properties = Collections.singletonList(pointedAdjacentProperty);\n\n\tpublic PipeLogisticsChassis(Item item) {\n\t\tsuper(item);\n\t\t_moduleInventory = new ItemIdentifierInventory(getChassisSize(), \"Chassis pipe\", 1);\n\t\t_moduleInventory.addListener(this);\n\t\t_module = new ChassisModule(getChassisSize(), this);\n\t\t_module.registerHandler(this, this);\n\t\thud = new HudChassisPipe(this, _moduleInventory);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<Property<?>> getProperties() {\n\t\treturn properties;\n\t}\n\n\t/**\n\t * Returns the pointed adjacent EnumFacing or null, if this chassis does not have an attached inventory.\n\t */\n\t@Nullable\n\t@Override\n\tpublic EnumFacing getPointedOrientation() {\n\t\treturn pointedAdjacentProperty.getDirectionOrNull();\n\t}\n\n\t/**\n\t * Returns just the adjacent this chassis points at or no adjacent.\n\t */\n\t@Nonnull\n\t@Override\n\tpublic Adjacent getAvailableAdjacent() {\n\t\treturn pointedAdjacentProperty.getValue();\n\t}\n\n\t/**\n\t * Updates pointedAdjacent on {@link CoreRoutedPipe}.\n\t */\n\t@Override\n\tprotected void updateAdjacentCache() {\n\t\tsuper.updateAdjacentCache();\n\t\tfinal Adjacent adjacent = getAdjacent();\n\t\tif (adjacent instanceof SingleAdjacent) {\n\t\t\tpointedAdjacentProperty.setValue(adjacent);\n\t\t} else {\n\t\t\tfinal @Nullable EnumFacing oldPointedDirection = pointedAdjacentProperty.getDirectionOrNull();\n\t\t\tSingleAdjacent newPointedAdjacent = null;\n\t\t\tif (oldPointedDirection != null) {\n\t\t\t\t// update pointed adjacent with connection type or reset it\n\t\t\t\tnewPointedAdjacent = adjacent.optionalGet(oldPointedDirection)\n\t\t\t\t\t.map(connectionType -> new SingleAdjacent(this, oldPointedDirection, connectionType))\n\t\t\t\t\t.orElse(null);\n\t\t\t}\n\t\t\tif (newPointedAdjacent == null) {\n\t\t\t\tnewPointedAdjacent = adjacent.neighbors().entrySet().stream().findAny()\n\t\t\t\t\t.map(connectedNeighbor -> new SingleAdjacent(this, connectedNeighbor.getKey().getDirection(), connectedNeighbor.getValue()))\n\t\t\t\t\t.orElse(null);\n\t\t\t}\n\t\t\tif (newPointedAdjacent == null) {\n\t\t\t\tpointedAdjacentProperty.setValue(NoAdjacent.INSTANCE);\n\t\t\t} else {\n\t\t\t\tpointedAdjacentProperty.setValue(newPointedAdjacent);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Nullable\n\tprivate Pair<NeighborTileEntity<TileEntity>, ConnectionType> nextPointedOrientation(@Nullable EnumFacing previousDirection) {\n\t\tfinal Map<NeighborTileEntity<TileEntity>, ConnectionType> neighbors = getAdjacent().neighbors();\n\t\tfinal Stream<NeighborTileEntity<TileEntity>> sortedNeighborsStream = neighbors.keySet().stream()\n\t\t\t\t.sorted(Comparator.comparingInt(n -> n.getDirection().ordinal()));\n\t\tif (previousDirection == null) {\n\t\t\treturn sortedNeighborsStream.findFirst().map(neighbor -> new Pair<>(neighbor, neighbors.get(neighbor))).orElse(null);\n\t\t} else {\n\t\t\tfinal List<NeighborTileEntity<TileEntity>> sortedNeighbors = sortedNeighborsStream.collect(Collectors.toList());\n\t\t\tif (sortedNeighbors.size() == 0) return null;\n\t\t\tfinal Optional<NeighborTileEntity<TileEntity>> nextNeighbor = sortedNeighbors.stream()\n\t\t\t\t\t.filter(neighbor -> neighbor.getDirection().ordinal() > previousDirection.ordinal())\n\t\t\t\t\t.findFirst();\n\t\t\treturn nextNeighbor.map(neighbor -> new Pair<>(neighbor, neighbors.get(neighbor)))\n\t\t\t\t\t.orElse(new Pair<>(sortedNeighbors.get(0), neighbors.get(sortedNeighbors.get(0))));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void nextOrientation() {\n\t\tfinal EnumFacing pointedDirection = pointedAdjacentProperty.getDirectionOrNull();\n\t\tPair<NeighborTileEntity<TileEntity>, ConnectionType> newNeighbor = nextPointedOrientation(pointedDirection);\n\t\tfinal ChassisOrientationPacket packet = PacketHandler.getPacket(ChassisOrientationPacket.class);\n\t\tif (newNeighbor == null) {\n\t\t\tpointedAdjacentProperty.setValue(NoAdjacent.INSTANCE);\n\t\t\tpacket.setDir(null);\n\t\t} else {\n\t\t\tpointedAdjacentProperty.setValue(\n\t\t\t\tnew SingleAdjacent(this, newNeighbor.getValue1().getDirection(), newNeighbor.getValue2()));\n\t\t\tpacket.setDir(newNeighbor.getValue1().getDirection());\n\t\t}\n\t\tMainProxy.sendPacketToAllWatchingChunk(_module, packet.setTilePos(container));\n\t\trefreshRender(true);\n\t}\n\n\t@Override\n\tpublic void setPointedOrientation(@Nullable EnumFacing dir) {\n\t\tif (dir == null) {\n\t\t\tpointedAdjacentProperty.setValue(NoAdjacent.INSTANCE);\n\t\t} else {\n\t\t\tpointedAdjacentProperty.setValue(\n\t\t\t\tnew SingleAdjacent(this, dir, ConnectionType.UNDEFINED));\n\t\t}\n\t}\n\n\t// FIXME: remove after 1.12\n\tprivate void updateModuleInventory() {\n\t\t_module.slottedModules().forEach(slottedModule -> {\n\t\t\tif (slottedModule.isEmpty()) {\n\t\t\t\t_moduleInventory.clearInventorySlotContents(slottedModule.getSlot());\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinal LogisticsModule module = Objects.requireNonNull(slottedModule.getModule());\n\t\t\tfinal ItemIdentifierStack idStack = _moduleInventory.getIDStackInSlot(slottedModule.getSlot());\n\t\t\tItemStack moduleStack;\n\t\t\tif (idStack != null) {\n\t\t\t\tmoduleStack = idStack.getItem().makeNormalStack(1);\n\t\t\t} else {\n\t\t\t\tResourceLocation resourceLocation = LPItems.modules.get(module.getLPName());\n\t\t\t\tItem item = Item.REGISTRY.getObject(resourceLocation);\n\t\t\t\tif (item == null) return;\n\t\t\t\tmoduleStack = new ItemStack(item);\n\t\t\t}\n\t\t\tItemModuleInformationManager.saveInformation(moduleStack, module);\n\t\t\t_moduleInventory.setInventorySlotContents(slottedModule.getSlot(), moduleStack);\n\t\t});\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IInventory getModuleInventory() {\n\t\tupdateModuleInventory();\n\t\treturn _moduleInventory;\n\t}\n\n\t@Nonnull\n\tpublic ModuleUpgradeManager getModuleUpgradeManager(int slot) {\n\t\treturn _module.getModuleUpgradeManager(slot);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_TEXTURE;\n\t}\n\n\t@Override\n\tpublic TextureType getRoutedTexture(EnumFacing connection) {\n\t\tif (getRouter().isSubPoweredExit(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_SUBPOWER_TEXTURE;\n\t\t}\n\t\treturn Textures.LOGISTICSPIPE_CHASSI_ROUTED_TEXTURE;\n\t}\n\n\t@Override\n\tpublic TextureType getNonRoutedTexture(@Nullable EnumFacing connection) {\n\t\tfinal @Nullable EnumFacing pointedDirection = pointedAdjacentProperty.getDirectionOrNull();\n\t\tif (pointedDirection != null && pointedDirection.equals(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE;\n\t\t}\n\t\tif (isPowerProvider(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_POWERED_TEXTURE;\n\t\t}\n\t\treturn Textures.LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\t_moduleInventory.readFromNBT(tag, \"chassi\");\n\n\t\t// FIXME: remove after 1.12.2\n\t\tif (tag.hasKey(\"Orientation\")) {\n\t\t\tint orientationInt = tag.getInteger(\"Orientation\");\n\t\t\tif (orientationInt != -1) {\n\t\t\t\tsetPointedOrientation(EnumFacingUtil.getOrientation(orientationInt % 6));\n\t\t\t}\n\t\t}\n\t\t// FIXME: remove after 1.12.2 update, backwards compatibility\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tfinal ItemIdentifierStack idStack = _moduleInventory.getIDStackInSlot(i);\n\t\t\tif (idStack != null && !_module.hasModule(i)) {\n\t\t\t\tfinal Item stackItem = idStack.getItem().item;\n\t\t\t\tif (stackItem instanceof ItemModule) {\n\t\t\t\t\tfinal ItemModule moduleItem = (ItemModule) stackItem;\n\t\t\t\t\tLogisticsModule module = moduleItem.getModule(null, this, this);\n\t\t\t\t\tif (module != null) {\n\t\t\t\t\t\t_module.installModule(i, module);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// remove end\n\n\t\t// register slotted modules\n\t\t_module.slottedModules()\n\t\t\t\t.filter(slottedModule -> !slottedModule.isEmpty())\n\t\t\t\t.forEach(slottedModule -> {\n\t\t\t\t\tLogisticsModule logisticsModule = Objects.requireNonNull(slottedModule.getModule());\n\t\t\t\t\t// FIXME: rely on getModuleForItem instead\n\t\t\t\t\tlogisticsModule.registerHandler(this, this);\n\t\t\t\t\tslottedModule.registerPosition();\n\t\t\t\t});\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound tag) {\n\t\tsuper.writeToNBT(tag);\n\t\tupdateModuleInventory();\n\t\t_moduleInventory.writeToNBT(tag, \"chassi\");\n\t}\n\n\t@Override\n\tpublic void onAllowedRemoval() {\n\t\t_moduleInventory.removeListener(this);\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\t\tLogisticsModule x = getSubModule(i);\n\t\t\t\tif (x instanceof ILegacyActiveModule) {\n\t\t\t\t\tILegacyActiveModule y = (ILegacyActiveModule) x;\n\t\t\t\t\ty.onBlockRemoval();\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdateModuleInventory();\n\t\t\t_moduleInventory.dropContents(getWorld(), getX(), getY(), getZ());\n\n\t\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\t\tgetModuleUpgradeManager(i).dropUpgrades();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemArrived(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (info instanceof ChassiTargetInformation) {\n\t\t\t\tChassiTargetInformation target = (ChassiTargetInformation) info;\n\t\t\t\tLogisticsModule module = getSubModule(target.moduleSlot);\n\t\t\t\tif (module instanceof IRequireReliableTransport) {\n\t\t\t\t\t((IRequireReliableTransport) module).itemArrived(item, info);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (LogisticsPipes.isDEBUG() && info != null) {\n\t\t\t\t\tSystem.out.println(item);\n\t\t\t\t\tnew RuntimeException(\"[ItemArrived] Information weren't meant for a chassis pipe\").printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemLost(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (info instanceof ChassiTargetInformation) {\n\t\t\t\tChassiTargetInformation target = (ChassiTargetInformation) info;\n\t\t\t\tLogisticsModule module = getSubModule(target.moduleSlot);\n\t\t\t\tif (module instanceof IRequireReliableTransport) {\n\t\t\t\t\t((IRequireReliableTransport) module).itemLost(item, info);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tSystem.out.println(item);\n\t\t\t\t\tnew RuntimeException(\"[ItemLost] Information weren't meant for a chassis pipe\").printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic int addToBuffer(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (info instanceof ChassiTargetInformation) {\n\t\t\t\tChassiTargetInformation target = (ChassiTargetInformation) info;\n\t\t\t\tLogisticsModule module = getSubModule(target.moduleSlot);\n\t\t\t\tif (module instanceof IBufferItems) {\n\t\t\t\t\treturn ((IBufferItems) module).addToBuffer(item, info);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tSystem.out.println(item);\n\t\t\t\t\tnew RuntimeException(\"[AddToBuffer] Information weren't meant for a chassis pipe\").printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn item.getStackSize();\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tboolean reInitGui = false;\n\t\tfor (int i = 0; i < inventory.getSizeInventory(); i++) {\n\t\t\tItemStack stack = inventory.getStackInSlot(i);\n\t\t\tif (stack.isEmpty()) {\n\t\t\t\tif (_module.hasModule(i)) {\n\t\t\t\t\t_module.removeModule(i);\n\t\t\t\t\treInitGui = true;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfinal Item stackItem = stack.getItem();\n\t\t\tif (stackItem instanceof ItemModule) {\n\t\t\t\tfinal ItemModule moduleItem = (ItemModule) stackItem;\n\t\t\t\tLogisticsModule current = _module.getModule(i);\n\t\t\t\tLogisticsModule next = moduleItem.getModuleForItem(stack, current, this, this);\n\t\t\t\tObjects.requireNonNull(next, \"getModuleForItem returned null for \" + stack);\n\t\t\t\tnext.registerPosition(ModulePositionType.SLOT, i);\n\t\t\t\tif (current != next) {\n\t\t\t\t\t_module.installModule(i, next);\n\t\t\t\t\tif (!MainProxy.isClient(getWorld())) {\n\t\t\t\t\t\tItemModuleInformationManager.readInformation(stack, next);\n\t\t\t\t\t}\n\t\t\t\t\tnext.finishInit();\n\t\t\t\t}\n\t\t\t\tinventory.setInventorySlotContents(i, stack);\n\t\t\t}\n\t\t}\n\t\tif (reInitGui) {\n\t\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiChassisPipe) {\n\t\t\t\t\tFMLClientHandler.instance().getClient().currentScreen.initGui();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (!localModeWatchers.isEmpty()) {\n\t\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(ChassisPipeModuleContent.class)\n\t\t\t\t\t\t.setIdentList(ItemIdentifierStack.getListFromInventory(_moduleInventory))\n\t\t\t\t\t\t.setPosX(getX()).setPosY(getY()).setPosZ(getZ()),\n\t\t\t\t\t\tlocalModeWatchers);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void ignoreDisableUpdateEntity() {\n\t\tif (!init) {\n\t\t\tinit = true;\n\t\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestChassisOrientationPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn _module;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic TransportLayer getTransportLayer() {\n\t\tif (_transportLayer == null) {\n\t\t\t_transportLayer = new ChassisTransportLayer(this);\n\t\t}\n\t\treturn _transportLayer;\n\t}\n\n\tprivate boolean tryInsertingModule(EntityPlayer entityplayer) {\n\t\tupdateModuleInventory();\n\t\tfor (int i = 0; i < _moduleInventory.getSizeInventory(); i++) {\n\t\t\tif (_moduleInventory.getIDStackInSlot(i) == null) {\n\t\t\t\t_moduleInventory.setInventorySlotContents(i, entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).splitStack(1));\n\t\t\t\tInventoryChanged(_moduleInventory);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\tif (entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (entityplayer.isSneaking() && SimpleServiceLocator.configToolHandler.canWrench(entityplayer, entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND), container)) {\n\t\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\t\tif (settings == null || settings.openGui) {\n\t\t\t\t\t((PipeLogisticsChassis) container.pipe).nextOrientation();\n\t\t\t\t} else {\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\tSimpleServiceLocator.configToolHandler.wrenchUsed(entityplayer, entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND), container);\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!entityplayer.isSneaking() && entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).getItem() instanceof ItemModule) {\n\t\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\t\tif (settings == null || settings.openGui) {\n\t\t\t\t\treturn tryInsertingModule(entityplayer);\n\t\t\t\t} else {\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/*** IProvideItems ***/\n\t@Override\n\tpublic void canProvide(RequestTreeNode tree, RequestTree root, List<IFilter> filters) {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tfor (IFilter filter : filters) {\n\t\t\tif (filter.isBlocked() == filter.isFilteredItem(tree.getRequestType()) || filter.blockProvider()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\t\t\tif (x instanceof ILegacyActiveModule) {\n\t\t\t\tILegacyActiveModule y = (ILegacyActiveModule) x;\n\t\t\t\ty.canProvide(tree, root, filters);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic LogisticsOrder fullFill(LogisticsPromise promise, IRequestItems destination, IAdditionalTargetInformation info) {\n\t\tif (!isEnabled()) {\n\t\t\treturn null;\n\t\t}\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\t\t\tif (x instanceof ILegacyActiveModule) {\n\t\t\t\tILegacyActiveModule y = (ILegacyActiveModule) x;\n\t\t\t\tLogisticsOrder result = y.fullFill(promise, destination, info);\n\t\t\t\tif (result != null) {\n\t\t\t\t\tspawnParticle(Particles.WhiteParticle, 2);\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void getAllItems(Map<ItemIdentifier, Integer> list, List<IFilter> filter) {\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\t\t\tif (x instanceof ILegacyActiveModule) {\n\t\t\t\tILegacyActiveModule y = (ILegacyActiveModule) x;\n\t\t\t\ty.getAllItems(list, filter);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn hud;\n\t}\n\n\t@Override\n\tpublic void startWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStartWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t}\n\n\t@Override\n\tpublic void stopWatching() {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(HUDStopWatchingPacket.class).setInteger(1).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t\thud.stopWatching();\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 1) {\n\t\t\tupdateModuleInventory();\n\t\t\tlocalModeWatchers.add(player);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ChassisPipeModuleContent.class).setIdentList(ItemIdentifierStack.getListFromInventory(_moduleInventory)).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), player);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SendQueueContent.class).setIdentList(ItemIdentifierStack.getListSendQueue(_sendQueue)).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), player);\n\t\t} else {\n\t\t\tsuper.playerStartWatching(player, mode);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tsuper.playerStopWatching(player, mode);\n\t\tlocalModeWatchers.remove(player);\n\t}\n\n\tpublic void handleModuleItemIdentifierList(Collection<ItemIdentifierStack> _allItems) {\n\t\t_moduleInventory.handleItemIdentifierList(_allItems);\n\t}\n\n\t@Override\n\tpublic int sendQueueChanged(boolean force) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (Configs.MULTI_THREAD_NUMBER > 0 && !force) {\n\t\t\t\tHudUpdateTick.add(getRouter());\n\t\t\t} else {\n\t\t\t\tif (localModeWatchers.size() > 0) {\n\t\t\t\t\tLinkedList<ItemIdentifierStack> items = ItemIdentifierStack.getListSendQueue(_sendQueue);\n\t\t\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(SendQueueContent.class).setIdentList(items).setPosX(getX()).setPosY(getY()).setPosZ(getZ()), localModeWatchers);\n\t\t\t\t\treturn items.size();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void handleSendQueueItemIdentifierList(Collection<ItemIdentifierStack> _allItems) {\n\t\tdisplayList.clear();\n\t\tdisplayList.addAll(_allItems);\n\t}\n\n\tpublic ChassisModule getModules() {\n\t\treturn _module;\n\t}\n\n\t@Override\n\tpublic void setTile(TileEntity tile) {\n\t\tsuper.setTile(tile);\n\t\t_module.slottedModules().forEach(SlottedModule::registerPosition);\n\t}\n\n\t@Override\n\tpublic int getSourceID() {\n\t\treturn getRouterId();\n\t}\n\n\t@Override\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {\n\t\t// if we don't have a pointed inventory we can't be interested in anything\n\t\tif (pointedAdjacentProperty.getValue().inventories().isEmpty()) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (int moduleIndex = 0; moduleIndex < getChassisSize(); moduleIndex++) {\n\t\t\tLogisticsModule module = getSubModule(moduleIndex);\n\t\t\tif (module != null && module.interestedInAttachedInventory()) {\n\t\t\t\tfinal ISlotUpgradeManager upgradeManager = getUpgradeManager(module.getSlot(), module.getPositionInt());\n\t\t\t\tIInventoryUtil inv = PipeServiceProviderUtilKt.availableSneakyInventories(this, upgradeManager).stream().findFirst().orElse(null);\n\t\t\t\tif (inv == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tSet<ItemIdentifier> items = inv.getItems();\n\t\t\t\titemIdentifiers.addAll(items);\n\n\t\t\t\t//also add tag-less variants ... we should probably add a module.interestedIgnoringNBT at some point\n\t\t\t\titems.stream().map(ItemIdentifier::getIgnoringNBT).forEach(itemIdentifiers::add);\n\n\t\t\t\tboolean modulesInterestedInUndamaged = false;\n\t\t\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\t\t\tif (getSubModule(moduleIndex).interestedInUndamagedID()) {\n\t\t\t\t\t\tmodulesInterestedInUndamaged = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (modulesInterestedInUndamaged) {\n\t\t\t\t\titems.stream().map(ItemIdentifier::getUndamaged).forEach(itemIdentifiers::add);\n\t\t\t\t}\n\t\t\t\tbreak; // no need to check other modules for interest in the inventory, when we know that 1 already is.\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule module = getSubModule(i);\n\t\t\tif (module != null) {\n\t\t\t\tmodule.collectSpecificInterests(itemIdentifiers);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasGenericInterests() {\n\t\tif (pointedAdjacentProperty.getValue().inventories().isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\n\t\t\tif (x != null && x.hasGenericInterests()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@CCCommand(description = \"Returns the LogisticsModule for the given slot number starting by 1\")\n\tpublic LogisticsModule getModuleInSlot(Double i) {\n\t\treturn getSubModule((int) (i - 1));\n\t}\n\n\t@CCCommand(description = \"Returns the size of this Chassis pipe\")\n\tpublic Integer getChassieSize() {\n\t\treturn getChassisSize();\n\t}\n\n\t/** ICraftItems */\n\tpublic final LinkedList<LogisticsOrder> _extras = new LinkedList<>();\n\n\t@Override\n\tpublic void registerExtras(IPromise promise) {\n\t\tif (!(promise instanceof LogisticsPromise)) {\n\t\t\tthrow new UnsupportedOperationException(\"Extra has to be an item for a chassis pipe\");\n\t\t}\n\t\tItemIdentifierStack stack = new ItemIdentifierStack(((LogisticsPromise) promise).item, ((LogisticsPromise) promise).numberOfItems);\n\t\t_extras.add(new LogisticsItemOrder(new DictResource(stack, null), null, ResourceType.EXTRA, null));\n\t}\n\n\t@Override\n\tpublic ICraftingTemplate addCrafting(IResource toCraft) {\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\n\t\t\tif (x instanceof ICraftItems) {\n\t\t\t\tif (((ICraftItems) x).canCraft(toCraft)) {\n\t\t\t\t\treturn ((ICraftItems) x).addCrafting(toCraft);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\n\t\t// trixy code goes here to ensure the right crafter answers the right request\n\t}\n\n\t@Override\n\tpublic List<ItemIdentifierStack> getCraftedItems() {\n\t\tList<ItemIdentifierStack> craftables = null;\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\n\t\t\tif (x instanceof ICraftItems) {\n\t\t\t\tif (craftables == null) {\n\t\t\t\t\tcraftables = new LinkedList<>();\n\t\t\t\t}\n\t\t\t\tcraftables.addAll(((ICraftItems) x).getCraftedItems());\n\t\t\t}\n\t\t}\n\t\treturn craftables;\n\t}\n\n\t@Override\n\tpublic boolean canCraft(IResource toCraft) {\n\t\tfor (int i = 0; i < getChassisSize(); i++) {\n\t\t\tLogisticsModule x = getSubModule(i);\n\n\t\t\tif (x instanceof ICraftItems) {\n\t\t\t\tif (((ICraftItems) x).canCraft(toCraft)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ISlotUpgradeManager getUpgradeManager(ModulePositionType slot, int positionInt) {\n\t\tif (slot != ModulePositionType.SLOT || positionInt >= getChassisSize()) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tnew UnsupportedOperationException(\"Position info aren't for a chassis pipe. (\" + slot + \"/\" + positionInt + \")\").printStackTrace();\n\t\t\t}\n\t\t\treturn super.getUpgradeManager(slot, positionInt);\n\t\t}\n\t\treturn _module.getModuleUpgradeManager(positionInt);\n\t}\n\n\t@Override\n\tpublic int getTodo() {\n\t\t// TODO Auto-generated method stub\n\t\t// probably not needed, the chassis order manager handles the count, would need to store origin to specifically know this.\n\t\treturn 0;\n\t}\n\n\t@Nullable\n\tpublic LogisticsModule getSubModule(int slot) {\n\t\treturn _module.getModule(slot);\n\t}\n\n\tpublic static class ChassiTargetInformation implements IAdditionalTargetInformation {\n\n\t\t@Getter\n\t\tprivate final int moduleSlot;\n\n\t\tpublic ChassiTargetInformation(int slot) {\n\t\t\tmoduleSlot = slot;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeLogisticsChassisMk1.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.item.Item;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\n\npublic class PipeLogisticsChassisMk1 extends PipeLogisticsChassis {\n\n\tpublic PipeLogisticsChassisMk1(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_CHASSI1_TEXTURE;\n\t}\n\n\t@Override\n\tpublic int getChassisSize() {\n\t\treturn Configs.CHASSIS_SLOTS_ARRAY[0];\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeLogisticsChassisMk2.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.item.Item;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\n\npublic class PipeLogisticsChassisMk2 extends PipeLogisticsChassis {\n\n\tpublic PipeLogisticsChassisMk2(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_CHASSI2_TEXTURE;\n\t}\n\n\t@Override\n\tpublic int getChassisSize() {\n\t\treturn Configs.CHASSIS_SLOTS_ARRAY[1];\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeLogisticsChassisMk3.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.item.Item;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\n\npublic class PipeLogisticsChassisMk3 extends PipeLogisticsChassis {\n\n\tpublic PipeLogisticsChassisMk3(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_CHASSI3_TEXTURE;\n\t}\n\n\t@Override\n\tpublic int getChassisSize() {\n\t\treturn Configs.CHASSIS_SLOTS_ARRAY[2];\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeLogisticsChassisMk4.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.item.Item;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\n\npublic class PipeLogisticsChassisMk4 extends PipeLogisticsChassis {\n\n\tpublic PipeLogisticsChassisMk4(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_CHASSI4_TEXTURE;\n\t}\n\n\t@Override\n\tpublic int getChassisSize() {\n\t\treturn Configs.CHASSIS_SLOTS_ARRAY[3];\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/PipeLogisticsChassisMk5.java",
    "content": "package logisticspipes.pipes;\n\nimport net.minecraft.item.Item;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\n\npublic class PipeLogisticsChassisMk5 extends PipeLogisticsChassis {\n\n\tpublic PipeLogisticsChassisMk5(Item item) {\n\t\tsuper(item);\n\t}\n\n\t@Override\n\tpublic TextureType getCenterTexture() {\n\t\treturn Textures.LOGISTICSPIPE_CHASSI5_TEXTURE;\n\t}\n\n\t@Override\n\tpublic int getChassisSize() {\n\t\treturn Configs.CHASSIS_SLOTS_ARRAY[4];\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/SatelliteNamingResult.java",
    "content": "package logisticspipes.pipes;\n\npublic enum SatelliteNamingResult {\n\tSUCCESS, DUPLICATE_NAME, BLANK_NAME;\n\n\t@Override\n\tpublic String toString() {\n\t\treturn super.toString().toLowerCase();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/CoreMultiBlockPipe.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeMultiBlockTransportLogistics;\nimport logisticspipes.utils.LPPositionSet;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic abstract class CoreMultiBlockPipe extends CoreUnroutedPipe {\n\n\tpublic enum SubBlockTypeForShare {\n\t\tNON_SHARE,\n\t\tS_CURVE_A,\n\t\tS_CURVE_B,\n\t\tCURVE_OUT_A,\n\t\tCURVE_INNER_A,\n\t\tCURVE_OUT_B,\n\t\tCURVE_INNER_B,\n\t\tGAIN_A,\n\t\tGAIN_B\n\t}\n\n\tprivate static List<Pair<SubBlockTypeForShare, SubBlockTypeForShare>> allowedCombinations;\n\n\tstatic {\n\t\tallowedCombinations = new ArrayList<>();\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.S_CURVE_A, SubBlockTypeForShare.S_CURVE_B));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.S_CURVE_A, SubBlockTypeForShare.S_CURVE_A));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.CURVE_OUT_A, SubBlockTypeForShare.CURVE_INNER_A));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.CURVE_OUT_B, SubBlockTypeForShare.CURVE_INNER_B));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.CURVE_OUT_A, SubBlockTypeForShare.S_CURVE_A));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.CURVE_OUT_B, SubBlockTypeForShare.S_CURVE_A));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.GAIN_A, SubBlockTypeForShare.GAIN_B));\n\t\tallowedCombinations.add(new Pair<>(SubBlockTypeForShare.GAIN_A, SubBlockTypeForShare.GAIN_A));\n\t}\n\n\tpublic static boolean canShare(List<SubBlockTypeForShare> list, SubBlockTypeForShare toAdd) {\n\t\tif (toAdd == SubBlockTypeForShare.NON_SHARE) return false;\n\t\tif (toAdd == null) return false;\n\t\tif (list.size() > 1) return false;\n\t\tif (list.isEmpty()) return true;\n\t\tSubBlockTypeForShare contained = list.get(0);\n\t\tif (contained == SubBlockTypeForShare.NON_SHARE) return false;\n\t\tfor (Pair<SubBlockTypeForShare, SubBlockTypeForShare> allowed : allowedCombinations) {\n\t\t\tif (allowed.getValue1() == contained) {\n\t\t\t\tif (allowed.getValue2() == toAdd) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (allowed.getValue2() == contained) {\n\t\t\t\tif (allowed.getValue1() == toAdd) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic CoreMultiBlockPipe(PipeMultiBlockTransportLogistics transport, Item item) {\n\t\tsuper(transport, item);\n\t}\n\n\t@Override\n\tpublic boolean isMultiBlock() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * North Orientated\n\t *\n\t * @return Relative Positions\n\t */\n\tpublic abstract LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getSubBlocks();\n\n\tpublic abstract LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getRotatedSubBlocks();\n\n\tpublic abstract void addCollisionBoxesToList(List<AxisAlignedBB> arraylist, AxisAlignedBB axisalignedbb);\n\n\tpublic abstract AxisAlignedBB getCompleteBox();\n\n\tpublic abstract ITubeOrientation getTubeOrientation(EntityPlayer player, int xPos, int zPos);\n\n\tpublic abstract float getPipeLength();\n\n\tpublic double getDistanceWeight() {\n\t\treturn 1.0 / 8.0;\n\t}\n\n\tpublic float getYawDiff(LPTravelingItem item) {\n\t\treturn (float) (getItemRenderYaw(getPipeLength(), item) - getItemRenderYaw(0.0F, item));\n\t}\n\n\tpublic abstract EnumFacing getExitForInput(EnumFacing commingFrom);\n\n\tpublic abstract TileEntity getConnectedEndTile(EnumFacing output);\n\n\t@Override\n\tpublic abstract boolean actAsNormalPipe();\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic abstract ISpecialPipeRenderer getSpecialRenderer();\n\n\t@Override\n\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing side) {\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\treturn true;\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tif (((LogisticsTileGenericPipe) tile).pipe.isMultiBlock()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn super.canPipeConnect(tile, side);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/CoreRoutedPipe.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.pipes.basic;\n\nimport java.util.*;\nimport java.util.concurrent.PriorityBlockingQueue;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.crash.CrashReportCategory;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport kotlin.Unit;\nimport lombok.Getter;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.asm.te.ILPTEInformation;\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.*;\nimport logisticspipes.interfaces.routing.*;\nimport logisticspipes.items.ItemPipeSignCreator;\nimport logisticspipes.logisticspipes.*;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.GuiIDs;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.pipe.PipeController;\nimport logisticspipes.network.packets.pipe.ParticleFX;\nimport logisticspipes.network.packets.pipe.PipeSignTypes;\nimport logisticspipes.network.packets.pipe.RequestSignPacket;\nimport logisticspipes.network.packets.pipe.StatUpdate;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipefxhandlers.PipeFXRenderHandler;\nimport logisticspipes.pipes.basic.debug.DebugLogController;\nimport logisticspipes.pipes.basic.debug.StatusEntry;\nimport logisticspipes.pipes.signs.IPipeSign;\nimport logisticspipes.pipes.upgrades.UpgradeManager;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.cc.CCConstants;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCDirectCall;\nimport logisticspipes.proxy.computers.interfaces.CCSecurtiyCheck;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.LogisticsItemOrderManager;\nimport logisticspipes.routing.order.LogisticsOrderManager;\nimport logisticspipes.security.PermissionException;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.transport.PipeTransportLogistics;\nimport logisticspipes.utils.*;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.connection.Adjacent;\nimport network.rs485.logisticspipes.connection.AdjacentFactory;\nimport network.rs485.logisticspipes.connection.NoAdjacent;\nimport network.rs485.logisticspipes.module.Gui;\nimport network.rs485.logisticspipes.property.PropertyHolder;\nimport network.rs485.logisticspipes.property.UtilKt;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@CCType(name = \"LogisticsPipes:Normal\")\npublic abstract class CoreRoutedPipe extends CoreUnroutedPipe\n\t\timplements IClientState, IRequestItems, ITrackStatistics, IWorldProvider, IWatchingHandler, IPipeServiceProvider, IQueueCCEvent, ILPPositionProvider {\n\n\tprivate static int pipecount = 0;\n\tpublic final PlayerCollectionList watchers = new PlayerCollectionList();\n\tprotected final PriorityBlockingQueue<ItemRoutingInformation> _inTransitToMe = new PriorityBlockingQueue<>(10,\n\t\t\tnew ItemRoutingInformation.DelayComparator());\n\tprotected final LinkedList<Triplet<IRoutedItem, EnumFacing, ItemSendMode>> _sendQueue = new LinkedList<>();\n\tprotected final Map<ItemIdentifier, Queue<Pair<Integer, ItemRoutingInformation>>> queuedDataForUnroutedItems = Collections.synchronizedMap(new TreeMap<>());\n\tpublic boolean _textureBufferPowered;\n\tpublic long delayTo = 0;\n\tpublic int repeatFor = 0;\n\tpublic int stat_session_sent;\n\tpublic int stat_session_recieved;\n\tpublic int stat_session_relayed;\n\tpublic long stat_lifetime_sent;\n\tpublic long stat_lifetime_recieved;\n\tpublic long stat_lifetime_relayed;\n\tpublic int server_routing_table_size = 0;\n\tprotected boolean stillNeedReplace = true;\n\tprotected IRouter router;\n\tprotected String routerId;\n\tprotected final Object routerIdLock = new Object();\n\tprotected int _delayOffset;\n\tprotected boolean _initialInit = true;\n\tprotected RouteLayer _routeLayer;\n\tprotected TransportLayer _transportLayer;\n\n\t@Nonnull\n\tfinal protected UpgradeManager upgradeManager = new UpgradeManager(this);\n\n\tprotected LogisticsItemOrderManager _orderItemManager = null;\n\tprotected int throttleTime = 20;\n\tprotected IPipeSign[] signItem = new IPipeSign[6];\n\tprivate boolean recheckConnections = false;\n\tprivate boolean enabled = true;\n\tprivate boolean preventRemove = false;\n\tprivate boolean destroyByPlayer = false;\n\tprivate final PowerSupplierHandler powerHandler = new PowerSupplierHandler(this);\n\t@Getter\n\tprivate final List<IOrderInfoProvider> clientSideOrderManager = new ArrayList<>();\n\tprivate int throttleTimeLeft = 20 + new Random().nextInt(Configs.LOGISTICS_DETECTION_FREQUENCY);\n\tprivate final int[] queuedParticles = new int[Particles.values().length];\n\tprivate boolean hasQueuedParticles = false;\n\tprivate boolean isOpaqueClientSide = false;\n\n\t/** Caches adjacent state, only on Side.SERVER */\n\t@Nonnull\n\tprivate Adjacent adjacent = NoAdjacent.INSTANCE;\n\n\t/**\n\t * @return the adjacent cache directly.\n\t */\n\t@Nonnull\n\tprotected Adjacent getAdjacent() {\n\t\treturn adjacent;\n\t}\n\n\t/**\n\t * Returns all adjacents on a regular routed pipe.\n\t */\n\t@Nonnull\n\t@Override\n\tpublic Adjacent getAvailableAdjacent() {\n\t\treturn getAdjacent();\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic EnumFacing getPointedOrientation() {\n\t\t// from IPipeServiceProvider, overridden in the PipeLogisticsChassis\n\t\treturn null;\n\t}\n\n\t/**\n\t * Re-creates adjacent cache.\n\t */\n\tprotected void updateAdjacentCache() {\n\t\tadjacent = AdjacentFactory.INSTANCE.createAdjacentCache(this);\n\t}\n\n\tprivate CacheHolder cacheHolder;\n\n\tpublic CoreRoutedPipe(Item item) {\n\t\tthis(new PipeTransportLogistics(true), item);\n\t}\n\n\tpublic CoreRoutedPipe(PipeTransportLogistics transport, Item item) {\n\t\tsuper(transport, item);\n\n\t\tCoreRoutedPipe.pipecount++;\n\n\t\t//Roughly spread pipe updates throughout the frequency, no need to maintain balance\n\t\t_delayOffset = CoreRoutedPipe.pipecount % Configs.LOGISTICS_DETECTION_FREQUENCY;\n\t}\n\n\t@Override\n\tpublic void markTileDirty() {\n\t\tif (container != null) container.markDirty();\n\t}\n\n\t@Nonnull\n\tpublic RouteLayer getRouteLayer() {\n\t\tif (_routeLayer == null) {\n\t\t\t_routeLayer = new RouteLayer(getRouter(), getTransportLayer(), this);\n\t\t}\n\t\treturn _routeLayer;\n\t}\n\n\t@Nonnull\n\tpublic TransportLayer getTransportLayer() {\n\t\tif (_transportLayer == null) {\n\t\t\t_transportLayer = new PipeTransportLayer(this, this, getRouter());\n\t\t}\n\t\treturn _transportLayer;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ISlotUpgradeManager getUpgradeManager(ModulePositionType slot, int positionInt) {\n\t\treturn upgradeManager;\n\t}\n\n\t@Override\n\tpublic IPipeUpgradeManager getUpgradeManager() {\n\t\treturn upgradeManager;\n\t}\n\n\tpublic UpgradeManager getOriginalUpgradeManager() {\n\t\treturn upgradeManager;\n\t}\n\n\t@Override\n\tpublic void queueRoutedItem(IRoutedItem routedItem, EnumFacing from) {\n\t\tif (from == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\t_sendQueue.addLast(new Triplet<>(routedItem, from, ItemSendMode.Normal));\n\t\tsendQueueChanged(false);\n\t}\n\n\tpublic void queueRoutedItem(IRoutedItem routedItem, @Nonnull EnumFacing from, ItemSendMode mode) {\n\t\tif (from == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\t_sendQueue.addLast(new Triplet<>(routedItem, from, mode));\n\t\tsendQueueChanged(false);\n\t}\n\n\t/**\n\t * @param force == true never delegates to a thread\n\t * @return number of things sent.\n\t */\n\tpublic int sendQueueChanged(boolean force) {\n\t\treturn 0;\n\t}\n\n\tprivate void sendRoutedItem(IRoutedItem routedItem, EnumFacing from) {\n\n\t\tif (from == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\n\t\ttransport.injectItem(routedItem, from.getOpposite());\n\n\t\tIRouter r = SimpleServiceLocator.routerManager.getServerRouter(routedItem.getDestination());\n\t\tif (r != null) {\n\t\t\tCoreRoutedPipe pipe = r.getCachedPipe();\n\t\t\tif (pipe != null) {\n\t\t\t\tpipe.notifyOfSend(routedItem.getInfo());\n\t\t\t} // else TODO: handle sending items to known chunk-unloaded destination?\n\t\t} // should not be able to send to a non-existing router\n\t\t// router.startTrackingRoutedItem((RoutedEntityItem) routedItem.getTravelingItem());\n\t\tspawnParticle(Particles.OrangeParticle, 2);\n\t\tstat_lifetime_sent++;\n\t\tstat_session_sent++;\n\t\tupdateStats();\n\t}\n\n\tprivate void notifyOfSend(ItemRoutingInformation routedItem) {\n\t\t_inTransitToMe.add(routedItem);\n\t\t//LogisticsPipes.log.info(\"Sending: \"+routedItem.getIDStack().getItem().getFriendlyName());\n\t}\n\n\tpublic void notifyOfReroute(ItemRoutingInformation routedItem) {\n\t\t_inTransitToMe.remove(routedItem);\n\t}\n\n\t//When Recreating the Item from the TE version we have the same hashCode but a different instance so we need to refresh this\n\tpublic void refreshItem(ItemRoutingInformation routedItem) {\n\t\tif (_inTransitToMe.contains(routedItem)) {\n\t\t\t_inTransitToMe.remove(routedItem);\n\t\t\t_inTransitToMe.add(routedItem);\n\t\t}\n\t}\n\n\tpublic abstract ItemSendMode getItemSendMode();\n\n\t/**\n\t * Designed to help protect against routing loops - if both pipes are on the same block\n\t *\n\t * @return boolean indicating if other and this are attached to the same inventory.\n\t */\n\tpublic boolean isOnSameContainer(CoreRoutedPipe other) {\n\t\t// FIXME: Same TileEntity? Same Inventory view?\n\t\treturn adjacent.connectedPos().keySet().stream().anyMatch(\n\t\t\tother.adjacent.connectedPos().keySet()::contains\n\t\t);\n\t}\n\n\t/***\n\t * first tick just create a router and do nothing.\n\t */\n\tpublic void firstInitialiseTick() {\n\t\tgetRouter();\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSignPacket.class).setTilePos(container));\n\t\t}\n\t}\n\n\t/***\n\t * Only Called Server Side Only Called when the pipe is enabled\n\t */\n\tpublic void enabledUpdateEntity() {\n\t\tpowerHandler.update();\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (signItem[i] != null) {\n\t\t\t\tsignItem[i].updateServerSide();\n\t\t\t}\n\t\t}\n\t}\n\n\t/***\n\t * Called Server and Client Side Called every tick\n\t */\n\tpublic void ignoreDisableUpdateEntity() {}\n\n\t@Override\n\tpublic final void updateEntity() {\n\t\tdebug.tick();\n\t\tspawnParticleTick();\n\t\tif (stillNeedReplace) {\n\t\t\tstillNeedReplace = false;\n\t\t\t//IBlockState state = getWorld().getBlockState(getPos());\n\t\t\t//getWorld().notifyNeighborsOfStateChange(getPos(), state == null ? null : state.getBlock(), true);\n\t\t\t/* TravelingItems are just held by a pipe, they don't need to know their world\n\t\t\t * for(Triplet<IRoutedItem, EnumFacing, ItemSendMode> item : _sendQueue) {\n\t\t\t\t//assign world to any entityitem we created in readfromnbt\n\t\t\t\titem.getValue1().getTravelingItem().setWorld(getWorld());\n\t\t\t}*/\n\t\t\t//first tick just create a router and do nothing.\n\t\t\tfirstInitialiseTick();\n\t\t\treturn;\n\t\t}\n\t\tif (repeatFor > 0) {\n\t\t\tif (delayTo < System.currentTimeMillis()) {\n\t\t\t\tdelayTo = System.currentTimeMillis() + 200;\n\t\t\t\trepeatFor--;\n\t\t\t\tgetWorld().notifyNeighborsOfStateChange(getPos(), getWorld().getBlockState(getPos()).getBlock(), true);\n\t\t\t}\n\t\t}\n\n\t\t// remove old items _inTransit -- these should have arrived, but have probably been lost instead. In either case, it will allow a re-send so that another attempt to re-fill the inventory can be made.\n\t\twhile (_inTransitToMe.peek() != null && _inTransitToMe.peek().getTickToTimeOut() <= 0) {\n\t\t\tfinal ItemRoutingInformation polledInfo = _inTransitToMe.poll();\n\t\t\tif (polledInfo != null) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tLogisticsPipes.log.info(\"Timed Out: \" + polledInfo.getItem().getFriendlyName() + \" (\" + polledInfo.hashCode() + \")\");\n\t\t\t\t}\n\t\t\t\tdebug.log(\"Timed Out: \" + polledInfo.getItem().getFriendlyName() + \" (\" + polledInfo.hashCode() + \")\");\n\t\t\t}\n\t\t}\n\t\t//update router before ticking logic/transport\n\t\tfinal boolean doFullRefresh =\n\t\t\t\tgetWorld().getTotalWorldTime() % Configs.LOGISTICS_DETECTION_FREQUENCY == _delayOffset\n\t\t\t\t|| _initialInit || recheckConnections;\n\t\tif (doFullRefresh) {\n\t\t\t// update adjacent cache first, so interests can be gathered correctly\n\t\t\t// in getRouter().update(…) below\n\t\t\tupdateAdjacentCache();\n\t\t}\n\t\tgetRouter().update(doFullRefresh, this);\n\t\trecheckConnections = false;\n\t\tgetOriginalUpgradeManager().securityTick();\n\t\tsuper.updateEntity();\n\n\t\tif (isNthTick(200)) {\n\t\t\tgetCacheHolder().trigger(null);\n\t\t}\n\n\t\t// from BaseRoutingLogic\n\t\tif (--throttleTimeLeft <= 0) {\n\t\t\tthrottledUpdateEntity();\n\t\t\tthrottleTimeLeft = throttleTime;\n\t\t}\n\n\t\tignoreDisableUpdateEntity();\n\t\t_initialInit = false;\n\t\tif (!_sendQueue.isEmpty()) {\n\t\t\tif (getItemSendMode() == ItemSendMode.Normal) {\n\t\t\t\tTriplet<IRoutedItem, EnumFacing, ItemSendMode> itemToSend = _sendQueue.getFirst();\n\t\t\t\tsendRoutedItem(itemToSend.getValue1(), itemToSend.getValue2());\n\t\t\t\t_sendQueue.removeFirst();\n\t\t\t\tfor (int i = 0; i < 16 && !_sendQueue.isEmpty() && _sendQueue.getFirst().getValue3() == ItemSendMode.Fast; i++) {\n\t\t\t\t\tif (!_sendQueue.isEmpty()) {\n\t\t\t\t\t\titemToSend = _sendQueue.getFirst();\n\t\t\t\t\t\tsendRoutedItem(itemToSend.getValue1(), itemToSend.getValue2());\n\t\t\t\t\t\t_sendQueue.removeFirst();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsendQueueChanged(false);\n\t\t\t} else if (getItemSendMode() == ItemSendMode.Fast) {\n\t\t\t\tfor (int i = 0; i < 16; i++) {\n\t\t\t\t\tif (!_sendQueue.isEmpty()) {\n\t\t\t\t\t\tTriplet<IRoutedItem, EnumFacing, ItemSendMode> itemToSend = _sendQueue.getFirst();\n\t\t\t\t\t\tsendRoutedItem(itemToSend.getValue1(), itemToSend.getValue2());\n\t\t\t\t\t\t_sendQueue.removeFirst();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsendQueueChanged(false);\n\t\t\t} else if (getItemSendMode() == null) {\n\t\t\t\tthrow new UnsupportedOperationException(\"getItemSendMode() can't return null. \" + this.getClass().getName());\n\t\t\t} else {\n\t\t\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\t\t\"getItemSendMode() returned unhandled value. \" + getItemSendMode().name() + \" in \" + this.getClass().getName());\n\t\t\t}\n\t\t}\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tcheckTexturePowered();\n\t\tif (!isEnabled()) {\n\t\t\treturn;\n\t\t}\n\t\tenabledUpdateEntity();\n\t\tif (getLogisticsModule() == null) {\n\t\t\treturn;\n\t\t}\n\t\tgetLogisticsModule().tick();\n\t}\n\n\tprotected void onAllowedRemoval() {}\n\n\t// From BaseRoutingLogic\n\tpublic void throttledUpdateEntity() {}\n\n\tprotected void delayThrottle() {\n\t\t//delay 6(+1) ticks to prevent suppliers from ticking between a item arriving at them and the item hitting their adj. inv\n\t\tif (throttleTimeLeft < 7) {\n\t\t\tthrottleTimeLeft = 7;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isNthTick(int n) {\n\t\treturn ((getWorld().getTotalWorldTime() + _delayOffset) % n == 0);\n\t}\n\n\tprivate void doDebugStuff(EntityPlayer entityplayer) {\n\t\t//entityplayer.world.setWorldTime(4951);\n\t\tif (!MainProxy.isServer(entityplayer.world)) {\n\t\t\treturn;\n\t\t}\n\t\tStringBuilder sb = new StringBuilder();\n\t\tServerRouter router = (ServerRouter) getRouter();\n\n\t\tsb.append(\"***\\n\");\n\t\tsb.append(\"---------Interests---------------\\n\");\n\t\tServerRouter.forEachGlobalSpecificInterest((itemIdentifier, serverRouters) -> {\n\t\t\tsb.append(itemIdentifier.getFriendlyName()).append(\":\");\n\t\t\tfor (IRouter j : serverRouters) {\n\t\t\t\tsb.append(j.getSimpleID()).append(\",\");\n\t\t\t}\n\t\t\tsb.append('\\n');\n\t\t});\n\n\t\tsb.append(\"ALL ITEMS:\");\n\t\tfor (IRouter j : ServerRouter.getInterestedInGeneral()) {\n\t\t\tsb.append(j.getSimpleID()).append(\",\");\n\t\t}\n\t\tsb.append('\\n');\n\n\t\tsb.append(router).append('\\n');\n\t\tsb.append(\"---------CONNECTED TO---------------\\n\");\n\t\tfor (CoreRoutedPipe adj : router._adjacent.keySet()) {\n\t\t\tsb.append(adj.getRouter().getSimpleID()).append('\\n');\n\t\t}\n\t\tsb.append('\\n');\n\t\tsb.append(\"========DISTANCE TABLE==============\\n\");\n\t\tfor (ExitRoute n : router.getIRoutersByCost()) {\n\t\t\tsb.append(n.destination.getSimpleID())\n\t\t\t\t\t.append(\" @ \")\n\t\t\t\t\t.append(n.distanceToDestination)\n\t\t\t\t\t.append(\" -> \")\n\t\t\t\t\t.append(n.connectionDetails)\n\t\t\t\t\t.append(\"(\")\n\t\t\t\t\t.append(n.destination.getId())\n\t\t\t\t\t.append(\")\")\n\t\t\t\t\t.append('\\n');\n\t\t}\n\t\tsb.append('\\n');\n\t\tsb.append(\"*******EXIT ROUTE TABLE*************\\n\");\n\t\tList<List<ExitRoute>> table = router.getRouteTable();\n\t\tfor (int i = 0; i < table.size(); i++) {\n\t\t\tif (table.get(i) != null) {\n\t\t\t\tif (table.get(i).size() > 0) {\n\t\t\t\t\tsb.append(i).append(\" -> \").append(table.get(i).get(0).destination.getSimpleID()).append('\\n');\n\t\t\t\t\tfor (ExitRoute route : table.get(i)) {\n\t\t\t\t\t\tsb.append(\"\\t\\t via \").append(route.exitOrientation).append(\"(\").append(route.distanceToDestination).append(\" distance)\").append('\\n');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsb.append('\\n');\n\t\tsb.append(\"++++++++++CONNECTIONS+++++++++++++++\\n\");\n\t\tsb.append(Arrays.toString(EnumFacing.VALUES)).append('\\n');\n\t\tsb.append(Arrays.toString(router.sideDisconnected)).append('\\n');\n\t\tif (container != null) {\n\t\t\tsb.append(Arrays.toString(container.pipeConnectionsBuffer)).append('\\n');\n\t\t}\n\t\tsb.append(\"+++++++++++++ADJACENT+++++++++++++++\\n\");\n\t\tsb.append(adjacent).append('\\n');\n\t\tsb.append(\"pointing: \").append(getPointedOrientation()).append('\\n');\n\t\tsb.append(\"~~~~~~~~~~~~~~~POWER~~~~~~~~~~~~~~~~\\n\");\n\t\tsb.append(router.getPowerProvider()).append('\\n');\n\t\tsb.append(\"~~~~~~~~~~~SUBSYSTEMPOWER~~~~~~~~~~~\\n\");\n\t\tsb.append(router.getSubSystemPowerProvider()).append('\\n');\n\t\tif (_orderItemManager != null) {\n\t\t\tsb.append(\"################ORDERDUMP#################\\n\");\n\t\t\t_orderItemManager.dump(sb);\n\t\t}\n\t\tsb.append(\"################END#################\\n\");\n\t\trefreshConnectionAndRender(true);\n\t\tSystem.out.print(sb);\n\t\trouter.CreateRouteTable(Integer.MAX_VALUE);\n\t}\n\n\t// end FromBaseRoutingLogic\n\n\t@Override\n\tpublic final void onBlockRemoval() {\n\t\ttry {\n\t\t\tonAllowedRemoval();\n\t\t\tsuper.onBlockRemoval();\n\t\t\t//Just in case\n\t\t\tCoreRoutedPipe.pipecount = Math.max(CoreRoutedPipe.pipecount - 1, 0);\n\n\t\t\tif (transport != null) {\n\t\t\t\ttransport.dropBuffer();\n\t\t\t}\n\t\t\tgetOriginalUpgradeManager().dropUpgrades();\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tif (router != null) {\n\t\t\trouter.destroy();\n\t\t\trouter = null;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (router != null) {\n\t\t\trouter.clearPipeCache();\n\t\t\trouter.clearInterests();\n\t\t}\n\t}\n\n\tpublic void checkTexturePowered() {\n\t\tif (Configs.LOGISTICS_POWER_USAGE_DISABLED) {\n\t\t\treturn;\n\t\t}\n\t\tif (!isNthTick(10)) {\n\t\t\treturn;\n\t\t}\n\t\tif (stillNeedReplace || _initialInit || router == null) {\n\t\t\treturn;\n\t\t}\n\t\tboolean flag;\n\t\tif ((flag = canUseEnergy(1)) != _textureBufferPowered) {\n\t\t\t_textureBufferPowered = flag;\n\t\t\trefreshRender(false);\n\t\t\tspawnParticle(Particles.RedParticle, 3);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\treturn getCenterTexture().newTexture;\n\t}\n\n\tpublic abstract TextureType getCenterTexture();\n\n\tpublic TextureType getTextureType(EnumFacing connection) {\n\t\tif (stillNeedReplace || _initialInit) {\n\t\t\treturn getCenterTexture();\n\t\t}\n\n\t\tif (connection == null) {\n\t\t\treturn getCenterTexture();\n\t\t} else if ((router != null) && getRouter().isRoutedExit(connection)) {\n\t\t\treturn getRoutedTexture(connection);\n\t\t} else {\n\t\t\tTextureType texture = getNonRoutedTexture(connection);\n\t\t\tif (this.getUpgradeManager().hasRFPowerSupplierUpgrade() || this.getUpgradeManager().getIC2PowerLevel() > 0) {\n\t\t\t\tif (texture.fileName.equals(Textures.LOGISTICSPIPE_NOTROUTED_TEXTURE.fileName)) {\n\t\t\t\t\ttexture = Textures.LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE;\n\t\t\t\t} else if (texture.fileName.equals(Textures.LOGISTICSPIPE_LIQUID_TEXTURE.fileName)) {\n\t\t\t\t\ttexture = Textures.LOGISTICSPIPE_LIQUID_POWERED_TEXTURE;\n\t\t\t\t} else if (texture.fileName.equals(Textures.LOGISTICSPIPE_POWERED_TEXTURE.fileName)) {\n\t\t\t\t\ttexture = Textures.LOGISTICSPIPE_POWERED_POWERED_TEXTURE;\n\t\t\t\t} else if (texture.fileName.equals(Textures.LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE.fileName)) {\n\t\t\t\t\ttexture = Textures.LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE;\n\t\t\t\t} else if (texture.fileName.equals(Textures.LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE.fileName)) {\n\t\t\t\t\ttexture = Textures.LOGISTICSPIPE_DIRECTION_POWERED_TEXTURE;\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.println(\"Unknown texture to power, :\" + texture.fileName);\n\t\t\t\t\tSystem.out.println(this.getClass());\n\t\t\t\t\tSystem.out.println(connection);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn texture;\n\t\t}\n\t}\n\n\tpublic TextureType getRoutedTexture(EnumFacing connection) {\n\t\tif (getRouter().isSubPoweredExit(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_SUBPOWER_TEXTURE;\n\t\t} else {\n\t\t\treturn Textures.LOGISTICSPIPE_ROUTED_TEXTURE;\n\t\t}\n\t}\n\n\tpublic TextureType getNonRoutedTexture(EnumFacing connection) {\n\t\tif (isPowerProvider(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_POWERED_TEXTURE;\n\t\t}\n\t\treturn Textures.LOGISTICSPIPE_NOTROUTED_TEXTURE;\n\t}\n\n\t@Override\n\tpublic void spawnParticle(Particles particle, int amount) {\n\t\tif (!Configs.ENABLE_PARTICLE_FX) {\n\t\t\treturn;\n\t\t}\n\t\tqueuedParticles[particle.ordinal()] += amount;\n\t\thasQueuedParticles = true;\n\t}\n\n\tprivate void spawnParticleTick() {\n\t\tif (!hasQueuedParticles) {\n\t\t\treturn;\n\t\t}\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tArrayList<ParticleCount> tosend = new ArrayList<>(queuedParticles.length);\n\t\t\tfor (int i = 0; i < queuedParticles.length; i++) {\n\t\t\t\tif (queuedParticles[i] > 0) {\n\t\t\t\t\ttosend.add(new ParticleCount(Particles.values()[i], queuedParticles[i]));\n\t\t\t\t}\n\t\t\t}\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(container, PacketHandler.getPacket(ParticleFX.class).setParticles(tosend).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t\t} else {\n\t\t\tif (Minecraft.isFancyGraphicsEnabled()) {\n\t\t\t\tfor (int i = 0; i < queuedParticles.length; i++) {\n\t\t\t\t\tif (queuedParticles[i] > 0) {\n\t\t\t\t\t\tPipeFXRenderHandler.spawnGenericParticle(Particles.values()[i], getX(), getY(), getZ(), queuedParticles[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tArrays.fill(queuedParticles, 0);\n\t\thasQueuedParticles = false;\n\t}\n\n\tprotected boolean isPowerProvider(@Nullable EnumFacing direction) {\n\t\tif (direction == null) return false;\n\t\tTileEntity tilePipe = container.getTile(direction);\n\t\tif (tilePipe == null || !container.canPipeConnect(tilePipe, direction)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn tilePipe instanceof ILogisticsPowerProvider || tilePipe instanceof ISubSystemPowerProvider;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\n\t\tsynchronized (routerIdLock) {\n\t\t\tif (routerId == null || routerId.isEmpty()) {\n\t\t\t\tif (router != null) {\n\t\t\t\t\trouterId = router.getId().toString();\n\t\t\t\t} else {\n\t\t\t\t\trouterId = UUID.randomUUID().toString();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tnbttagcompound.setString(\"routerId\", routerId);\n\t\tnbttagcompound.setLong(\"stat_lifetime_sent\", stat_lifetime_sent);\n\t\tnbttagcompound.setLong(\"stat_lifetime_recieved\", stat_lifetime_recieved);\n\t\tnbttagcompound.setLong(\"stat_lifetime_relayed\", stat_lifetime_relayed);\n\t\tif (getLogisticsModule() != null) {\n\t\t\tgetLogisticsModule().writeToNBT(nbttagcompound);\n\t\t}\n\t\tNBTTagCompound upgradeNBT = new NBTTagCompound();\n\t\tupgradeManager.writeToNBT(upgradeNBT);\n\t\tnbttagcompound.setTag(\"upgradeManager\", upgradeNBT);\n\n\t\tNBTTagCompound powerNBT = new NBTTagCompound();\n\t\tpowerHandler.writeToNBT(powerNBT);\n\t\tif (!powerNBT.isEmpty()) {\n\t\t\tnbttagcompound.setTag(\"powerHandler\", powerNBT);\n\t\t}\n\n\t\tNBTTagList sendqueue = new NBTTagList();\n\t\tfor (Triplet<IRoutedItem, EnumFacing, ItemSendMode> p : _sendQueue) {\n\t\t\tNBTTagCompound tagentry = new NBTTagCompound();\n\t\t\tNBTTagCompound tagentityitem = new NBTTagCompound();\n\t\t\tp.getValue1().writeToNBT(tagentityitem);\n\t\t\ttagentry.setTag(\"entityitem\", tagentityitem);\n\t\t\ttagentry.setByte(\"from\", (byte) (p.getValue2().ordinal()));\n\t\t\ttagentry.setByte(\"mode\", (byte) (p.getValue3().ordinal()));\n\t\t\tsendqueue.appendTag(tagentry);\n\t\t}\n\t\tnbttagcompound.setTag(\"sendqueue\", sendqueue);\n\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (signItem[i] != null) {\n\t\t\t\tnbttagcompound.setBoolean(\"PipeSign_\" + i, true);\n\t\t\t\tint signType = -1;\n\t\t\t\tList<Class<? extends IPipeSign>> typeClasses = ItemPipeSignCreator.signTypes;\n\t\t\t\tfor (int j = 0; j < typeClasses.size(); j++) {\n\t\t\t\t\tif (typeClasses.get(j) == signItem[i].getClass()) {\n\t\t\t\t\t\tsignType = j;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnbttagcompound.setInteger(\"PipeSign_\" + i + \"_type\", signType);\n\t\t\t\tNBTTagCompound tag = new NBTTagCompound();\n\t\t\t\tsignItem[i].writeToNBT(tag);\n\t\t\t\tnbttagcompound.setTag(\"PipeSign_\" + i + \"_tags\", tag);\n\t\t\t} else {\n\t\t\t\tnbttagcompound.setBoolean(\"PipeSign_\" + i, false);\n\t\t\t}\n\t\t}\n\n\t\tif (this instanceof PropertyHolder) {\n\t\t\tPropertyHolder.writeToNBT(nbttagcompound, (PropertyHolder) this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\n\t\tsynchronized (routerIdLock) {\n\t\t\trouterId = nbttagcompound.getString(\"routerId\");\n\t\t}\n\n\t\tstat_lifetime_sent = nbttagcompound.getLong(\"stat_lifetime_sent\");\n\t\tstat_lifetime_recieved = nbttagcompound.getLong(\"stat_lifetime_recieved\");\n\t\tstat_lifetime_relayed = nbttagcompound.getLong(\"stat_lifetime_relayed\");\n\t\tif (getLogisticsModule() != null) {\n\t\t\tgetLogisticsModule().readFromNBT(nbttagcompound);\n\t\t}\n\t\tupgradeManager.readFromNBT(nbttagcompound.getCompoundTag(\"upgradeManager\"));\n\t\tpowerHandler.readFromNBT(nbttagcompound.getCompoundTag(\"powerHandler\"));\n\n\t\t_sendQueue.clear();\n\t\tNBTTagList sendqueue = nbttagcompound.getTagList(\"sendqueue\", nbttagcompound.getId());\n\t\tfor (int i = 0; i < sendqueue.tagCount(); i++) {\n\t\t\tNBTTagCompound tagentry = sendqueue.getCompoundTagAt(i);\n\t\t\tNBTTagCompound tagentityitem = tagentry.getCompoundTag(\"entityitem\");\n\t\t\tLPTravelingItemServer item = new LPTravelingItemServer(tagentityitem);\n\t\t\tEnumFacing from = EnumFacing.values()[tagentry.getByte(\"from\")];\n\t\t\tItemSendMode mode = ItemSendMode.values()[tagentry.getByte(\"mode\")];\n\t\t\t_sendQueue.add(new Triplet<>(item, from, mode));\n\t\t}\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (nbttagcompound.getBoolean(\"PipeSign_\" + i)) {\n\t\t\t\tint type = nbttagcompound.getInteger(\"PipeSign_\" + i + \"_type\");\n\t\t\t\tClass<? extends IPipeSign> typeClass = ItemPipeSignCreator.signTypes.get(type);\n\t\t\t\ttry {\n\t\t\t\t\tsignItem[i] = typeClass.newInstance();\n\t\t\t\t\tsignItem[i].init(this, EnumFacingUtil.getOrientation(i));\n\t\t\t\t\tsignItem[i].readFromNBT(nbttagcompound.getCompoundTag(\"PipeSign_\" + i + \"_tags\"));\n\t\t\t\t} catch (InstantiationException | IllegalAccessException e) {\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this instanceof PropertyHolder) {\n\t\t\tPropertyHolder.readFromNBT(nbttagcompound, (PropertyHolder) this);\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\tif (stillNeedReplace) {\n\t\t\tSystem.out.format(\"Hey, don't get routers for pipes that aren't ready (%d, %d, %d, '%s')\", this.getX(), this.getY(), this.getZ(),\n\t\t\t\t\tthis.getWorld().getWorldInfo().getWorldName());\n\t\t\tnew Throwable().printStackTrace();\n\t\t}\n\t\tif (router == null) {\n\t\t\tsynchronized (routerIdLock) {\n\n\t\t\t\tUUID routerIntId = null;\n\t\t\t\tif (routerId != null && !routerId.isEmpty()) {\n\t\t\t\t\trouterIntId = UUID.fromString(routerId);\n\t\t\t\t}\n\t\t\t\trouter = SimpleServiceLocator.routerManager.getOrCreateRouter(routerIntId, getWorld(), getX(), getY(), getZ());\n\t\t\t}\n\t\t}\n\t\treturn router;\n\t}\n\n\tpublic boolean isEnabled() {\n\t\treturn enabled;\n\t}\n\n\tpublic void setEnabled(boolean enabled) {\n\t\tthis.enabled = enabled;\n\t}\n\n\t@CCCommand(description = \"Returns the Internal LogisticsModule for this pipe\")\n\tpublic abstract @Nullable LogisticsModule getLogisticsModule();\n\n\t@Override\n\tpublic final boolean blockActivated(EntityPlayer entityplayer) {\n\t\tif (container == null) return super.blockActivated(entityplayer);\n\t\tSecuritySettings settings = null;\n\t\tif (MainProxy.isServer(entityplayer.world)) {\n\t\t\tLogisticsSecurityTileEntity station = SimpleServiceLocator.securityStationManager.getStation(getOriginalUpgradeManager().getSecurityID());\n\t\t\tif (station != null) {\n\t\t\t\tsettings = station.getSecuritySettingsForPlayer(entityplayer, true);\n\t\t\t}\n\t\t}\n\n\t\tif (MainProxy.isPipeControllerEquipped(entityplayer)) {\n\t\t\tif (MainProxy.isServer(entityplayer.world)) {\n\t\t\t\tif (settings == null || settings.openNetworkMonitor) {\n\t\t\t\t\tNewGuiHandler.getGui(PipeController.class).setTilePos(container).open(entityplayer);\n\t\t\t\t} else {\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tif (handleClick(entityplayer, settings)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).isEmpty()) {\n\t\t\tif (!entityplayer.isSneaking()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t/*\n\t\t\tif (MainProxy.isClient(entityplayer.world)) {\n\t\t\t\tif (!LogisticsHUDRenderer.instance().hasLasers()) {\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RequestRoutingLasersPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));\n\t\t\t\t} else {\n\t\t\t\t\tLogisticsHUDRenderer.instance().resetLasers();\n\t\t\t\t}\n\t\t\t}\n\t\t\t*/\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tdoDebugStuff(entityplayer);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tif (entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).getItem() == LPItems.remoteOrderer) {\n\t\t\tif (MainProxy.isServer(entityplayer.world)) {\n\t\t\t\tif (settings == null || settings.openRequest) {\n\t\t\t\t\tentityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Normal_Orderer_ID, getWorld(), getX(), getY(), getZ());\n\t\t\t\t} else {\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tif (SimpleServiceLocator.configToolHandler.canWrench(entityplayer, entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND), container)) {\n\t\t\tif (MainProxy.isServer(entityplayer.world)) {\n\t\t\t\tif (settings == null || settings.openGui) {\n\t\t\t\t\tfinal LogisticsModule module = getLogisticsModule();\n\t\t\t\t\tif (module instanceof Gui) {\n\t\t\t\t\t\tGui.getPipeGuiProvider((Gui) module).setTilePos(container).open(entityplayer);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tonWrenchClicked(entityplayer);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tentityplayer.sendMessage(new TextComponentTranslation(\"lp.chat.permissiondenied\"));\n\t\t\t\t}\n\t\t\t}\n\t\t\tSimpleServiceLocator.configToolHandler.wrenchUsed(entityplayer, entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND), container);\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!(entityplayer.isSneaking()) && getOriginalUpgradeManager().tryIserting(getWorld(), entityplayer)) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn super.blockActivated(entityplayer);\n\t}\n\n\tprotected boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {\n\t\treturn false;\n\t}\n\n\tpublic void refreshRender(boolean spawnPart) {\n\t\tcontainer.scheduleRenderUpdate();\n\t\tif (spawnPart) {\n\t\t\tspawnParticle(Particles.GreenParticle, 3);\n\t\t}\n\t}\n\n\tpublic void refreshConnectionAndRender(boolean spawnPart) {\n\t\tcontainer.scheduleNeighborChange();\n\t\tif (spawnPart) {\n\t\t\tspawnParticle(Particles.GreenParticle, 3);\n\t\t}\n\t}\n\n\t/* ITrackStatistics */\n\n\t@Override\n\tpublic void receivedItem(int count) {\n\t\tstat_session_recieved += count;\n\t\tstat_lifetime_recieved += count;\n\t\tupdateStats();\n\t}\n\n\t@Override\n\tpublic void relayedItem(int count) {\n\t\tstat_session_relayed += count;\n\t\tstat_lifetime_relayed += count;\n\t\tupdateStats();\n\t}\n\n\t@Override\n\tpublic void playerStartWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 0) {\n\t\t\twatchers.add(player);\n\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(StatUpdate.class).setPipe(this), player);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void playerStopWatching(EntityPlayer player, int mode) {\n\t\tif (mode == 0) {\n\t\t\twatchers.remove(player);\n\t\t}\n\t}\n\n\tpublic void updateStats() {\n\t\tif (watchers.size() > 0) {\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(StatUpdate.class).setPipe(this), watchers);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void itemCouldNotBeSend(ItemIdentifierStack item, IAdditionalTargetInformation info) {\n\t\tif (this instanceof IRequireReliableTransport) {\n\t\t\t((IRequireReliableTransport) this).itemLost(item, info);\n\t\t}\n\t}\n\n\tpublic boolean isLockedExit(EnumFacing orientation) {\n\t\treturn false;\n\t}\n\n\tpublic boolean logisitcsIsPipeConnected(TileEntity tile, EnumFacing dir) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic final boolean canPipeConnect(TileEntity tile, EnumFacing dir) {\n\t\treturn canPipeConnect(tile, dir, false);\n\t}\n\n\t@Override\n\tpublic final boolean canPipeConnect(TileEntity tile, EnumFacing dir, boolean ignoreSystemDisconnection) {\n\t\tEnumFacing side = OrientationsUtil.getOrientationOfTilewithTile(container, tile);\n\t\tif (isSideBlocked(side, ignoreSystemDisconnection)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn (super.canPipeConnect(tile, dir) || logisitcsIsPipeConnected(tile, dir));\n\t}\n\n\t@Override\n\tpublic final boolean isSideBlocked(EnumFacing side, boolean ignoreSystemDisconnection) {\n\t\tif (getUpgradeManager().isSideDisconnected(side)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn !stillNeedReplace && getRouter().isSideDisconnected(side) && !ignoreSystemDisconnection;\n\t}\n\n\tpublic void connectionUpdate() {\n\t\tif (container != null && !stillNeedReplace) {\n\t\t\tif (MainProxy.isClient(getWorld())) throw new IllegalStateException(\"Wont do connectionUpdate on client-side\");\n\t\t\tcontainer.scheduleNeighborChange();\n\t\t\tIBlockState state = getWorld().getBlockState(getPos());\n\t\t\tgetWorld().notifyNeighborsOfStateChange(getPos(), state.getBlock(), true);\n\t\t}\n\t}\n\n\tpublic UUID getSecurityID() {\n\t\treturn getOriginalUpgradeManager().getSecurityID();\n\t}\n\n\tpublic void insetSecurityID(UUID id) {\n\t\tgetOriginalUpgradeManager().insetSecurityID(id);\n\t}\n\n\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> getRoutedPowerProviders() {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn null;\n\t\t}\n\t\tif (stillNeedReplace) {\n\t\t\treturn null;\n\t\t}\n\t\treturn getRouter().getPowerProvider();\n\t}\n\n\t/* Power System */\n\n\t@Override\n\tpublic boolean useEnergy(int amount) {\n\t\treturn useEnergy(amount, null, true);\n\t}\n\n\tpublic boolean useEnergy(int amount, boolean sparkles) {\n\t\treturn useEnergy(amount, null, sparkles);\n\t}\n\n\t@Override\n\tpublic boolean canUseEnergy(int amount) {\n\t\treturn canUseEnergy(amount, null);\n\t}\n\n\t@Override\n\tpublic boolean canUseEnergy(int amount, List<Object> providersToIgnore) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn false;\n\t\t}\n\t\tif (Configs.LOGISTICS_POWER_USAGE_DISABLED) {\n\t\t\treturn true;\n\t\t}\n\t\tif (amount == 0) {\n\t\t\treturn true;\n\t\t}\n\t\tif (providersToIgnore != null && providersToIgnore.contains(this)) {\n\t\t\treturn false;\n\t\t}\n\t\tList<Pair<ILogisticsPowerProvider, List<IFilter>>> list = getRoutedPowerProviders();\n\t\tif (list == null) {\n\t\t\treturn false;\n\t\t}\n\t\touter:\n\t\tfor (Pair<ILogisticsPowerProvider, List<IFilter>> provider : list) {\n\t\t\tfor (IFilter filter : provider.getValue2()) {\n\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (provider.getValue1().canUseEnergy(amount, providersToIgnore)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean useEnergy(int amount, List<Object> providersToIgnore) {\n\t\treturn useEnergy(amount, providersToIgnore, false);\n\t}\n\n\tprivate boolean useEnergy(int amount, List<Object> providersToIgnore, boolean sparkles) {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn false;\n\t\t}\n\t\tif (Configs.LOGISTICS_POWER_USAGE_DISABLED) {\n\t\t\treturn true;\n\t\t}\n\t\tif (amount == 0) {\n\t\t\treturn true;\n\t\t}\n\t\tif (providersToIgnore == null) {\n\t\t\tprovidersToIgnore = new ArrayList<>();\n\t\t}\n\t\tif (providersToIgnore.contains(this)) {\n\t\t\treturn false;\n\t\t}\n\t\tprovidersToIgnore.add(this);\n\t\tList<Pair<ILogisticsPowerProvider, List<IFilter>>> list = getRoutedPowerProviders();\n\t\tif (list == null) {\n\t\t\treturn false;\n\t\t}\n\t\touter:\n\t\tfor (Pair<ILogisticsPowerProvider, List<IFilter>> provider : list) {\n\t\t\tfor (IFilter filter : provider.getValue2()) {\n\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (provider.getValue1().canUseEnergy(amount, providersToIgnore)) {\n\t\t\t\tif (provider.getValue1().useEnergy(amount, providersToIgnore)) {\n\t\t\t\t\tif (sparkles) {\n\t\t\t\t\t\tint particlecount = amount;\n\t\t\t\t\t\tif (particlecount > 10) {\n\t\t\t\t\t\t\tparticlecount = 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tspawnParticle(Particles.GoldParticle, particlecount);\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void queueEvent(String event, Object[] arguments) {\n\t\tif (container != null) {\n\t\t\tcontainer.queueEvent(event, arguments);\n\t\t}\n\t}\n\n\tpublic boolean stillNeedReplace() {\n\t\treturn stillNeedReplace;\n\t}\n\n\tpublic boolean initialInit() {\n\t\treturn _initialInit;\n\t}\n\n\t@Override\n\tpublic int compareTo(@Nonnull IRequestItems other) {\n\t\treturn Integer.compare(getID(), other.getID());\n\t}\n\n\t@Override\n\tpublic int getID() {\n\t\treturn getRouter().getSimpleID();\n\t}\n\n\tpublic void collectSpecificInterests(@Nonnull Collection<ItemIdentifier> itemIdentifiers) {}\n\n\tpublic boolean hasGenericInterests() {\n\t\treturn false;\n\t}\n\n\t@Nullable\n\tpublic ISecurityProvider getSecurityProvider() {\n\t\treturn SimpleServiceLocator.securityStationManager.getStation(getOriginalUpgradeManager().getSecurityID());\n\t}\n\n\tpublic boolean canBeDestroyedByPlayer(EntityPlayer entityPlayer) {\n\t\tLogisticsSecurityTileEntity station = SimpleServiceLocator.securityStationManager.getStation(getOriginalUpgradeManager().getSecurityID());\n\t\treturn station == null || station.getSecuritySettingsForPlayer(entityPlayer, true).removePipes;\n\t}\n\n\t@Override\n\tpublic boolean canBeDestroyed() {\n\t\tISecurityProvider sec = getSecurityProvider();\n\t\treturn sec == null || sec.canAutomatedDestroy();\n\t}\n\n\tpublic void setDestroyByPlayer() {\n\t\tdestroyByPlayer = true;\n\t}\n\n\t@Override\n\tpublic boolean destroyByPlayer() {\n\t\treturn destroyByPlayer;\n\t}\n\n\t@Override\n\tpublic boolean preventRemove() {\n\t\treturn preventRemove;\n\t}\n\n\t@CCSecurtiyCheck\n\tpublic void checkCCAccess() throws PermissionException {\n\t\tISecurityProvider sec = getSecurityProvider();\n\t\tif (sec != null) {\n\t\t\tint id = -1;\n\t\t\tif (container != null) {\n\t\t\t\tid = container.getLastCCID();\n\t\t\t}\n\t\t\tif (!sec.getAllowCC(id)) {\n\t\t\t\tthrow new PermissionException();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void queueUnroutedItemInformation(ItemIdentifierStack item, ItemRoutingInformation information) {\n\t\tif (item != null) {\n\t\t\tsynchronized (queuedDataForUnroutedItems) {\n\t\t\t\tQueue<Pair<Integer, ItemRoutingInformation>> queue = queuedDataForUnroutedItems.computeIfAbsent(item.getItem(), k -> new LinkedList<>());\n\t\t\t\tqueue.add(new Pair<>(item.getStackSize(), information));\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic ItemRoutingInformation getQueuedForItemStack(ItemIdentifierStack item) {\n\t\tsynchronized (queuedDataForUnroutedItems) {\n\t\t\tQueue<Pair<Integer, ItemRoutingInformation>> queue = queuedDataForUnroutedItems.get(item.getItem());\n\t\t\tif (queue == null || queue.isEmpty()) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tPair<Integer, ItemRoutingInformation> pair = queue.peek();\n\t\t\tint wantItem = pair.getValue1();\n\n\t\t\tif (wantItem <= item.getStackSize()) {\n\t\t\t\tif (queue.remove() != pair) {\n\t\t\t\t\tLogisticsPipes.log.fatal(\"Item queue mismatch\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tif (queue.isEmpty()) {\n\t\t\t\t\tqueuedDataForUnroutedItems.remove(item.getItem());\n\t\t\t\t}\n\t\t\t\titem.setStackSize(wantItem);\n\t\t\t\treturn pair.getValue2();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * used as a distance offset when deciding which pipe to use NOTE: called\n\t * very regularly, returning a pre-calculated int is probably appropriate.\n\t */\n\tpublic double getLoadFactor() {\n\t\treturn 0.0;\n\t}\n\n\tpublic void notifyOfItemArival(ItemRoutingInformation information) {\n\t\t_inTransitToMe.remove(information);\n\t\tif (this instanceof IRequireReliableTransport) {\n\t\t\t((IRequireReliableTransport) this).itemArrived(information.getItem(), information.targetInfo);\n\t\t}\n\t\tif (this instanceof IRequireReliableFluidTransport) {\n\t\t\tItemIdentifierStack stack = information.getItem();\n\t\t\tif (stack.getItem().isFluidContainer()) {\n\t\t\t\tFluidIdentifierStack liquid = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(stack);\n\t\t\t\tif (liquid != null) {\n\t\t\t\t\t((IRequireReliableFluidTransport) this).liquidArrived(liquid.getFluid(), liquid.getAmount());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic int countOnRoute(ItemIdentifier it) {\n\t\tint count = 0;\n\t\tfor (ItemRoutingInformation next : _inTransitToMe) {\n\t\t\tif (next.getItem().getItem().equals(it)) {\n\t\t\t\tcount += next.getItem().getStackSize();\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\t@Override\n\tpublic final int getIconIndex(EnumFacing connection) {\n\t\tTextureType texture = getTextureType(connection);\n\t\tif (_textureBufferPowered) {\n\t\t\treturn texture.powered;\n\t\t} else if (Configs.LOGISTICS_POWER_USAGE_DISABLED) {\n\t\t\treturn texture.normal;\n\t\t} else {\n\t\t\treturn texture.unpowered;\n\t\t}\n\t}\n\n\tpublic void addCrashReport(CrashReportCategory crashReportCategory) {\n\t\taddRouterCrashReport(crashReportCategory);\n\t\tcrashReportCategory.addCrashSection(\"stillNeedReplace\", stillNeedReplace);\n\t}\n\n\tprotected void addRouterCrashReport(CrashReportCategory crashReportCategory) {\n\t\tcrashReportCategory.addCrashSection(\"Router\", getRouter().toString());\n\t}\n\n\t/* --- CCCommands --- */\n\t@CCCommand(description = \"Returns the Router UUID as an integer; all pipes have a unique ID (runtime stable)\")\n\tpublic int getRouterId() {\n\t\treturn getRouter().getSimpleID();\n\t}\n\n\t@CCCommand(description = \"Returns the Router UUID; all pipes have a unique ID (lifetime stable)\")\n\tpublic String getRouterUUID() {\n\t\treturn getRouter().getId().toString();\n\t}\n\n\t@CCCommand(description = \"Returns the Router UUID for the givvin router Id\")\n\tpublic String getRouterUUID(Double id) {\n\t\tIRouter router = SimpleServiceLocator.routerManager.getRouter(id.intValue());\n\t\tif (router == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn router.getId().toString();\n\t}\n\n\t@CCCommand(description = \"Returns the TurtleConnect targeted for this Turtle on this LogisticsPipe\")\n\t@CCDirectCall\n\tpublic boolean getTurtleConnect() {\n\t\tif (container != null) {\n\t\t\treturn container.getTurtleConnect();\n\t\t}\n\t\treturn false;\n\t}\n\n\t@CCCommand(description = \"Sets the TurtleConnect targeted for this Turtle on this LogisticsPipe\")\n\t@CCDirectCall\n\tpublic void setTurtleConnect(Boolean flag) {\n\t\tif (container != null) {\n\t\t\tcontainer.setTurtleConnect(flag);\n\t\t}\n\t}\n\n\t@CCCommand(description = \"Returns true if the computer is allowed to interact with the connected pipe.\", needPermission = false)\n\tpublic boolean canAccess() {\n\t\tISecurityProvider sec = getSecurityProvider();\n\t\tif (sec != null) {\n\t\t\tint id = -1;\n\t\t\tif (container != null) {\n\t\t\t\tid = container.getLastCCID();\n\t\t\t}\n\t\t\treturn sec.getAllowCC(id);\n\t\t}\n\t\treturn true;\n\t}\n\n\t@CCCommand(description = \"Sends a message to the given computerId over the LP network. Event: \" + CCConstants.LP_CC_MESSAGE_EVENT)\n\t@CCDirectCall\n\tpublic void sendMessage(final Double computerId, final Object message) {\n\t\tint sourceId = -1;\n\t\tif (container != null) {\n\t\t\tsourceId = SimpleServiceLocator.ccProxy.getLastCCID(container);\n\t\t}\n\t\tfinal int fSourceId = sourceId;\n\t\tBitSet set = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\tgetRouter().getIRoutersByCost().stream()\n\t\t\t\t.filter(exit -> !set.get(exit.destination.getSimpleID()))\n\t\t\t\t.forEach(exit -> {\n\t\t\t\t\texit.destination.queueTask(10, (pipe, router1) -> pipe.handleMesssage(computerId.intValue(), message, fSourceId));\n\t\t\t\t\tset.set(exit.destination.getSimpleID());\n\t\t\t\t});\n\t}\n\n\t@CCCommand(description = \"Sends a broadcast message to all Computer connected to this LP network. Event: \" + CCConstants.LP_CC_BROADCAST_EVENT)\n\t@CCDirectCall\n\tpublic void sendBroadcast(final String message) {\n\t\tint sourceId = -1;\n\t\tif (container != null) {\n\t\t\tsourceId = SimpleServiceLocator.ccProxy.getLastCCID(container);\n\t\t}\n\t\tfinal int fSourceId = sourceId;\n\t\tBitSet set = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\tgetRouter().getIRoutersByCost().stream()\n\t\t\t\t.filter(exit -> !set.get(exit.destination.getSimpleID()))\n\t\t\t\t.forEach(exit -> {\n\t\t\t\t\texit.destination.queueTask(10, (pipe, router1) -> pipe.handleBroadcast(message, fSourceId));\n\t\t\t\t\tset.set(exit.destination.getSimpleID());\n\t\t\t\t});\n\t}\n\n\t@CCCommand(description = \"Returns the access to the pipe of the given router UUID\")\n\t@ModDependentMethod(modId = LPConstants.computerCraftModID)\n\t@CCDirectCall\n\tpublic Object getPipeForUUID(String sUuid) throws PermissionException {\n\t\tif (!getUpgradeManager().hasCCRemoteControlUpgrade()) {\n\t\t\tthrow new PermissionException();\n\t\t}\n\t\tUUID uuid = UUID.fromString(sUuid);\n\t\tint id = SimpleServiceLocator.routerManager.getIDforUUID(uuid);\n\t\tIRouter router = SimpleServiceLocator.routerManager.getRouter(id);\n\t\tif (router == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn router.getPipe();\n\t}\n\n\t@CCCommand(description = \"Returns the global LP object which is used to access general LP methods.\", needPermission = false)\n\t@CCDirectCall\n\tpublic Object getLP() throws PermissionException {\n\t\treturn LogisticsPipes.getComputerLP();\n\t}\n\n\t@CCCommand(description = \"Returns true if the pipe has an internal module\")\n\tpublic boolean hasLogisticsModule() {\n\t\treturn getLogisticsModule() != null;\n\t}\n\n\tprivate void handleMesssage(int computerId, Object message, int sourceId) {\n\t\tif (container != null) {\n\t\t\tcontainer.handleMesssage(computerId, message, sourceId);\n\t\t}\n\t}\n\n\tprivate void handleBroadcast(String message, int sourceId) {\n\t\tqueueEvent(CCConstants.LP_CC_BROADCAST_EVENT, new Object[] { sourceId, message });\n\t}\n\n\tpublic void onWrenchClicked(EntityPlayer entityplayer) {\n\t\t//do nothing, every pipe with a GUI should either have a LogisticsGuiModule or override this method\n\t}\n\n\tpublic void handleRFPowerArival(double toSend) {\n\t\tpowerHandler.addRFPower(toSend);\n\t}\n\n\tpublic void handleIC2PowerArival(double toSend) {\n\t\tpowerHandler.addIC2Power(toSend);\n\t}\n\n\t/* ISendRoutedItem */\n\n\t@Override\n\tpublic IRoutedItem sendStack(@Nonnull ItemStack stack, Pair<Integer, SinkReply> reply, ItemSendMode mode, @Nonnull EnumFacing direction) {\n\t\tIRoutedItem itemToSend = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);\n\t\titemToSend.setDestination(reply.getValue1());\n\t\tif (reply.getValue2().isPassive) {\n\t\t\tif (reply.getValue2().isDefault) {\n\t\t\t\titemToSend.setTransportMode(TransportMode.Default);\n\t\t\t} else {\n\t\t\t\titemToSend.setTransportMode(TransportMode.Passive);\n\t\t\t}\n\t\t}\n\t\titemToSend.setAdditionalTargetInformation(reply.getValue2().addInfo);\n\t\tqueueRoutedItem(itemToSend, direction, mode);\n\t\treturn itemToSend;\n\t}\n\n\t@Override\n\tpublic IRoutedItem sendStack(@Nonnull ItemStack stack, int destination, ItemSendMode mode, IAdditionalTargetInformation info, @Nonnull EnumFacing direction) {\n\t\tIRoutedItem itemToSend = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);\n\t\titemToSend.setDestination(destination);\n\t\titemToSend.setTransportMode(TransportMode.Active);\n\t\titemToSend.setAdditionalTargetInformation(info);\n\t\tqueueRoutedItem(itemToSend, direction, mode);\n\t\treturn itemToSend;\n\t}\n\n\t@Override\n\tpublic LogisticsItemOrderManager getItemOrderManager() {\n\t\t_orderItemManager = _orderItemManager != null ? _orderItemManager : new LogisticsItemOrderManager(this);\n\t\treturn _orderItemManager;\n\t}\n\n\tpublic LogisticsOrderManager<?, ?> getOrderManager() {\n\t\treturn getItemOrderManager();\n\t}\n\n\tpublic void addPipeSign(EnumFacing dir, IPipeSign type, EntityPlayer player) {\n\t\tif (dir.ordinal() < 6) {\n\t\t\tif (signItem[dir.ordinal()] == null) {\n\t\t\t\tsignItem[dir.ordinal()] = type;\n\t\t\t\tsignItem[dir.ordinal()].init(this, dir);\n\t\t\t}\n\t\t\tif (container != null) {\n\t\t\t\tsendSignData(player, true);\n\t\t\t\trefreshRender(false);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void sendSignData(EntityPlayer player, boolean sendToAll) {\n\t\tList<Integer> types = new ArrayList<>();\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (signItem[i] == null) {\n\t\t\t\ttypes.add(-1);\n\t\t\t} else {\n\t\t\t\tList<Class<? extends IPipeSign>> typeClasses = ItemPipeSignCreator.signTypes;\n\t\t\t\tfor (int j = 0; j < typeClasses.size(); j++) {\n\t\t\t\t\tif (typeClasses.get(j) == signItem[i].getClass()) {\n\t\t\t\t\t\ttypes.add(j);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tModernPacket packet = PacketHandler.getPacket(PipeSignTypes.class).setTypes(types).setTilePos(container);\n\t\tif (sendToAll) {\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(container, packet);\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (signItem[i] != null) {\n\t\t\t\tpacket = signItem[i].getPacket();\n\t\t\t\tif (packet != null) {\n\t\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(container, packet);\n\t\t\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void removePipeSign(EnumFacing dir, EntityPlayer player) {\n\t\tif (dir.ordinal() < 6) {\n\t\t\tsignItem[dir.ordinal()] = null;\n\t\t}\n\t\tsendSignData(player, true);\n\t\trefreshRender(false);\n\t}\n\n\tpublic boolean hasPipeSign(EnumFacing dir) {\n\t\tif (dir.ordinal() < 6) {\n\t\t\treturn signItem[dir.ordinal()] != null;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void activatePipeSign(EnumFacing dir, EntityPlayer player) {\n\t\tif (dir.ordinal() < 6) {\n\t\t\tif (signItem[dir.ordinal()] != null) {\n\t\t\t\tsignItem[dir.ordinal()].activate(player);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic List<Pair<EnumFacing, IPipeSign>> getPipeSigns() {\n\t\tList<Pair<EnumFacing, IPipeSign>> list = new ArrayList<>();\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (signItem[i] != null) {\n\t\t\t\tlist.add(new Pair<>(EnumFacingUtil.getOrientation(i), signItem[i]));\n\t\t\t}\n\t\t}\n\t\treturn list;\n\t}\n\n\tpublic void handleSignPacket(List<Integer> types) {\n\t\tif (!MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tint integer = types.get(i);\n\t\t\tif (integer >= 0) {\n\t\t\t\tClass<? extends IPipeSign> type = ItemPipeSignCreator.signTypes.get(integer);\n\t\t\t\tif (signItem[i] == null || signItem[i].getClass() != type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsignItem[i] = type.newInstance();\n\t\t\t\t\t\tsignItem[i].init(this, EnumFacingUtil.getOrientation(i));\n\t\t\t\t\t} catch (InstantiationException | IllegalAccessException e) {\n\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsignItem[i] = null;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Nullable\n\tpublic IPipeSign getPipeSign(@Nullable EnumFacing dir) {\n\t\tif (dir == null) return null;\n\t\treturn signItem[dir.ordinal()];\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeBoolean(isOpaque());\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tisOpaqueClientSide = input.readBoolean();\n\t}\n\n\t@Override\n\tpublic boolean isOpaque() {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn Configs.OPAQUE || isOpaqueClientSide;\n\t\t} else {\n\t\t\treturn Configs.OPAQUE || this.getUpgradeManager().isOpaque();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addStatusInformation(List<StatusEntry> status) {\n\t\tStatusEntry entry = new StatusEntry();\n\t\tentry.name = \"Send Queue\";\n\t\tentry.subEntry = new ArrayList<>();\n\t\tfor (Triplet<IRoutedItem, EnumFacing, ItemSendMode> part : _sendQueue) {\n\t\t\tStatusEntry subEntry = new StatusEntry();\n\t\t\tsubEntry.name = part.toString();\n\t\t\tentry.subEntry.add(subEntry);\n\t\t}\n\t\tstatus.add(entry);\n\t\tentry = new StatusEntry();\n\t\tentry.name = \"In Transit To Me\";\n\t\tentry.subEntry = new ArrayList<>();\n\t\tfor (ItemRoutingInformation part : _inTransitToMe) {\n\t\t\tStatusEntry subEntry = new StatusEntry();\n\t\t\tsubEntry.name = part.toString();\n\t\t\tentry.subEntry.add(subEntry);\n\t\t}\n\t\tstatus.add(entry);\n\t}\n\n\t@Override\n\tpublic int getSourceID() {\n\t\treturn getRouterId();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic DebugLogController getDebug() {\n\t\treturn debug;\n\t}\n\n\t@Override\n\tpublic void setPreventRemove(boolean flag) {\n\t\tpreventRemove = flag;\n\t}\n\n\t@Override\n\tpublic boolean isRoutedPipe() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic double getDistanceTo(int destinationint, EnumFacing ignore, ItemIdentifier ident, boolean isActive, double traveled, double max,\n\t\t\tList<DoubleCoordinates> visited) {\n\t\tif (!stillNeedReplace) {\n\t\t\tif (getRouterId() == destinationint) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tExitRoute route = getRouter().getExitFor(destinationint, isActive, ident);\n\t\t\tif (route != null && route.exitOrientation != ignore) {\n\t\t\t\tif (route.distanceToDestination + traveled >= max) {\n\t\t\t\t\treturn Integer.MAX_VALUE;\n\t\t\t\t}\n\t\t\t\treturn route.distanceToDestination;\n\t\t\t}\n\t\t}\n\t\treturn Integer.MAX_VALUE;\n\t}\n\n\tprotected void triggerConnectionCheck() {\n\t\trecheckConnections = true;\n\t}\n\n\t@Override\n\tpublic CacheHolder getCacheHolder() {\n\t\tif (cacheHolder == null) {\n\t\t\tif (container instanceof ILPTEInformation && ((ILPTEInformation) container).getLPTileEntityObject() != null) {\n\t\t\t\tcacheHolder = ((ILPTEInformation) container).getLPTileEntityObject().getCacheHolder();\n\t\t\t} else {\n\t\t\t\tcacheHolder = new CacheHolder();\n\t\t\t}\n\t\t}\n\t\treturn cacheHolder;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn LogisticsRenderPipe.secondRenderer;\n\t}\n\n\tpublic enum ItemSendMode {\n\t\tNormal,\n\t\tFast\n\t}\n\n\t@Override\n\tpublic void finishInit() {\n\t\tsuper.finishInit();\n\t\tif (isInitialized()) {\n\t\t\tMainProxy.runOnServer(getWorld(), () -> () -> {\n\t\t\t\tif (this instanceof PropertyHolder) {\n\t\t\t\t\tUtilKt.addObserver(((PropertyHolder) this).getProperties(), (prop) -> {\n\t\t\t\t\t\tmarkTileDirty();\n\t\t\t\t\t\treturn Unit.INSTANCE;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (getLogisticsModule() != null) {\n\t\t\t\tgetLogisticsModule().finishInit();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/CoreUnroutedPipe.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.api.ILPPipe;\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.IClientState;\nimport logisticspipes.interfaces.IPipeUpgradeManager;\nimport logisticspipes.pipes.basic.debug.DebugLogController;\nimport logisticspipes.pipes.basic.debug.StatusEntry;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.renderer.IIconProvider;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeTransportLogistics;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic abstract class CoreUnroutedPipe implements IClientState, ILPPipe, ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\t@Nullable\n\tpublic LogisticsTileGenericPipe container;\n\tpublic final PipeTransportLogistics transport;\n\tpublic final Item item;\n\tpublic DebugLogController debug = new DebugLogController(this);\n\n\tprivate boolean initialized = false;\n\n\tpublic CoreUnroutedPipe(PipeTransportLogistics transport, Item item) {\n\t\tthis.transport = transport;\n\t\tthis.item = item;\n\t}\n\n\tpublic void setTile(TileEntity tile) {\n\t\tcontainer = (LogisticsTileGenericPipe) tile;\n\t\ttransport.setTile((LogisticsTileGenericPipe) tile);\n\t}\n\n\tpublic boolean blockActivated(EntityPlayer entityplayer) {\n\t\treturn false;\n\t}\n\n\tpublic void onBlockPlaced() {\n\t\ttransport.onBlockPlaced();\n\t}\n\n\tpublic void onBlockPlacedBy(EntityLivingBase placer) {}\n\n\tpublic void onNeighborBlockChange() {\n\t\ttransport.onNeighborBlockChange();\n\t}\n\n\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing side) {\n\t\tCoreUnroutedPipe otherPipe;\n\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\totherPipe = ((LogisticsTileGenericPipe) tile).pipe;\n\t\t\tif (!LogisticsBlockGenericPipe.isFullyDefined(otherPipe)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn transport.canPipeConnect(tile, side);\n\t}\n\n\t/**\n\t * Should return the textureindex used by the Pipe Item Renderer, as this is\n\t * done client-side the default implementation might not work if your\n\t * getTextureIndex(Orienations.Unknown) has logic. Then override this\n\t */\n\tpublic int getIconIndexForItem() {\n\t\treturn getIconIndex(null);\n\t}\n\n\t/**\n\t * Should return the IIconProvider that provides icons for this pipe\n\t *\n\t * @return An array of icons\n\t */\n\t@SideOnly(Side.CLIENT)\n\tpublic IIconProvider getIconProvider() {\n\t\treturn Textures.LPpipeIconProvider;\n\t}\n\n\t/**\n\t * Should return the index in the array returned by GetTextureIcons() for a\n\t * specified direction\n\t *\n\t * @param direction - The direction for which the indexed should be rendered.\n\t *                  Unknown for pipe center\n\t * @return An index valid in the array returned by getTextureIcons()\n\t */\n\tpublic abstract int getIconIndex(EnumFacing direction);\n\n\tpublic void updateEntity() {\n\t\ttransport.updateEntity();\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound data) {\n\t\ttransport.writeToNBT(data);\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound data) {\n\t\ttransport.readFromNBT(data);\n\t}\n\n\tpublic boolean needsInit() {\n\t\treturn !initialized;\n\t}\n\n\tpublic void initialize() {\n\t\ttransport.initialize();\n\t\tinitialized = true;\n\t}\n\n\tpublic void onBlockRemoval() {}\n\n\t@Nullable\n\tpublic LogisticsTileGenericPipe getContainer() {\n\t\treturn container;\n\t}\n\n\tpublic NonNullList<ItemStack> dropContents() {\n\t\treturn transport.dropContents();\n\t}\n\n\t/**\n\t * Called when TileGenericPipe.invalidate() is called\n\t */\n\tpublic void invalidate() {}\n\n\t/**\n\t * Called when TileGenericPipe.validate() is called\n\t */\n\tpublic void validate() {}\n\n\t/**\n\t * Called when TileGenericPipe.onChunkUnload is called\n\t */\n\tpublic void onChunkUnload() {}\n\n\tpublic World getWorld() {\n\t\tif (container == null) return null;\n\t\treturn container.getWorld();\n\t}\n\n\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing direction, boolean flag) {\n\t\treturn canPipeConnect(tile, direction);\n\t}\n\n\tpublic boolean isSideBlocked(EnumFacing side, boolean ignoreSystemDisconnection) {\n\t\treturn false;\n\t}\n\n\tpublic final int getX() {\n\t\treturn getPos().getX();\n\t}\n\n\tpublic final int getY() {\n\t\treturn getPos().getY();\n\t}\n\n\tpublic final int getZ() {\n\t\treturn getPos().getZ();\n\t}\n\n\t@Nonnull\n\tpublic final BlockPos getPos() {\n\t\treturn container.getPos();\n\t}\n\n\tpublic boolean canBeDestroyed() {\n\t\treturn true;\n\t}\n\n\tpublic boolean destroyByPlayer() {\n\t\treturn false;\n\t}\n\n\tpublic void setPreventRemove(boolean flag) {}\n\n\tpublic boolean preventRemove() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isRoutedPipe() {\n\t\treturn false;\n\t}\n\n\tpublic boolean isFluidPipe() {\n\t\treturn false;\n\t}\n\n\tpublic abstract int getTextureIndex();\n\n\tpublic void triggerDebug() {\n\t\tif (debug.debugThisPipe) {\n\t\t\tSystem.out.print(\"\");\n\t\t}\n\t}\n\n\tpublic void addStatusInformation(List<StatusEntry> status) {}\n\n\tpublic boolean isOpaque() {\n\t\treturn Configs.OPAQUE;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tif (container == null) {\n\t\t\treturn getClass().getName() + \"(NO CONTAINER)\";\n\t\t} else {\n\t\t\treturn String.format(\"%s(%s)\", getClass().getName(), container.getPos());\n\t\t}\n\t}\n\n\tpublic DoubleCoordinates getLPPosition() {\n\t\treturn new DoubleCoordinates(this);\n\t}\n\n\tpublic IPipeUpgradeManager getUpgradeManager() {\n\t\treturn new IPipeUpgradeManager() {\n\n\t\t\t@Override\n\t\t\tpublic boolean hasPowerPassUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasRFPowerSupplierUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasBCPowerSupplierUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getIC2PowerLevel() {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getSpeedUpgradeCount() {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isSideDisconnected(EnumFacing side) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasCCRemoteControlUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasCraftingMonitoringUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isOpaque() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasUpgradeModuleUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasCombinedSneakyUpgrade() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic EnumFacing[] getCombinedSneakyOrientation() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic double getDistanceTo(int destinationint, EnumFacing ignore, ItemIdentifier ident, boolean isActive, double travled, double max, List<DoubleCoordinates> visited) {\n\t\tdouble lowest = Integer.MAX_VALUE;\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (ignore == dir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tIPipeInformationProvider information = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(container.getNextConnectedTile(dir));\n\t\t\tif (information != null) {\n\t\t\t\tDoubleCoordinates pos = new DoubleCoordinates(information);\n\t\t\t\tif (visited.contains(pos)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tvisited.add(pos);\n\n\t\t\t\tlowest = information.getDistanceTo(destinationint, dir.getOpposite(), ident, isActive, travled, Math.min(max, lowest), visited);\n\n\t\t\t\tvisited.remove(pos);\n\t\t\t}\n\t\t}\n\t\treturn lowest;\n\t}\n\n\tpublic boolean isMultiBlock() {\n\t\treturn false;\n\t}\n\n\tpublic boolean actAsNormalPipe() {\n\t\treturn true;\n\t}\n\n\tpublic boolean isHSTube() {\n\t\treturn false;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic ISpecialPipeRenderer getSpecialRenderer() {\n\t\treturn null;\n\t}\n\n\tpublic boolean hasSpecialPipeEndAt(EnumFacing dir) {\n\t\treturn false;\n\t}\n\n\tpublic DoubleCoordinates getItemRenderPos(float fPos, LPTravelingItem travelItem) {\n\t\tDoubleCoordinates pos = new DoubleCoordinates(0.5, 0.5, 0.5);\n\t\tif (fPos < 0.5) {\n\t\t\tif (travelItem.input == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!container.renderState.pipeConnectionMatrix.isConnected(travelItem.input.getOpposite())) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tCoordinateUtils.add(pos, travelItem.input.getOpposite(), 0.5 - fPos);\n\t\t} else {\n\t\t\tif (travelItem.output == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!container.renderState.pipeConnectionMatrix.isConnected(travelItem.output)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tCoordinateUtils.add(pos, travelItem.output, fPos - 0.5);\n\t\t}\n\t\treturn pos;\n\t}\n\n\tpublic double getBoxRenderScale(float fPos, LPTravelingItem travelItem) {\n\t\tdouble boxScale = 1;\n\t\tif (container.renderState.pipeConnectionMatrix.isTDConnected(travelItem.input.getOpposite())) {\n\t\t\tboxScale = (fPos * (1 - 0.65)) + 0.65;\n\t\t}\n\t\tif (container.renderState.pipeConnectionMatrix.isTDConnected(travelItem.output)) {\n\t\t\tboxScale = ((1 - fPos) * (1 - 0.65)) + 0.65;\n\t\t}\n\t\tif (container.renderState.pipeConnectionMatrix.isTDConnected(travelItem.input.getOpposite()) && container.renderState.pipeConnectionMatrix.isTDConnected(travelItem.output)) {\n\t\t\tboxScale = 0.65;\n\t\t}\n\t\treturn boxScale;\n\t}\n\n\tpublic double getItemRenderPitch(float fPos, LPTravelingItem travelItem) {\n\t\treturn 0;\n\t}\n\n\tpublic double getItemRenderYaw(float fPos, LPTravelingItem travelItem) {\n\t\treturn 0;\n\t}\n\n\tpublic boolean isInitialized() {\n\t\treturn container != null;\n\t}\n\n\tpublic abstract IHighlightPlacementRenderer getHighlightRenderer();\n\n\tpublic World getWorldForHUD() {\n\t\treturn getWorld();\n\t}\n\n\tpublic boolean isMultipartAllowedInPipe() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n\tprotected void updateAdjacentCache() {}\n\n\t/**\n\t * Triggers connection checks for routing.\n\t */\n\tprotected void triggerConnectionCheck() {}\n\n\t/**\n\t * Called after reading data from NBT.\n\t */\n\tpublic void finishInit() {}\n\n\tpublic boolean isPipeBlock() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/ItemInsertionHandler.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.items.IItemHandler;\n\nimport logisticspipes.interfaces.ILPItemAcceptor;\n\npublic class ItemInsertionHandler implements IItemHandler {\n\n\tpublic static final List<ILPItemAcceptor> ACCEPTORS = new ArrayList<>();\n\n\tprivate final LogisticsTileGenericPipe pipe;\n\tprivate final EnumFacing dir;\n\n\tpublic ItemInsertionHandler(LogisticsTileGenericPipe pipe, EnumFacing dir) {\n\t\tthis.pipe = pipe;\n\t\tthis.dir = dir;\n\t}\n\n\t@Override\n\tpublic int getSlots() {\n\t\treturn 1;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack getStackInSlot(int slot) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {\n\t\tif (!simulate) {\n\t\t\treturn handleItemInsetion(pipe, dir, stack);\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack extractItem(int slot, int amount, boolean simulate) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\tpublic int getSlotLimit(int slot) {\n\t\treturn 64;\n\t}\n\n\t@Nonnull\n\tpublic static ItemStack handleItemInsetion(LogisticsTileGenericPipe pipe, EnumFacing from, @Nonnull ItemStack stack) {\n\t\tfor (ILPItemAcceptor acceptor : ACCEPTORS) {\n\t\t\tif (acceptor.accept(pipe, from, stack)) {\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t}\n\t\treturn pipe.insertItem(from, stack);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/LogisticsBlockGenericPipe.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Random;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.properties.PropertyBool;\nimport net.minecraft.block.properties.PropertyEnum;\nimport net.minecraft.block.properties.PropertyInteger;\nimport net.minecraft.block.state.BlockFaceShape;\nimport net.minecraft.block.state.BlockStateContainer;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.Particle;\nimport net.minecraft.client.particle.ParticleManager;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.init.Items;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.BlockRenderLayer;\nimport net.minecraft.util.EnumBlockRenderType;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.EnumParticleTypes;\nimport net.minecraft.util.IStringSerializable;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.property.IExtendedBlockState;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\nimport net.minecraftforge.registries.IForgeRegistry;\n\nimport static logisticspipes.LPConstants.PIPE_MAX_POS;\nimport static logisticspipes.LPConstants.PIPE_MIN_POS;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.IRotationProvider;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.ltgpmodcompat.LPMicroblockBlock;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.renderer.newpipe.PropertyCache;\nimport logisticspipes.renderer.newpipe.PropertyRenderList;\nimport logisticspipes.ticks.QueuedTasks;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.proxy.mcmp.BlockAccessDelegate;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class LogisticsBlockGenericPipe extends LPMicroblockBlock {\n\n\tpublic static boolean ignoreSideRayTrace = false;\n\tpublic static Map<Item, Function<Item, ? extends CoreUnroutedPipe>> pipes = new HashMap<>();\n\tpublic static Map<DoubleCoordinates, CoreUnroutedPipe> pipeRemoved = new HashMap<>();\n\tpublic static Map<DoubleCoordinates, BlockPos> pipeSubMultiRemoved = new HashMap<>();\n\tprivate static long lastRemovedDate = -1;\n\tprotected final Random rand = new Random();\n\n\tpublic static final PropertyInteger rotationProperty = PropertyInteger.create(\"rotation\", 0, 3);\n\tpublic static final PropertyEnum<PipeRenderModel> modelTypeProperty = PropertyEnum.create(\"model_type\", PipeRenderModel.class);\n\tpublic static final Map<EnumFacing, PropertyBool> connectionPropertys = Arrays.stream(EnumFacing.values()).collect(Collectors\n\t\t\t.toMap(key -> key, key -> PropertyBool.create(\"connection_\" + key.ordinal())));\n\n\tpublic static final PropertyRenderList propertyRenderList = new PropertyRenderList();\n\tpublic static final PropertyCache propertyCache = new PropertyCache();\n\n\tpublic static final AxisAlignedBB PIPE_CENTER_BB = new AxisAlignedBB(PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MAX_POS, PIPE_MAX_POS, PIPE_MAX_POS);\n\tpublic static final List<AxisAlignedBB> PIPE_CONN_BB = Arrays.asList(\n\t\t\tnew AxisAlignedBB(PIPE_MIN_POS, 0, PIPE_MIN_POS, PIPE_MAX_POS, PIPE_MIN_POS, PIPE_MAX_POS),\n\t\t\tnew AxisAlignedBB(PIPE_MIN_POS, PIPE_MAX_POS, PIPE_MIN_POS, PIPE_MAX_POS, 1, PIPE_MAX_POS),\n\t\t\tnew AxisAlignedBB(PIPE_MIN_POS, PIPE_MIN_POS, 0, PIPE_MAX_POS, PIPE_MAX_POS, PIPE_MIN_POS),\n\t\t\tnew AxisAlignedBB(PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MAX_POS, PIPE_MAX_POS, PIPE_MAX_POS, 1),\n\t\t\tnew AxisAlignedBB(0, PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MAX_POS, PIPE_MAX_POS),\n\t\t\tnew AxisAlignedBB(PIPE_MAX_POS, PIPE_MIN_POS, PIPE_MIN_POS, 1, PIPE_MAX_POS, PIPE_MAX_POS)\n\t);\n\n\tpublic enum PipeRenderModel implements IStringSerializable {\n\t\tNONE,\n\t\tREQUEST_TABLE;\n\n\t\t@Override\n\t\tpublic String getName() {\n\t\t\treturn name().toLowerCase();\n\t\t}\n\t}\n\n\tpublic LogisticsBlockGenericPipe() {\n\t\tsuper(Material.GLASS);\n\t\tIBlockState state = this.blockState.getBaseState()\n\t\t\t\t.withProperty(rotationProperty, 0)\n\t\t\t\t.withProperty(modelTypeProperty, PipeRenderModel.NONE);\n\t\tconnectionPropertys.values().forEach(it -> state.withProperty(it, false));\n\t\tsetDefaultState(state);\n\t\tsetCreativeTab(LogisticsPipes.CREATIVE_TAB_LP);\n\t}\n\n\tpublic static void removePipe(CoreUnroutedPipe pipe) {\n\t\tif (!LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (pipe.canBeDestroyed() || pipe.destroyByPlayer()) {\n\t\t\tpipe.onBlockRemoval();\n\t\t} else if (pipe.preventRemove()) {\n\t\t\tLogisticsBlockGenericPipe.cacheTileToPreventRemoval(pipe);\n\t\t}\n\n\t\tWorld world = pipe.container.getWorld();\n\n\t\tif (LogisticsBlockGenericPipe.lastRemovedDate != world.getTotalWorldTime()) {\n\t\t\tLogisticsBlockGenericPipe.lastRemovedDate = world.getTotalWorldTime();\n\t\t\tLogisticsBlockGenericPipe.pipeRemoved.clear();\n\t\t\tLogisticsBlockGenericPipe.pipeSubMultiRemoved.clear();\n\t\t}\n\n\t\tif (pipe.isMultiBlock()) {\n\t\t\tif (pipe.preventRemove()) {\n\t\t\t\tthrow new UnsupportedOperationException(\"A multi block can't be protected against removal.\");\n\t\t\t}\n\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> list = ((CoreMultiBlockPipe) pipe).getRotatedSubBlocks();\n\t\t\tlist.forEach(pos -> pos.add(new DoubleCoordinates(pipe)));\n\t\t\tfor (DoubleCoordinates pos : pipe.container.subMultiBlock) {\n\t\t\t\tTileEntity tile = pos.getTileEntity(world);\n\t\t\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\t\tDoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare> equ = list.findClosest(pos);\n\t\t\t\t\tif (equ != null) {\n\t\t\t\t\t\t((LogisticsTileGenericSubMultiBlock) tile).removeSubType(equ.getType());\n\t\t\t\t\t}\n\t\t\t\t\tif (((LogisticsTileGenericSubMultiBlock) tile).removeMainPipe(new DoubleCoordinates(pipe))) {\n\t\t\t\t\t\tLogisticsBlockGenericSubMultiBlock.redirectedToMainPipe = true;\n\t\t\t\t\t\tpos.setBlockToAir(world);\n\t\t\t\t\t\tLogisticsBlockGenericSubMultiBlock.redirectedToMainPipe = false;\n\t\t\t\t\t\tLogisticsBlockGenericPipe.pipeSubMultiRemoved.put(new DoubleCoordinates(pos), pipe.container.getPos());\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(tile, ((LogisticsTileGenericSubMultiBlock) tile).getLPDescriptionPacket());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tBlockPos pos = pipe.container.getPos();\n\t\tLogisticsBlockGenericPipe.pipeRemoved.put(new DoubleCoordinates(pos), pipe);\n\t\tworld.removeTileEntity(pos);\n\t}\n\n\t/* Registration ******************************************************** */\n\tpublic static ItemLogisticsPipe registerPipe(IForgeRegistry<Item> registry, String name, Function<Item, ? extends CoreUnroutedPipe> constructor) {\n\t\tItemLogisticsPipe item = new ItemLogisticsPipe();\n\t\tLogisticsPipes.setName(item, String.format(\"pipe_%s\", name));\n\n\t\tLogisticsBlockGenericPipe.pipes.put(item, constructor);\n\n\t\tCoreUnroutedPipe dummyPipe = LogisticsBlockGenericPipe.createPipe(item);\n\t\tif (dummyPipe != null) {\n\t\t\titem.setPipeIconIndex(dummyPipe.getIconIndexForItem(), dummyPipe.getTextureIndex());\n\t\t\tMainProxy.proxy.setIconProviderFromPipe(item, dummyPipe);\n\t\t\titem.setDummyPipe(dummyPipe);\n\t\t}\n\n\t\tregistry.register(item);\n\t\treturn item;\n\t}\n\n\tpublic static CoreUnroutedPipe createPipe(Item key) {\n\t\tFunction<Item, ? extends CoreUnroutedPipe> pipe = LogisticsBlockGenericPipe.pipes.get(key);\n\t\tif (pipe != null) {\n\t\t\treturn pipe.apply(key);\n\t\t} else {\n\t\t\tLogisticsPipes.log.warn(\"Detected pipe with unknown key (\" + key + \"). This should not have happend.\");\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static boolean placePipe(CoreUnroutedPipe pipe, World world, BlockPos blockPos, Block block) {\n\t\treturn LogisticsBlockGenericPipe.placePipe(pipe, world, blockPos, block, null);\n\t}\n\n\tpublic static boolean placePipe(CoreUnroutedPipe pipe, World world, BlockPos blockPos, Block block, ITubeOrientation orientation) {\n\t\tIBlockState oldBlockState = world.getBlockState(blockPos);\n\t\tboolean placed = world.setBlockState(blockPos, block.getDefaultState(), 0);\n\n\t\tif (world.isRemote) {\n\t\t\treturn placed;\n\t\t}\n\n\t\tif (placed) {\n\t\t\tTileEntity tile = world.getTileEntity(blockPos);\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\tLogisticsTileGenericPipe tilePipe = (LogisticsTileGenericPipe) tile;\n\t\t\t\tif (pipe instanceof CoreMultiBlockPipe) {\n\t\t\t\t\tif (orientation == null) {\n\t\t\t\t\t\tthrow new NullPointerException();\n\t\t\t\t\t}\n\t\t\t\t\tCoreMultiBlockPipe mPipe = (CoreMultiBlockPipe) pipe;\n\t\t\t\t\torientation.setOnPipe(mPipe);\n\t\t\t\t\tDoubleCoordinates placeAt = new DoubleCoordinates(blockPos);\n\t\t\t\t\tLogisticsBlockGenericSubMultiBlock.currentCreatedMultiBlock = placeAt;\n\t\t\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> positions = ((CoreMultiBlockPipe) pipe).getSubBlocks();\n\t\t\t\t\torientation.rotatePositions(positions);\n\t\t\t\t\tfor (DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare> pos : positions) {\n\t\t\t\t\t\tpos.add(placeAt);\n\t\t\t\t\t\tTileEntity subTile = world.getTileEntity(pos.getBlockPos());\n\t\t\t\t\t\tIBlockState oldSubBlockState = world.getBlockState(pos.getBlockPos());\n\t\t\t\t\t\tif (subTile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\t\t\t\t((LogisticsTileGenericSubMultiBlock) subTile).addMultiBlockMainPos(placeAt);\n\t\t\t\t\t\t\t((LogisticsTileGenericSubMultiBlock) subTile).addSubTypeTo(pos.getType());\n\t\t\t\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(subTile, ((LogisticsTileGenericSubMultiBlock) subTile).getLPDescriptionPacket());\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tworld.setBlockState(pos.getBlockPos(), LPBlocks.subMultiblock.getDefaultState(), 0);\n\t\t\t\t\t\t\tsubTile = world.getTileEntity(pos.getBlockPos());\n\t\t\t\t\t\t\tif (subTile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\t\t\t\t\t((LogisticsTileGenericSubMultiBlock) subTile).addSubTypeTo(pos.getType());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tworld.markAndNotifyBlock(pos.getBlockPos(), world.getChunk(pos.getBlockPos()), oldSubBlockState, world.getBlockState(pos.getBlockPos()), 3);\n\t\t\t\t\t}\n\t\t\t\t\tLogisticsBlockGenericSubMultiBlock.currentCreatedMultiBlock = null;\n\t\t\t\t}\n\t\t\t\ttilePipe.initialize(pipe);\n\t\t\t\t//\t\t\t\ttilePipe.sendUpdateToClient();\n\t\t\t}\n\t\t\tworld.markAndNotifyBlock(blockPos, world.getChunk(blockPos), oldBlockState, world.getBlockState(blockPos), 3);\n\t\t}\n\n\t\treturn placed;\n\t}\n\n\tpublic static CoreUnroutedPipe getPipe(IBlockAccess blockAccess, BlockPos pos) {\n\t\tTileEntity tile = blockAccess.getTileEntity(pos);\n\n\t\tif (!(tile instanceof LogisticsTileGenericPipe) || tile.isInvalid()) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn ((LogisticsTileGenericPipe) tile).pipe;\n\t\t}\n\t}\n\n\tpublic static boolean isFullyDefined(CoreUnroutedPipe pipe) {\n\t\treturn pipe != null && pipe.transport != null && pipe.container != null;\n\t}\n\n\tpublic static boolean isValid(CoreUnroutedPipe pipe) {\n\t\treturn LogisticsBlockGenericPipe.isFullyDefined(pipe);\n\t}\n\n\tprivate static void cacheTileToPreventRemoval(CoreUnroutedPipe pipe) {\n\t\tfinal World worldCache = pipe.getWorld();\n\t\tfinal BlockPos posCache = pipe.getPos();\n\t\tfinal TileEntity tileCache = pipe.container;\n\t\tfinal CoreUnroutedPipe fPipe = pipe;\n\t\tfPipe.setPreventRemove(true);\n\t\tQueuedTasks.queueTask(() -> {\n\t\t\tif (!fPipe.preventRemove()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tboolean changed = false;\n\t\t\tif (worldCache.getBlockState(posCache).getBlock() != LPBlocks.pipe) {\n\t\t\t\tworldCache.setBlockState(posCache, LPBlocks.pipe.getDefaultState());\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tif (worldCache.getTileEntity(posCache) != tileCache) {\n\t\t\t\tworldCache.setTileEntity(posCache, tileCache);\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tif (changed) {\n\t\t\t\tworldCache.markAndNotifyBlock(posCache, worldCache.getChunk(posCache), worldCache.getBlockState(posCache), worldCache.getBlockState(posCache), 3);\n\t\t\t}\n\t\t\tfPipe.setPreventRemove(false);\n\t\t\treturn null;\n\t\t});\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NonNullList<ItemStack> getDrops(@Nonnull IBlockAccess world, @Nonnull BlockPos pos, @Nonnull IBlockState state, int fortune) {\n\t\tNonNullList<ItemStack> list = NonNullList.create();\n\t\tif (MainProxy.isClient(world)) {\n\t\t\treturn list;\n\t\t}\n\n\t\tRandom rand = world instanceof World ? ((World) world).rand : RANDOM;\n\t\tint count = quantityDropped(state, fortune, rand);\n\t\tfor (int i = 0; i < count; i++) {\n\t\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\n\t\t\tif (pipe == null) {\n\t\t\t\tpipe = LogisticsBlockGenericPipe.pipeRemoved.get(new DoubleCoordinates(pos));\n\t\t\t}\n\n\t\t\tif (pipe != null) {\n\t\t\t\tif (pipe.item != null && (pipe.canBeDestroyed() || pipe.destroyByPlayer())) {\n\t\t\t\t\tlist.addAll(pipe.dropContents());\n\t\t\t\t\tlist.add(new ItemStack(pipe.item, 1, damageDropped(state)));\n\t\t\t\t} else if (pipe.item != null) {\n\t\t\t\t\tLogisticsBlockGenericPipe.cacheTileToPreventRemoval(pipe);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tmcmpBlockAccess.addDrops(list, world, pos, state, fortune);\n\t\treturn list;\n\t}\n\n\t@Nonnull\n\tpublic BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) {\n\t\treturn BlockFaceShape.UNDEFINED;\n\t}\n\n\tpublic void addCollisionBoxToList(LogisticsTileGenericPipe pipe, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entityIn, boolean isActualState) {\n\t\taddCollisionBoxToList(pipe.getWorld().getBlockState(pipe.getPos()), pipe.getWorld(), pipe.getPos(), entityBox, collidingBoxes, entityIn, isActualState);\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxToList(@Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull AxisAlignedBB entityBox, @Nonnull List<AxisAlignedBB> collidingBoxes, @Nullable Entity entity, boolean isActualState) {\n\t\tTileEntity te = world.getTileEntity(pos);\n\t\tif (te instanceof LogisticsTileGenericPipe) {\n\t\t\tLogisticsTileGenericPipe tile = (LogisticsTileGenericPipe) te;\n\t\t\tCoreUnroutedPipe pipe = tile.pipe;\n\t\t\tif (pipe != null && pipe.isPipeBlock()) {\n\t\t\t\taddCollisionBoxToList(pos, entityBox, collidingBoxes, Block.FULL_BLOCK_AABB);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pipe != null && pipe.isMultiBlock()) {\n\t\t\t\t((CoreMultiBlockPipe) pipe).addCollisionBoxesToList(collidingBoxes, entityBox);\n\t\t\t\tif (!pipe.actAsNormalPipe()) return;\n\t\t\t}\n\n\t\t\tArrays.stream(EnumFacing.VALUES)\n\t\t\t\t\t.filter(tile::isPipeConnectedCached)\n\t\t\t\t\t.map(f -> PIPE_CONN_BB.get(f.getIndex()))\n\t\t\t\t\t.forEach(bb -> addCollisionBoxToList(pos, entityBox, collidingBoxes, bb));\n\t\t}\n\t\taddCollisionBoxToList(pos, entityBox, collidingBoxes, PIPE_CENTER_BB);\n\t\tmcmpBlockAccess.addCollisionBoxToList(state, world, pos, entityBox, collidingBoxes, entity, isActualState);\n\t}\n\n\t@Nonnull\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, @Nonnull BlockPos pos) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).isPipeBlock()) {\n\t\t\treturn new AxisAlignedBB((double) pos.getX() + 0, (double) pos.getY() + 0, (double) pos.getZ() + 0,\n\t\t\t\t\t(double) pos.getX() + 1, (double) pos.getY() + 1, (double) pos.getZ() + 1);\n\t\t}\n\t\tInternalRayTraceResult rayTraceResult = doRayTrace(world, pos, Minecraft.getMinecraft().player);\n\n\t\tif (rayTraceResult != null && rayTraceResult.boundingBox != null) {\n\t\t\tAxisAlignedBB box = rayTraceResult.boundingBox;\n\t\t\tif (rayTraceResult.hitPart == Part.PIPE) {\n\t\t\t\tfloat scale = 0.001F;\n\t\t\t\tbox = box.expand(scale, scale, scale);\n\t\t\t}\n\t\t\treturn box.offset(pos);\n\t\t}\n\t\treturn super.getSelectedBoundingBox(state, world, pos);\n\t}\n\n\t@Override\n\tpublic RayTraceResult collisionRayTrace(IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull Vec3d start, @Nonnull Vec3d end) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).isPipeBlock()) {\n\t\t\tVec3d vec3d = start.subtract(pos.getX(), pos.getY(), pos.getZ());\n\t\t\tVec3d vec3d1 = end.subtract(pos.getX(), pos.getY(), pos.getZ());\n\t\t\tRayTraceResult raytraceresult = FULL_BLOCK_AABB.calculateIntercept(vec3d, vec3d1);\n\t\t\treturn raytraceresult == null ? null : new RayTraceResult(raytraceresult.hitVec.add(pos.getX(), pos.getY(), pos.getZ()), raytraceresult.sideHit, pos);\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe == null) { // Fallback for defect pipe\n\t\t\treturn rayTrace(pos, start, end, Block.FULL_BLOCK_AABB);\n\t\t}\n\n\t\tInternalRayTraceResult result = doRayTrace(world, pos, start, end);\n\n\t\tif (result == null) {\n\t\t\treturn mcmpBlockAccess.collisionRayTrace(state, world, pos, start, end);\n\t\t} else {\n\t\t\tRayTraceResult secondResult = mcmpBlockAccess.collisionRayTrace(state, world, pos, start, end);\n\t\t\tif (secondResult != null) {\n\t\t\t\tif (secondResult.hitVec.distanceTo(start) < result.rayTraceResult.hitVec.distanceTo(start)) {\n\t\t\t\t\treturn secondResult;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result.rayTraceResult;\n\t\t}\n\t}\n\n\tpublic InternalRayTraceResult doRayTrace(World world, BlockPos pos, EntityPlayer player) {\n\t\tdouble reachDistance = 5;\n\n\t\tif (player instanceof EntityPlayerMP) {\n\t\t\treachDistance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue();\n\t\t}\n\n\t\tdouble eyeHeight = player.getEyeHeight();\n\t\tVec3d lookVec = player.getLookVec();\n\t\tVec3d start = new Vec3d(player.posX, player.posY + eyeHeight, player.posZ);\n\t\tVec3d end = start.add(lookVec.x * reachDistance, lookVec.y * reachDistance, lookVec.z * reachDistance);\n\n\t\treturn doRayTrace(world, pos, start, end);\n\t}\n\n\tpublic InternalRayTraceResult doRayTrace(World world, BlockPos pos, Vec3d start, Vec3d end) {\n\t\tTileEntity te = world.getTileEntity(pos);\n\n\t\tif (te instanceof LogisticsTileGenericPipe) {\n\t\t\tLogisticsTileGenericPipe tileG = (LogisticsTileGenericPipe) te;\n\t\t\tCoreUnroutedPipe pipe = tileG.pipe;\n\t\t\tif (!LogisticsBlockGenericPipe.isValid(pipe)) return null;\n\n\t\t\tif (pipe.isMultiBlock()) {\n\t\t\t\tInternalRayTraceResult result1 = doRayTraceMultiblock(tileG, (CoreMultiBlockPipe) pipe, start, end);\n\n\t\t\t\tif (!pipe.actAsNormalPipe())\n\t\t\t\t\treturn result1;\n\n\t\t\t\tInternalRayTraceResult result2 = doRayTrace(tileG, pipe, start, end);\n\n\t\t\t\treturn Stream.of(result1, result2)\n\t\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t\t.min(Comparator.comparing(r -> r.rayTraceResult.hitVec.squareDistanceTo(start)))\n\t\t\t\t\t\t.orElse(null);\n\t\t\t} else {\n\t\t\t\treturn doRayTrace(tileG, pipe, start, end);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Data\n\t@AllArgsConstructor\n\tprivate static class Hit {\n\n\t\tpublic RayTraceResult rayTraceResult;\n\t\tpublic AxisAlignedBB box;\n\t\tpublic EnumFacing side;\n\t\tpublic Part part;\n\t}\n\n\tprivate InternalRayTraceResult doRayTrace(LogisticsTileGenericPipe tileG, CoreUnroutedPipe pipe, Vec3d start, Vec3d end) {\n\t\tif (tileG == null) return null;\n\t\tif (!LogisticsBlockGenericPipe.isValid(pipe)) return null;\n\n\t\t/*\n\t\t * pipe hits along x, y, and z axis, gate (all 6 sides) [and\n\t\t * wires+facades]\n\t\t */\n\t\tArrayList<Hit> list = new ArrayList<>();\n\n\t\t// pipe\n\t\tfor (EnumFacing side : LogisticsBlockGenericPipe.DIR_VALUES) {\n\t\t\tif (side == null || tileG.isPipeConnectedCached(side)) {\n\t\t\t\tif (side != null && ignoreSideRayTrace) continue;\n\t\t\t\tAxisAlignedBB bb = getPipeBoundingBox(side);\n\t\t\t\tlist.add(new Hit(rayTrace(tileG.getPos(), start, end, bb), bb, side, Part.PIPE));\n\t\t\t}\n\t\t}\n\n\t\t// pluggables\n\n\t\t/*\n\t\tfor (EnumFacing side : EnumFacing.VALUES) {\n\t\t\tif (tileG.getBCPipePluggable(side) != null) {\n\t\t\t\tif(side != null && ignoreSideRayTrace) continue;\n\t\t\t\tAxisAlignedBB bb = tileG.getBCPipePluggable(side).getBoundingBox(side);\n\t\t\t\tboxes[7 + side.ordinal()] = bb;\n\t\t\t\thits[7 + side.ordinal()] = super.collisionRayTrace(new BoundingBoxDelegateBlockState(bb, state), tileG.getWorld(), tileG.getPos(), start, end);\n\t\t\t\tsideHit[7 + side.ordinal()] = side;\n\t\t\t}\n\t\t}\n\t\t*/\n\n\t\t// TODO: check wires\n\n\t\t// get closest hit\n\n\t\treturn list.stream()\n\t\t\t\t.filter(r -> r.rayTraceResult != null)\n\t\t\t\t.min(Comparator.comparing(r -> r.rayTraceResult.hitVec.squareDistanceTo(start)))\n\t\t\t\t.map(r -> new InternalRayTraceResult(r.part, r.rayTraceResult, r.box, r.side))\n\t\t\t\t.orElse(null);\n\t}\n\n\tprivate InternalRayTraceResult doRayTraceMultiblock(LogisticsTileGenericPipe tileG, CoreMultiBlockPipe pipe, Vec3d start, Vec3d direction) {\n\t\tif (tileG == null) return null;\n\t\tif (!LogisticsBlockGenericPipe.isValid(pipe)) return null;\n\n\t\tList<RayTraceResult> hits = new ArrayList<>();\n\t\tList<AxisAlignedBB> boxes = new ArrayList<>();\n\n\t\tpipe.addCollisionBoxesToList(boxes, null);\n\n\t\twhile (hits.size() < boxes.size()) {\n\t\t\thits.add(null);\n\t\t}\n\n\t\tfor (int i = 0; i < boxes.size(); i++) {\n\t\t\tAxisAlignedBB bb = boxes.get(i);\n\t\t\thits.set(i, super.rayTrace(tileG.getPos(), start, direction, bb.offset(BlockPos.ORIGIN.subtract(tileG.getPos()))));\n\t\t}\n\n\t\treturn hits.stream()\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.min(Comparator.comparing(r -> r.hitVec.squareDistanceTo(start)))\n\t\t\t\t.map(r -> new InternalRayTraceResult(Part.PIPE, r, pipe.getCompleteBox(), null))\n\t\t\t\t.orElse(null);\n\t}\n\n\tprivate AxisAlignedBB getPipeBoundingBox(@Nullable EnumFacing side) {\n\t\tif (side == null) return PIPE_CENTER_BB;\n\t\treturn PIPE_CONN_BB.get(side.getIndex());\n\t}\n\n\t@Override\n\tpublic TileEntity createNewTileEntity(@Nonnull World world, int metadata) {\n\t\treturn new LogisticsTileGenericPipe();\n\t}\n\n\tpublic enum Part {\n\t\tPIPE,\n\t\tUNKNOWN\n\t}\n\n\tpublic static class InternalRayTraceResult {\n\n\t\tpublic final Part hitPart;\n\t\tpublic final RayTraceResult rayTraceResult;\n\t\tpublic final AxisAlignedBB boundingBox;\n\t\tpublic final EnumFacing sideHit;\n\n\t\tInternalRayTraceResult(Part hitPart, RayTraceResult rayTraceResult, AxisAlignedBB boundingBox, EnumFacing side) {\n\t\t\tthis.hitPart = hitPart;\n\t\t\tthis.rayTraceResult = rayTraceResult;\n\t\t\tthis.boundingBox = boundingBox;\n\t\t\tsideHit = side;\n\t\t}\n\n\t\t@Override\n\t\tpublic String toString() {\n\t\t\treturn String.format(\"RayTraceResult: %s, %s\", hitPart == null ? \"null\" : hitPart.name(), boundingBox == null ? \"null\" : boundingBox.toString());\n\t\t}\n\t}\n\n\tprivate static final EnumFacing[] DIR_VALUES;\n\n\tstatic {\n\t\tDIR_VALUES = new EnumFacing[EnumFacing.VALUES.length + 1];\n\t\tDIR_VALUES[0] = null;\n\t\tSystem.arraycopy(EnumFacing.VALUES, 0, DIR_VALUES, 1, EnumFacing.VALUES.length);\n\t}\n\n\t@Override\n\tpublic float getBlockHardness(IBlockState state, World par1World, BlockPos pos) {\n\t\treturn Configs.pipeDurability;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic EnumBlockRenderType getRenderType(IBlockState state) {\n\t\treturn EnumBlockRenderType.MODEL;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic BlockRenderLayer getRenderLayer() {\n\t\treturn BlockRenderLayer.CUTOUT;\n\t}\n\n\t@Override\n\tpublic boolean isFullBlock(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isFullCube(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isNormalCube(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isOpaqueCube(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isTopSolid(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canBeReplacedByLeaves(@Nonnull IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isSideSolid(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tif (((LogisticsTileGenericPipe) tile).isPipeBlock()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn super.isSideSolid(state, world, pos, side);\n\t}\n\n\t@Override\n\tpublic void breakBlock(World world, @Nonnull BlockPos pos, @Nonnull IBlockState state) {\n\t\tLogisticsBlockGenericPipe.removePipe(LogisticsBlockGenericPipe.getPipe(world, pos));\n\t\tsuper.breakBlock(world, pos, state);\n\t}\n\n\t@Override\n\tpublic void dropBlockAsItemWithChance(World world, @Nonnull final BlockPos pos, @Nonnull IBlockState state, float chance, int fortune) {\n\n\t\tif (world.isRemote) {\n\t\t\treturn;\n\t\t}\n\n\t\tint i1 = quantityDropped(world.rand);\n\t\tfor (int j1 = 0; j1 < i1; j1++) {\n\t\t\tif (world.rand.nextFloat() > chance) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\n\t\t\tif (pipe == null) {\n\t\t\t\tpipe = LogisticsBlockGenericPipe.pipeRemoved.get(new DoubleCoordinates(pos));\n\t\t\t}\n\n\t\t\tif (pipe == null) return;\n\n\t\t\tif (pipe.item != null && (pipe.canBeDestroyed() || pipe.destroyByPlayer())) {\n\t\t\t\tfor (ItemStack stack : pipe.dropContents()) {\n\t\t\t\t\tspawnAsEntity(world, pos, stack);\n\t\t\t\t}\n\t\t\t\tspawnAsEntity(world, pos, new ItemStack(pipe.item, 1, damageDropped(state)));\n\t\t\t\tfinal NonNullList<ItemStack> list = NonNullList.create();\n\t\t\t\tCoreUnroutedPipe finalPipe = pipe;\n\t\t\t\tBlockAccessDelegate worldDelegate = new BlockAccessDelegate(world) {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic TileEntity getTileEntity(BlockPos testPos) {\n\t\t\t\t\t\tif (pos == testPos) {\n\t\t\t\t\t\t\treturn finalPipe.container;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn super.getTileEntity(pos);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tmcmpBlockAccess.addDrops(list, worldDelegate, pos, state, fortune);\n\t\t\t\tfor (ItemStack stack : list) {\n\t\t\t\t\tspawnAsEntity(world, pos, stack);\n\t\t\t\t}\n\t\t\t} else if (pipe.item != null) {\n\t\t\t\tLogisticsBlockGenericPipe.cacheTileToPreventRemoval(pipe);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Item getItemDropped(IBlockState state, Random rand, int fortune) {\n\t\t// Returns null to be safe - the id does not depend on the meta\n\t\treturn null;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player) {\n\t\tItemStack pick = super.getPickBlock(state, target, world, pos, player);\n\t\tif (!pick.isEmpty()) {\n\t\t\treturn pick;\n\t\t}\n\t\tInternalRayTraceResult rayTraceResult = doRayTrace(world, pos, player);\n\n\t\tif (rayTraceResult != null && rayTraceResult.boundingBox != null) {\n\t\t\tif (rayTraceResult.hitPart == Part.PIPE) {\n\t\t\t\tfinal CoreUnroutedPipe pipe = Objects.requireNonNull(LogisticsBlockGenericPipe.getPipe(world, pos));\n\t\t\t\treturn new ItemStack(pipe.item);\n\t\t\t}\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t/* Wrappers ************************************************************ */\n\t@Override\n\tpublic void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) {\n\t\tsuper.neighborChanged(state, worldIn, pos, blockIn, fromPos);\n\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(worldIn, pos);\n\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\tpipe.container.scheduleNeighborChange();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, EntityLivingBase placer, @Nonnull ItemStack stack) {\n\t\tsuper.onBlockPlacedBy(world, pos, state, placer, stack);\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\tpipe.onBlockPlaced();\n\t\t\tpipe.onBlockPlacedBy(placer);\n\t\t\tif (pipe instanceof IRotationProvider) {\n\t\t\t\t((IRotationProvider) pipe).setFacing(placer.getHorizontalFacing().getOpposite());\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float xOffset, float yOffset, float zOffset) {\n\t\tif (super.onBlockActivated(world, pos, state, player, hand, side, xOffset, yOffset, zOffset)) return true;\n\n\t\tItemStack heldItem = player.inventory.mainInventory.get(player.inventory.currentItem);\n\n\t\t//world.notifyBlocksOfNeighborChange(pos, LogisticsPipes.LogisticsPipeBlock);\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe)) {\n\n\t\t\tif (heldItem.isEmpty()) {\n\t\t\t\t// Fall through the end of the test\n\t\t\t} else if (heldItem.getItem() == Items.SIGN) {\n\t\t\t\t// Sign will be placed anyway, so lets show the sign gui\n\t\t\t\treturn false;\n\t\t\t} else if (heldItem.getItem() instanceof ItemLogisticsPipe) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn pipe.blockActivated(player);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canProvidePower(IBlockState state) {\n\t\treturn true;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\t@Override\n\tpublic boolean addHitEffects(IBlockState state, World world, RayTraceResult target, ParticleManager effectRenderer) {\n\t\tif (super.addHitEffects(state, world, target, effectRenderer)) return true;\n\t\tBlockPos pos = target.getBlockPos();\n\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\t\tif (pipe == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tTextureAtlasSprite icon = pipe.getIconProvider().getIcon(pipe.getIconIndexForItem());\n\n\t\tEnumFacing sideHit = target.sideHit;\n\n\t\tBlock block = LPBlocks.pipe;\n\t\tfloat b = 0.1F;\n\t\tdouble px = target.hitVec.x + rand.nextDouble() * (state.getBoundingBox(world, pos).maxX - state.getBoundingBox(world, pos).minX - (b * 2.0F)) + b + state.getBoundingBox(world, pos).minX;\n\t\tdouble py = target.hitVec.y + rand.nextDouble() * (state.getBoundingBox(world, pos).maxY - state.getBoundingBox(world, pos).minY - (b * 2.0F)) + b + state.getBoundingBox(world, pos).minY;\n\t\tdouble pz = target.hitVec.z + rand.nextDouble() * (state.getBoundingBox(world, pos).maxZ - state.getBoundingBox(world, pos).minZ - (b * 2.0F)) + b + state.getBoundingBox(world, pos).minZ;\n\n\t\tif (sideHit == EnumFacing.DOWN) {\n\t\t\tpy = target.hitVec.y + state.getBoundingBox(world, pos).minY - b;\n\t\t}\n\n\t\tif (sideHit == EnumFacing.UP) {\n\t\t\tpy = target.hitVec.y + state.getBoundingBox(world, pos).maxY + b;\n\t\t}\n\n\t\tif (sideHit == EnumFacing.NORTH) {\n\t\t\tpz = target.hitVec.z + state.getBoundingBox(world, pos).minZ - b;\n\t\t}\n\n\t\tif (sideHit == EnumFacing.SOUTH) {\n\t\t\tpz = target.hitVec.z + state.getBoundingBox(world, pos).maxZ + b;\n\t\t}\n\n\t\tif (sideHit == EnumFacing.EAST) {\n\t\t\tpx = target.hitVec.x + state.getBoundingBox(world, pos).minX - b;\n\t\t}\n\n\t\tif (sideHit == EnumFacing.WEST) {\n\t\t\tpx = target.hitVec.x + state.getBoundingBox(world, pos).maxX + b;\n\t\t}\n\n\t\tParticle fx = effectRenderer.spawnEffectParticle(EnumParticleTypes.BLOCK_CRACK.getParticleID(), px, py, pz, 0.0D, 0.0D, 0.0D, Block.getStateId(world.getBlockState(target.getBlockPos())));\n\t\tfx.setParticleTexture(icon);\n\t\teffectRenderer.addEffect(fx.multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F));\n\t\treturn true;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\t@Override\n\tpublic boolean addDestroyEffects(World world, BlockPos pos, ParticleManager effectRenderer) {\n\t\tif (super.addDestroyEffects(world, pos, effectRenderer)) return true;\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(world, pos);\n\t\tif (pipe == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\t\t//if (config.isUseNewRenderer()) {\n\t\tLogisticsNewRenderPipe.renderDestruction(pipe, world, pos.getX(), pos.getY(), pos.getZ(), effectRenderer);\n\t\t/*} else {\n\t\t\tTextureAtlasSprite icon = pipe.getIconProvider().getIcon(pipe.getIconIndexForItem());\n\n\t\t\tbyte its = 4;\n\t\t\tfor (int i = 0; i < its; ++i) {\n\t\t\t\tfor (int j = 0; j < its; ++j) {\n\t\t\t\t\tfor (int k = 0; k < its; ++k) {\n\t\t\t\t\t\tif (pipe.isMultiBlock()) {\n\t\t\t\t\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> set = ((CoreMultiBlockPipe) pipe).getRotatedSubBlocks();\n\t\t\t\t\t\t\tset.add(new DoubleCoordinatesType<>(0, 0, 0, CoreMultiBlockPipe.SubBlockTypeForShare.NON_SHARE));\n\t\t\t\t\t\t\tfor (DoubleCoordinates pos : set) {\n\t\t\t\t\t\t\t\tint localx = x + pos.getXInt();\n\t\t\t\t\t\t\t\tint localy = y + pos.getYInt();\n\t\t\t\t\t\t\t\tint localz = z + pos.getZInt();\n\t\t\t\t\t\t\t\tdouble px = localx + (i + 0.5D) / its;\n\t\t\t\t\t\t\t\tdouble py = localy + (j + 0.5D) / its;\n\t\t\t\t\t\t\t\tdouble pz = localz + (k + 0.5D) / its;\n\t\t\t\t\t\t\t\tint random = rand.nextInt(6);\n\t\t\t\t\t\t\t\tEntityDiggingFX fx = new EntityDiggingFX(world, px, py, pz, px - localx - 0.5D, py - localy - 0.5D, pz - localz - 0.5D, LogisticsPipes.LogisticsPipeBlock, random, meta);\n\t\t\t\t\t\t\t\tfx.setParticleIcon(icon);\n\t\t\t\t\t\t\t\teffectRenderer.addEffect(fx.applyColourMultiplier(pos));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tdouble px = x + (i + 0.5D) / its;\n\t\t\t\t\t\t\tdouble py = y + (j + 0.5D) / its;\n\t\t\t\t\t\t\tdouble pz = z + (k + 0.5D) / its;\n\t\t\t\t\t\t\tint random = rand.nextInt(6);\n\t\t\t\t\t\t\tEntityDiggingFX fx = new EntityDiggingFX(world, px, py, pz, px - x - 0.5D, py - y - 0.5D, pz - z - 0.5D, LogisticsPipes.LogisticsPipeBlock, random, meta);\n\t\t\t\t\t\t\tfx.setParticleIcon(icon);\n\t\t\t\t\t\t\teffectRenderer.addEffect(fx.applyColourMultiplier(pos));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t*/\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tprotected BlockStateContainer createBlockState() {\n\t\tBlockStateContainer.Builder builder = new BlockStateContainer.Builder(this);\n\t\tbuilder.add(rotationProperty);\n\t\tbuilder.add(modelTypeProperty);\n\t\tconnectionPropertys.values().forEach(builder::add);\n\n\t\tbuilder.add(propertyRenderList);\n\t\tbuilder.add(propertyCache);\n\n\t\tmcmpBlockAccess.addBlockState(builder);\n\n\t\treturn builder.build();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBlockState getStateFromMeta(int meta) {\n\t\treturn this.getDefaultState();\n\t}\n\n\t@Override\n\tpublic int getMetaFromState(IBlockState state) {\n\t\treturn 0;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess worldIn, BlockPos pos) {\n\t\tcheckForRenderChanges(worldIn, pos);\n\t\tstate = super.getActualState(state, worldIn, pos);\n\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(worldIn, pos);\n\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\tif (pipe instanceof IRotationProvider) {\n\t\t\t\tstate = state.withProperty(rotationProperty, ((IRotationProvider) pipe).getRotation());\n\t\t\t}\n\n\t\t\tfor (EnumFacing side : EnumFacing.VALUES) {\n\t\t\t\tstate = state.withProperty(connectionPropertys.get(side), pipe.container.renderState.pipeConnectionMatrix.isConnected(side));\n\t\t\t}\n\n\t\t\tif (pipe instanceof PipeBlockRequestTable) {\n\t\t\t\tstate = state.withProperty(modelTypeProperty, PipeRenderModel.REQUEST_TABLE);\n\t\t\t}\n\t\t}\n\n\t\treturn state;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBlockState getExtendedState(@Nonnull IBlockState state, IBlockAccess worldIn, BlockPos pos) {\n\t\tstate = mcmpBlockAccess.getExtendedState(state, worldIn, pos);\n\n\t\tCoreUnroutedPipe pipe = LogisticsBlockGenericPipe.getPipe(worldIn, pos);\n\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\tLogisticsNewRenderPipe.checkAndCalculateRenderCache(pipe.container);\n\t\t\tstate = ((IExtendedBlockState) state).withProperty(propertyRenderList, pipe.container.renderState.cachedRenderer);\n\t\t\tstate = ((IExtendedBlockState) state).withProperty(propertyCache, pipe.container.renderState.objectCache);\n\t\t} else {\n\t\t\tstate = ((IExtendedBlockState) state).withProperty(propertyRenderList, LogisticsNewRenderPipe.getBasicPipeFrameRenderList());\n\t\t}\n\t\treturn state;\n\t}\n\n\tprivate void checkForRenderChanges(IBlockAccess worldIn, BlockPos blockPos) {\n\t\tTileEntity tile = new DoubleCoordinates(blockPos).getTileEntity(worldIn);\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) return;\n\t\t((LogisticsTileGenericPipe) tile).renderState.checkForRenderUpdate(worldIn, blockPos);\n\t}\n\n\t@Override\n\tpublic boolean canRenderInLayer(IBlockState state, BlockRenderLayer layer) {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/LogisticsBlockGenericSubMultiBlock.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Random;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.BlockContainer;\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.ParticleManager;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumBlockRenderType;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport static logisticspipes.LPBlocks.pipe;\nimport static net.minecraft.util.EnumBlockRenderType.ENTITYBLOCK_ANIMATED;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.config.Configs;\nimport logisticspipes.proxy.MainProxy;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsBlockGenericSubMultiBlock extends BlockContainer {\n\n\tprotected final Random rand = new Random();\n\tpublic static boolean redirectedToMainPipe = false;\n\n\tpublic LogisticsBlockGenericSubMultiBlock() {\n\t\tsuper(Material.GLASS);\n\t\tsetCreativeTab(LogisticsPipes.CREATIVE_TAB_LP);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic List<ItemStack> getDrops(IBlockAccess world, @Nonnull BlockPos pos, @Nonnull IBlockState state, int fortune) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\treturn mainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.map(mainPipe -> pipe.getDrops(world, mainPipe.getPos(), world.getBlockState(mainPipe.getPos()), fortune))\n\t\t\t\t\t.flatMap(Collection::stream)\n\t\t\t\t\t.collect(Collectors.toCollection(NonNullList::create));\n\t\t}\n\t\treturn Collections.emptyList();\n\t}\n\n\t/*\n\t@Override\n\tpublic TextureAtlasSprite getIcon(int p_149691_1_, int p_149691_2_) {\n\t\treturn LogisticsPipes.LogisticsPipeBlock.getIcon(p_149691_1_, p_149691_2_);\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@SuppressWarnings({ \"all\" })\n\tpublic TextureAtlasSprite getIcon(IBlockAccess iblockaccess, int i, int j, int k, int l) {\n\t\tDoubleCoordinates pos = new DoubleCoordinates(i, j, k);\n\t\tTileEntity tile = pos.getTileEntity(iblockaccess);\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipe = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tif (!mainPipe.isEmpty() && mainPipe.get(0).pipe != null && mainPipe.get(0).pipe.isMultiBlock()) {\n\t\t\t\treturn LogisticsPipes.LogisticsPipeBlock.getIcon(iblockaccess, mainPipe.get(0).xCoord, mainPipe.get(0).yCoord, mainPipe.get(0).zCoord, l);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\t*/\n\n\tpublic static DoubleCoordinates currentCreatedMultiBlock;\n\n\t@Override\n\t@Nonnull\n\tpublic TileEntity createNewTileEntity(@Nonnull World worldIn, int meta) {\n\t\tif (LogisticsBlockGenericSubMultiBlock.currentCreatedMultiBlock == null && MainProxy.isServer(worldIn)) {\n\t\t\tnew RuntimeException(\"Unknown MultiBlock controller\").printStackTrace();\n\t\t}\n\t\treturn new LogisticsTileGenericSubMultiBlock(LogisticsBlockGenericSubMultiBlock.currentCreatedMultiBlock);\n\t}\n\n\t@Override\n\tpublic void breakBlock(World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state) {\n\t\tif (redirectedToMainPipe) return;\n\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tmainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.forEach(mainPipe -> {\n\t\t\t\t\t\tredirectedToMainPipe = true;\n\t\t\t\t\t\tpipe.breakBlock(worldIn, mainPipe.getBlockPos(), worldIn.getBlockState(mainPipe.getBlockPos()));\n\t\t\t\t\t\tredirectedToMainPipe = false;\n\t\t\t\t\t\tworldIn.setBlockToAir(mainPipe.getPos());\n\t\t\t\t\t});\n\t\t}\n\t}\n\n\t@Override\n\tpublic void dropBlockAsItemWithChance(World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, float chance, int fortune) {\n\t\tif (world.isRemote) {\n\t\t\treturn;\n\t\t}\n\t\tBlockPos mainPipePos = LogisticsBlockGenericPipe.pipeSubMultiRemoved.get(new DoubleCoordinates(pos));\n\t\tif (mainPipePos != null) {\n\t\t\tpipe.dropBlockAsItemWithChance(world, mainPipePos, state, chance, fortune);\n\t\t}\n\t}\n\n\t@Override\n\tpublic float getBlockHardness(IBlockState state, World par1World, BlockPos pos) {\n\t\treturn Configs.pipeDurability;\n\t}\n\n\t@Override\n\tpublic boolean isNormalCube(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canBeReplacedByLeaves(@Nonnull IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos) {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic EnumBlockRenderType getRenderType(IBlockState state) {\n\t\treturn ENTITYBLOCK_ANIMATED;\n\t}\n\n\t@Override\n\tpublic boolean isOpaqueCube(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isFullCube(IBlockState state) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxToList(IBlockState state, World worldIn, @Nonnull BlockPos pos, @Nonnull AxisAlignedBB entityBox, @Nonnull List<AxisAlignedBB> collidingBoxes, @Nullable Entity entityIn, boolean isActualState) {\n\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tmainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.forEach(mainPipe -> pipe.addCollisionBoxToList(mainPipe, entityBox, collidingBoxes, entityIn, isActualState));\n\t\t}\n\t}\n\n\t@Override\n\t@Nullable\n\tpublic RayTraceResult collisionRayTrace(IBlockState blockState, @Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull Vec3d start, @Nonnull Vec3d end) {\n\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\treturn mainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.map(mainPipe -> pipe.collisionRayTrace(blockState, worldIn, mainPipe.getPos(), start, end))\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.findFirst()\n\t\t\t\t\t.map(it -> {\n\t\t\t\t\t\tRayTraceResult result = new RayTraceResult(it.typeOfHit, it.hitVec, it.sideHit, pos);\n\t\t\t\t\t\tresult.subHit = it.subHit;\n\t\t\t\t\t\tresult.hitVec = it.hitVec;\n\t\t\t\t\t\tresult.hitInfo = it.hitInfo;\n\t\t\t\t\t\tresult.entityHit = it.entityHit;\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t})\n\t\t\t\t\t.orElse(null);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@Nonnull\n\tpublic AxisAlignedBB getSelectedBoundingBox(IBlockState state, @Nonnull World worldIn, @Nonnull BlockPos pos) {\n\t\tTileEntity tile = worldIn.getTileEntity(pos);\n\t\tOptional<AxisAlignedBB> result = Optional.empty();\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tresult = mainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.filter(mainPipe -> Objects.nonNull(pipe.doRayTrace(worldIn, mainPipe.getPos(), Minecraft.getMinecraft().player)))\n\t\t\t\t\t.map(mainPipe -> pipe.getSelectedBoundingBox(state, worldIn, mainPipe.getPos()))\n\t\t\t\t\t.findFirst();\n\t\t}\n\t\treturn result.orElse(super.getSelectedBoundingBox(state, worldIn, pos).expand(-0.85F, -0.85F, -0.85F));\n\t}\n\n\t@Override\n\tpublic void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) {\n\t\tsuper.onNeighborChange(world, pos, neighbor);\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t((LogisticsTileGenericSubMultiBlock) tile).scheduleNeighborChange();\n\t\t}\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic boolean addDestroyEffects(World world, BlockPos pos, ParticleManager manager) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tOptional<Boolean> result = Optional.empty();\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tIBlockState state = tile.getBlockType().getExtendedState(tile.getBlockType().getDefaultState(), world, pos);\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tresult = mainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.filter(mainPipe -> Objects.nonNull(pipe.doRayTrace(world, mainPipe.getPos(), Minecraft.getMinecraft().player)))\n\t\t\t\t\t.map(mainPipe -> pipe.addDestroyEffects(world, mainPipe.getPos(), manager))\n\t\t\t\t\t.findFirst();\n\t\t}\n\t\treturn result.orElse(super.addDestroyEffects(world, pos, manager));\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getPickBlock(@Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tOptional<ItemStack> result = Optional.empty();\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tresult = mainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.filter(mainPipe -> Objects.nonNull(pipe.doRayTrace(world, mainPipe.getPos(), player)))\n\t\t\t\t\t.map(mainPipe -> pipe.getPickBlock(state, target, world, mainPipe.getPos(), player))\n\t\t\t\t\t.findFirst();\n\n\t\t\tif (!result.isPresent()) {\n\t\t\t\tresult = mainPipeList.stream()\n\t\t\t\t\t\t.findFirst()\n\t\t\t\t\t\t.map(mainPipe -> pipe.getPickBlock(state, target, world, mainPipe.getPos(), player));\n\t\t\t}\n\t\t}\n\t\treturn result.orElse(super.getPickBlock(state, target, world, pos, player));\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprivate void addHitEffects(LogisticsTileGenericPipe mainPipe, IBlockState state, World world, RayTraceResult target, ParticleManager manager) {\n\t\tfinal TextureAtlasSprite icon = mainPipe.pipe.getIconProvider().getIcon(mainPipe.pipe.getIconIndexForItem());\n\t\tfinal EnumFacing sideHit = target.sideHit;\n\t\tfinal float b = 0.1F;\n\t\tfinal AxisAlignedBB boundingBox = state.getBoundingBox(world, target.getBlockPos());\n\n\t\tdouble px = target.getBlockPos().getX() + rand.nextDouble() * (boundingBox.maxX - boundingBox.minX - (b * 2.0F)) + b + boundingBox.minX;\n\t\tdouble py = target.getBlockPos().getY() + rand.nextDouble() * (boundingBox.maxY - boundingBox.minY - (b * 2.0F)) + b + boundingBox.minY;\n\t\tdouble pz = target.getBlockPos().getZ() + rand.nextDouble() * (boundingBox.maxZ - boundingBox.minZ - (b * 2.0F)) + b + boundingBox.minZ;\n\n\t\tswitch (sideHit) {\n\t\t\tcase DOWN:\n\t\t\t\tpy = target.getBlockPos().getY() + boundingBox.minY - b;\n\t\t\t\tbreak;\n\t\t\tcase UP:\n\t\t\t\tpy = target.getBlockPos().getY() + boundingBox.maxY + b;\n\t\t\t\tbreak;\n\t\t\tcase NORTH:\n\t\t\t\tpz = target.getBlockPos().getZ() + boundingBox.minZ - b;\n\t\t\t\tbreak;\n\t\t\tcase SOUTH:\n\t\t\t\tpz = target.getBlockPos().getZ() + boundingBox.maxZ + b;\n\t\t\t\tbreak;\n\t\t\tcase WEST:\n\t\t\t\tpx = target.getBlockPos().getX() + boundingBox.minX - b;\n\t\t\t\tbreak;\n\t\t\tcase EAST:\n\t\t\t\tpx = target.getBlockPos().getX() + boundingBox.maxX + b;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// TODO spawn particles with icon\n\t\t/*\n\t\tparticle type: EnumParticleTypes.BLOCK_CRACK\n\n\t\tEntityDiggingFX fx = new EntityDiggingFX(world, px, py, pz, 0.0D, 0.0D, 0.0D, block, sideHit, world.getBlockMetadata(x, y, z));\n\t\tfx.setParticleIcon(icon);\n\t\tmanager.addEffect(fx.applyColourMultiplier(x, y, z).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F));\n\t\t*/\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic boolean addHitEffects(IBlockState state, World world, RayTraceResult target, ParticleManager manager) {\n\t\tTileEntity tile = world.getTileEntity(target.getBlockPos());\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> mainPipeList = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tOptional<LogisticsTileGenericPipe> result = mainPipeList.stream()\n\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t.filter(LogisticsTileGenericPipe::isMultiBlock)\n\t\t\t\t\t.filter(mainPipe -> Objects.nonNull(pipe.doRayTrace(world, mainPipe.getPos(), Minecraft.getMinecraft().player)))\n\t\t\t\t\t.findFirst();\n\n\t\t\tresult.ifPresent(mainPipe -> addHitEffects(mainPipe, state, world, target, manager));\n\t\t\tif (result.isPresent()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn super.addHitEffects(state, world, target, manager);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/LogisticsTileGenericPipe.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.Arrays;\nimport java.util.EnumMap;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.crash.CrashReportCategory;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.network.NetworkManager;\nimport net.minecraft.network.play.server.SPacketUpdateTileEntity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ITickable;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport dan200.computercraft.api.peripheral.IComputerAccess;\nimport li.cil.oc.api.machine.Arguments;\nimport li.cil.oc.api.machine.Context;\nimport li.cil.oc.api.network.Environment;\nimport li.cil.oc.api.network.ManagedPeripheral;\nimport li.cil.oc.api.network.Message;\nimport li.cil.oc.api.network.Node;\nimport li.cil.oc.api.network.SidedEnvironment;\nimport static logisticspipes.pipes.basic.LogisticsBlockGenericPipe.PIPE_CONN_BB;\nimport lombok.Getter;\nimport org.apache.logging.log4j.Level;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILPPipe;\nimport logisticspipes.api.ILPPipeTile;\nimport logisticspipes.asm.ModDependentField;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.interfaces.IClientState;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.logic.LogicController;\nimport logisticspipes.logic.interfaces.ILogicControllerTile;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.block.PipeSolidSideCheck;\nimport logisticspipes.network.packets.pipe.PipeTileStatePacket;\nimport logisticspipes.pipes.PipeItemsFirewall;\nimport logisticspipes.pipes.basic.ltgpmodcompat.LPDuctHolderTileEntity;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.buildcraft.subproxies.IBCPipeCapabilityProvider;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\nimport logisticspipes.proxy.opencomputers.IOCTile;\nimport logisticspipes.proxy.opencomputers.asm.BaseWrapperClass;\nimport logisticspipes.renderer.IIconProvider;\nimport logisticspipes.renderer.LogisticsTileRenderController;\nimport logisticspipes.renderer.state.PipeRenderState;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.LPPositionSet;\nimport logisticspipes.utils.OrientationsUtil;\nimport logisticspipes.utils.ReflectionHelper;\nimport logisticspipes.utils.StackTraceUtil;\nimport logisticspipes.utils.StackTraceUtil.Info;\nimport logisticspipes.utils.TileBuffer;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.connection.ConnectionType;\nimport network.rs485.logisticspipes.connection.PipeInventoryConnectionChecker;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\n@ModDependentInterface(modId = { LPConstants.cofhCoreModID, LPConstants.openComputersModID, LPConstants.openComputersModID, LPConstants.openComputersModID },\n\t\tinterfacePath = { \"cofh.api.transport.IItemDuct\", \"li.cil.oc.api.network.ManagedPeripheral\",\n\t\t\t\t\"li.cil.oc.api.network.Environment\", \"li.cil.oc.api.network.SidedEnvironment\", })\npublic class LogisticsTileGenericPipe extends LPDuctHolderTileEntity\n\t\timplements ITickable, IOCTile, ILPPipeTile, IPipeInformationProvider, /*IItemDuct,*/ ManagedPeripheral, Environment, SidedEnvironment,\n\t\tILogicControllerTile {\n\n\tpublic static PipeInventoryConnectionChecker pipeInventoryConnectionChecker = new PipeInventoryConnectionChecker();\n\n\tpublic int statePacketId = 0;\n\tpublic final PipeRenderState renderState;\n\tpublic final CoreState coreState = new CoreState();\n\tpublic final IBCPipeCapabilityProvider bcCapProvider;\n\tpublic Object OPENPERIPHERAL_IGNORE; //Tell OpenPeripheral to ignore this class\n\tpublic Set<DoubleCoordinates> subMultiBlock = new HashSet<>();\n\tpublic boolean[] turtleConnect = new boolean[7];\n\t@ModDependentField(modId = LPConstants.computerCraftModID)\n\tpublic HashMap<IComputerAccess, EnumFacing> connections;\n\t@ModDependentField(modId = LPConstants.computerCraftModID)\n\tpublic IComputerAccess currentPC;\n\t@ModDependentField(modId = LPConstants.openComputersModID)\n\tpublic Node node;\n\tpublic LogicController logicController = new LogicController();\n\tpublic boolean[] pipeConnectionsBuffer = new boolean[6];\n\tpublic boolean[] pipeBCConnectionsBuffer = new boolean[6];\n\tpublic boolean[] pipeTDConnectionsBuffer = new boolean[6];\n\tpublic CoreUnroutedPipe pipe;\n\tprivate LogisticsTileRenderController renderController;\n\tprivate boolean addedToNetwork = false;\n\tprivate boolean sendInitPacket = true;\n\t@Getter\n\tprivate boolean initialized = false;\n\tprivate boolean deletePipe = false;\n\tprivate TileBuffer[] tileBuffer;\n\tprivate boolean sendClientUpdate = false;\n\tprivate boolean blockNeighborChange = false;\n\tprivate boolean refreshRenderState = false;\n\tprivate boolean pipeBound = false;\n\t@SideOnly(Side.CLIENT)\n\tprivate AxisAlignedBB renderBox;\n\tprivate EnumMap<EnumFacing, ItemInsertionHandler> itemInsertionHandlers;\n\n\tpublic LogisticsTileGenericPipe() {\n\t\tif (SimpleServiceLocator.ccProxy.isCC()) {\n\t\t\tconnections = new HashMap<>();\n\t\t}\n\t\tSimpleServiceLocator.openComputersProxy.initLogisticsTileGenericPipe(this);\n\t\ttdPart = SimpleServiceLocator.thermalDynamicsProxy.getTDPart(this);\n\t\tbcCapProvider = SimpleServiceLocator.buildCraftProxy.getIBCPipeCapabilityProvider(this);\n\t\timcmpltgpCompanion = SimpleServiceLocator.mcmpProxy.createMCMPCompanionFor(this);\n\t\titemInsertionHandlers = new EnumMap<>(EnumFacing.class);\n\t\tArrays.stream(EnumFacing.values()).forEach(face -> itemInsertionHandlers.put(face, new ItemInsertionHandler(this, face)));\n\t\tItemInsertionHandler itemInsertionHandlerNull = new ItemInsertionHandler(this, null);\n\t\trenderState = new PipeRenderState();\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tif (pipe == null) {\n\t\t\ttileEntityInvalid = true;\n\t\t\tinitialized = false;\n\t\t\ttileBuffer = null;\n\t\t\tsuper.invalidate();\n\t\t} else if (!pipe.preventRemove()) {\n\t\t\ttileEntityInvalid = true;\n\t\t\tinitialized = false;\n\t\t\ttileBuffer = null;\n\t\t\tpipe.invalidate();\n\t\t\tsuper.invalidate();\n\t\t\tSimpleServiceLocator.openComputersProxy.handleInvalidate(this);\n\t\t\ttdPart.invalidate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\tinitialized = false;\n\t\ttileBuffer = null;\n\t\tbindPipe();\n\t\tif (pipe != null) {\n\t\t\tpipe.validate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (pipe != null) {\n\t\t\tpipe.onChunkUnload();\n\t\t}\n\t\tSimpleServiceLocator.openComputersProxy.handleChunkUnload(this);\n\t\ttdPart.onChunkUnload();\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\timcmpltgpCompanion.update();\n\t\tfinal Info superDebug = StackTraceUtil.addSuperTraceInformation(() -> \"Time: \" + getWorld().getWorldTime());\n\t\tfinal Info debug = StackTraceUtil.addTraceInformation(() -> \"(\" + getX() + \", \" + getY() + \", \" + getZ() + \")\", superDebug);\n\t\tif (sendInitPacket && MainProxy.isServer(getWorld())) {\n\t\t\tsendInitPacket = false;\n\t\t\tgetRenderController().sendInit();\n\t\t}\n\t\tif (!world.isRemote) {\n\t\t\tif (deletePipe) {\n\t\t\t\tworld.setBlockToAir(getPos());\n\t\t\t}\n\n\t\t\tif (pipe == null) {\n\t\t\t\tdebug.end();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!initialized) {\n\t\t\t\tinitialize(pipe);\n\t\t\t}\n\t\t}\n\n\t\tif (!LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\tdebug.end();\n\t\t\treturn;\n\t\t}\n\n\t\tpipe.updateEntity();\n\n\t\tif (world.isRemote) {\n\t\t\tdebug.end();\n\t\t\treturn;\n\t\t}\n\n\t\tif (blockNeighborChange) {\n\t\t\tcomputeConnections();\n\t\t\tpipe.onNeighborBlockChange();\n\t\t\tblockNeighborChange = false;\n\t\t\trefreshRenderState = true;\n\n\t\t\tif (MainProxy.isServer(world)) {\n\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(this, PacketHandler.getPacket(PipeSolidSideCheck.class).setTilePos(this));\n\t\t\t}\n\t\t}\n\n\t\t//Sideblocks need to be checked before this\n\t\t//Network needs to be after this\n\n\t\tif (refreshRenderState) {\n\t\t\trefreshRenderState();\n\n\t\t\tif (renderState.isDirty()) {\n\t\t\t\trenderState.clean();\n\t\t\t\tsendUpdateToClient();\n\t\t\t}\n\n\t\t\trefreshRenderState = false;\n\t\t}\n\n\t\tif (sendClientUpdate) {\n\t\t\tsendClientUpdate = false;\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(this, getLPDescriptionPacket());\n\t\t}\n\n\t\tgetRenderController().onUpdate();\n\t\tif (!addedToNetwork) {\n\t\t\taddedToNetwork = true;\n\t\t\tSimpleServiceLocator.openComputersProxy.addToNetwork(this);\n\t\t}\n\t\tdebug.end();\n\t}\n\n\tprivate void refreshRenderState() {\n\t\t// Pipe connections;\n\t\tfor (EnumFacing o : EnumFacing.VALUES) {\n\t\t\trenderState.pipeConnectionMatrix.setConnected(o, pipeConnectionsBuffer[o.ordinal()]);\n\t\t\trenderState.pipeConnectionMatrix.setBCConnected(o, pipeBCConnectionsBuffer[o.ordinal()]);\n\t\t\trenderState.pipeConnectionMatrix.setTDConnected(o, pipeTDConnectionsBuffer[o.ordinal()]);\n\t\t}\n\t\t// Pipe Textures\n\t\tfor (int i = 0; i < 7; i++) {\n\t\t\tEnumFacing o = EnumFacing.byIndex(i);\n\t\t\trenderState.textureMatrix.setIconIndex(o, pipe.getIconIndex(o));\n\t\t}\n\t\t//New Pipe Texture States\n\t\trenderState.textureMatrix.refreshStates(pipe);\n\t}\n\n\t@Override\n\tpublic boolean isMultipartAllowedInPipe() {\n\t\treturn !isMultiBlock() && (pipe == null || pipe.isMultipartAllowedInPipe());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound getUpdateTag() {\n\t\tsendInitPacket = true;\n\t\tNBTTagCompound nbt = super.getUpdateTag();\n\t\ttry {\n\t\t\tPacketHandler.addPacketToNBT(getLPDescriptionPacket(), nbt);\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn nbt;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void handleUpdateTag(@Nonnull NBTTagCompound tag) {\n\t\tPacketHandler.queueAndRemovePacketFromNBT(tag);\n\t\tsuper.handleUpdateTag(tag);\n\t}\n\n\t@Override\n\tpublic SPacketUpdateTileEntity getUpdatePacket() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\tSPacketUpdateTileEntity superPacket = super.getUpdatePacket();\n\t\tif (superPacket != null) {\n\t\t\tnbt.setTag(\"LogisticsPipes:SuperUpdatePacket\", ReflectionHelper.getPrivateField(SPacketUpdateTileEntity.class, superPacket, \"nbt\", \"field_148860_e\"));\n\t\t}\n\t\ttry {\n\t\t\tPacketHandler.addPacketToNBT(getLPDescriptionPacket(), nbt);\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn new SPacketUpdateTileEntity(getPos(), 1, nbt);\n\t}\n\n\t@Override\n\tpublic void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) {\n\t\tPacketHandler.queueAndRemovePacketFromNBT(packet.getNbtCompound());\n\t\tif (packet.getNbtCompound().hasKey(\"LogisticsPipes:SuperUpdatePacket\")) {\n\t\t\tsuper.onDataPacket(net, new SPacketUpdateTileEntity(getPos(), 0, packet.getNbtCompound().getCompoundTag(\"LogisticsPipes:SuperUpdatePacket\")));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addInfoToCrashReport(@Nonnull CrashReportCategory reportCategory) {\n\t\ttry {\n\t\t\tsuper.addInfoToCrashReport(reportCategory);\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t\treportCategory.addCrashSection(\"LP-Version\", LogisticsPipes.getVersionString());\n\t\tif (pipe != null) {\n\t\t\treportCategory.addCrashSection(\"Pipe\", pipe.getClass().getCanonicalName());\n\t\t\tif (pipe.transport != null) {\n\t\t\t\treportCategory.addCrashSection(\"Transport\", pipe.transport.getClass().getCanonicalName());\n\t\t\t} else {\n\t\t\t\treportCategory.addCrashSection(\"Transport\", \"null\");\n\t\t\t}\n\n\t\t\tif (pipe instanceof CoreRoutedPipe) {\n\t\t\t\ttry {\n\t\t\t\t\t((CoreRoutedPipe) pipe).addCrashReport(reportCategory);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\treportCategory.addCrashSectionThrowable(\"Internal LogisticsPipes Error\", e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void scheduleNeighborChange() {\n\t\ttdPart.scheduleNeighborChange();\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tpipe.triggerConnectionCheck();\n\t\t}\n\t\tblockNeighborChange = true;\n\t\tboolean[] connected = new boolean[6];\n\t\tnew WorldCoordinatesWrapper(this).allNeighborTileEntities().stream()\n\t\t\t\t.filter(adjacent -> SimpleServiceLocator.ccProxy.isTurtle(adjacent.getTileEntity()))\n\t\t\t\t.forEach(adjacent -> connected[adjacent.getDirection().ordinal()] = true);\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tif (!connected[i]) {\n\t\t\t\tturtleConnect[i] = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* IPipeInformationProvider */\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tnbt = super.writeToNBT(nbt);\n\n\t\t/*\n\t\tfor (int i = 0; i < EnumFacing.VALUES.length; i++) {\n\t\t\tfinal String key = \"redstoneInputSide[\" + i + \"]\";\n\t\t\tnbt.setByte(key, (byte) redstoneInputSide[i]);\n\t\t}\n\t\t */\n\n\t\tif (pipe != null) {\n\t\t\tnbt.setInteger(\"pipeId\", Item.REGISTRY.getIDForObject(pipe.item));\n\t\t\tpipe.writeToNBT(nbt);\n\t\t} else {\n\t\t\tnbt.setInteger(\"pipeId\", coreState.pipeId);\n\t\t}\n\n\t\tfor (int i = 0; i < turtleConnect.length; i++) {\n\t\t\tnbt.setBoolean(\"turtleConnect_\" + i, turtleConnect[i]);\n\t\t}\n\t\tSimpleServiceLocator.openComputersProxy.handleWriteToNBT(this, nbt);\n\n\t\tNBTTagCompound logicNBT = new NBTTagCompound();\n\t\tlogicController.writeToNBT(logicNBT);\n\t\tnbt.setTag(\"logicController\", logicNBT);\n\t\treturn nbt;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tif (pipe != null) {\n\t\t\tStackTraceElement[] trace = Thread.currentThread().getStackTrace();\n\t\t\tif (trace.length > 2 && trace[2].getMethodName().equals(\"handle\") && trace[2].getClassName()\n\t\t\t\t\t.equals(\"com.xcompwiz.lookingglass.network.packet.PacketTileEntityNBT\")) {\n\t\t\t\tSystem.out.println(\"Prevented false data injection by LookingGlass\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tsuper.readFromNBT(nbt);\n\n\t\tif (!nbt.hasKey(\"pipeId\") && MainProxy.isClient(world)) return;\n\n\t\tcoreState.pipeId = nbt.getInteger(\"pipeId\");\n\t\tpipe = LogisticsBlockGenericPipe.createPipe(Item.getItemById(coreState.pipeId));\n\t\tbindPipe();\n\n\t\tif (pipe != null) {\n\t\t\tpipe.readFromNBT(nbt);\n\t\t\tpipe.finishInit();\n\t\t} else {\n\t\t\tLogisticsPipes.log.log(Level.WARN, \"Pipe failed to load from NBT at \" + getPos());\n\t\t\tdeletePipe = true;\n\t\t}\n\n\t\tfor (int i = 0; i < turtleConnect.length; i++) {\n\t\t\tturtleConnect[i] = nbt.getBoolean(\"turtleConnect_\" + i);\n\t\t}\n\t\tSimpleServiceLocator.openComputersProxy.handleReadFromNBT(this, nbt);\n\n\t\tlogicController.readFromNBT(nbt.getCompoundTag(\"logicController\"));\n\t}\n\n\tpublic boolean canPipeConnect(TileEntity with, EnumFacing side) {\n\t\tif (MainProxy.isClient(world)) {\n\t\t\t//XXX why is this ever called client side, its not *used* for anything.\n\t\t\treturn false;\n\t\t}\n\t\tif (with == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (!LogisticsBlockGenericPipe.isValid(pipe)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfinal EnumFacing neighborOrientation = OrientationsUtil.getOrientationOfTilewithTile(this, with);\n\t\tif (SimpleServiceLocator.ccProxy.isTurtle(with) && (neighborOrientation == null || !turtleConnect[neighborOrientation.ordinal()])) {\n\t\t\treturn false;\n\t\t}\n\n\t\tAxisAlignedBB aabb = PIPE_CONN_BB.get(side.getIndex());\n\t\tif (SimpleServiceLocator.mcmpProxy.checkIntersectionWith(this, aabb)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (SimpleServiceLocator.thermalDynamicsProxy.isBlockedSide(with, side.getOpposite())) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (with instanceof LogisticsTileGenericPipe) {\n\t\t\tCoreUnroutedPipe otherPipe = ((LogisticsTileGenericPipe) with).pipe;\n\n\t\t\tif (!(LogisticsBlockGenericPipe.isValid(otherPipe))) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!(otherPipe.canPipeConnect(this, side.getOpposite()))) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tAxisAlignedBB aabbB = PIPE_CONN_BB.get(side.getOpposite().getIndex());\n\t\t\tif (SimpleServiceLocator.mcmpProxy.checkIntersectionWith((LogisticsTileGenericPipe) with, aabbB)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t}\n\t\treturn pipe.canPipeConnect(with, side);\n\t}\n\n\tpublic void queueEvent(String event, Object[] arguments) {\n\t\tSimpleServiceLocator.ccProxy.queueEvent(event, arguments, this);\n\t}\n\n\tpublic void handleMesssage(int computerId, Object message, int sourceId) {\n\t\tSimpleServiceLocator.ccProxy.handleMesssage(computerId, message, this, sourceId);\n\t}\n\n\tpublic boolean getTurtleConnect() {\n\t\treturn SimpleServiceLocator.ccProxy.getTurtleConnect(this);\n\t}\n\n\tpublic void setTurtleConnect(boolean flag) {\n\t\tSimpleServiceLocator.ccProxy.setTurtleConnect(flag, this);\n\t}\n\n\tpublic int getLastCCID() {\n\t\treturn SimpleServiceLocator.ccProxy.getLastCCID(this);\n\t}\n\n\t@Nonnull\n\tpublic ItemStack insertItem(EnumFacing from, @Nonnull ItemStack stack) {\n\t\tint used = injectItem(stack, true, from);\n\t\tif (used == stack.getCount()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t} else {\n\t\t\tstack = stack.copy();\n\t\t\tstack.shrink(used);\n\t\t\treturn stack;\n\t\t}\n\t}\n\n\tpublic void addLaser(EnumFacing dir, float length, int color, boolean reverse, boolean renderBall) {\n\t\tgetRenderController().addLaser(dir, length, color, reverse, renderBall);\n\t}\n\n\tpublic void removeLaser(EnumFacing dir, int color, boolean isBall) {\n\t\tgetRenderController().removeLaser(dir, color, isBall);\n\t}\n\n\tpublic LogisticsTileRenderController getRenderController() {\n\t\tif (renderController == null) {\n\t\t\trenderController = new LogisticsTileRenderController(this);\n\t\t}\n\t\treturn renderController;\n\t}\n\n\t@Override\n\tpublic boolean isCorrect(ConnectionType type) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn getPos().getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn getPos().getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn getPos().getZ();\n\t}\n\n\t@Override\n\tpublic boolean isRouterInitialized() {\n\t\treturn isInitialized() && (!isRoutingPipe() || !getRoutingPipe().stillNeedReplace());\n\t}\n\n\t@Override\n\tpublic boolean isRoutingPipe() {\n\t\treturn pipe instanceof CoreRoutedPipe;\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getRoutingPipe() {\n\t\tif (pipe instanceof CoreRoutedPipe) {\n\t\t\treturn (CoreRoutedPipe) pipe;\n\t\t}\n\t\tthrow new RuntimeException(\"This is no routing pipe\");\n\t}\n\n\t@Override\n\tpublic boolean isFirewallPipe() {\n\t\treturn pipe instanceof PipeItemsFirewall;\n\t}\n\n\t@Override\n\tpublic IFilter getFirewallFilter() {\n\t\tif (pipe instanceof PipeItemsFirewall) {\n\t\t\treturn ((PipeItemsFirewall) pipe).getFilter();\n\t\t}\n\t\tthrow new RuntimeException(\"This is no firewall pipe\");\n\t}\n\n\tpublic TileEntity getTile() {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic boolean divideNetwork() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean powerOnly() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isOnewayPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isOutputClosed(EnumFacing direction) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isItemPipe() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isFluidPipe() {\n\t\treturn pipe != null && pipe.isFluidPipe();\n\t}\n\n\t@Override\n\tpublic boolean isPowerPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean canConnect(TileEntity to, EnumFacing direction, boolean flag) {\n\t\tif (pipe == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (direction != null) {\n\t\t\tAxisAlignedBB aabb = PIPE_CONN_BB.get(direction.getIndex());\n\t\t\tif (SimpleServiceLocator.mcmpProxy.checkIntersectionWith(this, aabb)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn pipe.canPipeConnect(to, direction, flag);\n\t}\n\n\t@Override\n\tpublic double getDistance() {\n\t\tif (this.pipe != null && this.pipe.transport != null) {\n\t\t\treturn this.pipe.transport.getPipeLength();\n\t\t}\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic double getDistanceWeight() {\n\t\tif (this.pipe != null && this.pipe.transport != null) {\n\t\t\treturn this.pipe.transport.getDistanceWeight();\n\t\t}\n\t\treturn 1;\n\t}\n\n\tpublic int injectItem(@Nonnull ItemStack payload, boolean doAdd, EnumFacing from) {\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe) && pipe.transport != null && isPipeConnectedCached(from)) {\n\t\t\tif (doAdd && MainProxy.isServer(getWorld())) {\n\t\t\t\tItemStack leftStack = payload.copy();\n\t\t\t\tint lastIterLeft;\n\t\t\t\tdo {\n\t\t\t\t\tlastIterLeft = leftStack.getCount();\n\t\t\t\t\tLPTravelingItem.LPTravelingItemServer travelingItem = SimpleServiceLocator.routedItemHelper.createNewTravelItem(leftStack);\n\t\t\t\t\tleftStack.setCount(pipe.transport.injectItem(travelingItem, from.getOpposite()));\n\t\t\t\t} while (leftStack.getCount() != lastIterLeft && leftStack.getCount() != 0);\n\t\t\t\treturn payload.getCount() - leftStack.getCount();\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\n\tpublic boolean isPipeConnectedCached(EnumFacing side) {\n\t\tif (MainProxy.isClient(this.world)) {\n\t\t\treturn renderState.pipeConnectionMatrix.isConnected(side);\n\t\t} else {\n\t\t\treturn pipeConnectionsBuffer[side.ordinal()];\n\t\t}\n\t}\n\n\tpublic boolean isOpaque() {\n\t\treturn pipe.isOpaque();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic Node node() {\n\t\treturn node;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic void onConnect(Node node1) {}\n\t//public int redstoneInput = 0;\n\t//public int[] redstoneInputSide = new int[EnumFacing.VALUES.length];\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic void onDisconnect(Node node1) {}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic void onMessage(Message message) {}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic Object[] invoke(String s, Context context, Arguments arguments) {\n\t\tBaseWrapperClass object = (BaseWrapperClass) Objects.requireNonNull(CCObjectWrapper.getWrappedObject(pipe, BaseWrapperClass.WRAPPER), \"wrapped object returned null in \" + toString());\n\t\tobject.isDirectCall = true;\n\t\treturn CCObjectWrapper.createArray(object);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic String[] methods() {\n\t\treturn new String[] { \"getPipe\" };\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic Node sidedNode(EnumFacing side) {\n\t\tif (this.getTile(side) instanceof LogisticsTileGenericPipe || this.getTile(side) instanceof LogisticsSolidTileEntity) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn node();\n\t\t}\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@ModDependentMethod(modId = LPConstants.openComputersModID)\n\tpublic boolean canConnect(EnumFacing side) {\n\t\treturn !(this.getTile(side) instanceof LogisticsTileGenericPipe) && !(this.getTile(side) instanceof LogisticsSolidTileEntity);\n\t}\n\n\t@Override\n\tpublic Object getOCNode() {\n\t\treturn node;\n\t}\n\n\tpublic void initialize(CoreUnroutedPipe pipe) {\n\t\tblockType = getBlockType();\n\n\t\tif (pipe == null) {\n\t\t\tLogisticsPipes.log.warn(\"Pipe failed to initialize at \" + getPos().toString() + \", deleting\");\n\t\t\tworld.setBlockToAir(getPos());\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pipe = pipe;\n\n\t\t/*\n\t\tfor (EnumFacing o : EnumFacing.VALUES) {\n\t\t\tTileEntity tile = getTile(o);\n\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\t((LogisticsTileGenericPipe) tile).scheduleNeighborChange();\n\t\t\t}\n\t\t}*/\n\n\t\tbindPipe();\n\n\t\tcomputeConnections();\n\t\tscheduleRenderUpdate();\n\n\t\tif (pipe.needsInit()) {\n\t\t\tpipe.initialize();\n\t\t}\n\n\t\tinitialized = true;\n\t}\n\n\tprivate void bindPipe() {\n\t\tif (!pipeBound && pipe != null) {\n\t\t\tpipe.setTile(this);\n\t\t\tcoreState.pipeId = Item.getIdFromItem(pipe.item);\n\t\t\tpipeBound = true;\n\t\t}\n\t}\n\n\t/* SMP */\n\n\tpublic ModernPacket getLPDescriptionPacket() {\n\t\tbindPipe();\n\n\t\tPipeTileStatePacket packet = PacketHandler.getPacket(PipeTileStatePacket.class);\n\n\t\tpacket.setTilePos(this);\n\n\t\tpacket.setCoreState(coreState);\n\t\tpacket.setRenderState(renderState);\n\t\tpacket.setPipe(pipe);\n\t\tpacket.setStatePacketId(statePacketId++);\n\n\t\treturn packet;\n\t}\n\n\tpublic void afterStateUpdated() {\n\t\tif (pipe == null && coreState.pipeId != 0) {\n\t\t\tinitialize(LogisticsBlockGenericPipe.createPipe(Item.REGISTRY.getObjectById(coreState.pipeId)));\n\t\t}\n\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tworld.markBlockRangeForRenderUpdate(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ());\n\n\t\tif (renderState.needsRenderUpdate()) {\n\t\t\tworld.markBlockRangeForRenderUpdate(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ());\n\t\t\trenderState.clean();\n\t\t}\n\t}\n\n\tpublic void sendUpdateToClient() {\n\t\tsendClientUpdate = true;\n\t}\n\n\tpublic TileBuffer[] getTileCache() {\n\t\tif (tileBuffer == null && pipe != null) {\n\t\t\ttileBuffer = TileBuffer.makeBuffer(world, pos, pipe.transport.delveIntoUnloadedChunks());\n\t\t}\n\t\treturn tileBuffer;\n\t}\n\n\tpublic void blockCreated(EnumFacing from, Block block, TileEntity tile) {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache != null) {\n\t\t\tcache[from.getOpposite().ordinal()].set(block, tile);\n\t\t}\n\t}\n\n\t@Override\n\tpublic TileEntity getNextConnectedTile(EnumFacing to) {\n\t\tif (this.pipe.isMultiBlock()) {\n\t\t\treturn ((CoreMultiBlockPipe) this.pipe).getConnectedEndTile(to);\n\t\t}\n\t\treturn getTile(to, false);\n\t}\n\n\tpublic TileEntity getTile(EnumFacing to) {\n\t\treturn getTile(to, false);\n\t}\n\n\tpublic TileEntity getTile(EnumFacing to, boolean force) {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache != null) {\n\t\t\tif (force) {\n\t\t\t\tcache[to.ordinal()].refresh();\n\t\t\t}\n\t\t\treturn cache[to.ordinal()].getTile();\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic Block getBlock(EnumFacing to) {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache != null) {\n\t\t\treturn cache[to.ordinal()].getBlock();\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate void computeConnections() {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tboolean[] pipeTDConnectionsBufferOld = pipeTDConnectionsBuffer.clone();\n\n\t\tfor (EnumFacing side : EnumFacing.VALUES) {\n\t\t\tTileBuffer t = cache[side.ordinal()];\n\t\t\tt.refresh();\n\n\t\t\tpipeConnectionsBuffer[side.ordinal()] = canPipeConnect(t.getTile(), side);\n\t\t\tif (pipeConnectionsBuffer[side.ordinal()]) {\n\t\t\t\tpipeBCConnectionsBuffer[side.ordinal()] = SimpleServiceLocator.buildCraftProxy.isBuildCraftPipe(t.getTile());\n\t\t\t\tpipeTDConnectionsBuffer[side.ordinal()] = SimpleServiceLocator.thermalDynamicsProxy.isItemDuct(t.getTile());\n\t\t\t} else {\n\t\t\t\tpipeBCConnectionsBuffer[side.ordinal()] = false;\n\t\t\t\tpipeTDConnectionsBuffer[side.ordinal()] = false;\n\t\t\t}\n\t\t}\n\t\tif (!Arrays.equals(pipeTDConnectionsBufferOld, pipeTDConnectionsBuffer)) {\n\t\t\ttdPart.connectionsChanged();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == LogisticsPipes.FLUID_HANDLER_CAPABILITY && LogisticsBlockGenericPipe.isValid(pipe) && pipe.transport instanceof PipeFluidTransportLogistics && facing != null) {\n\t\t\tif (((PipeFluidTransportLogistics) pipe.transport).getIFluidHandler(facing) != null) return true;\n\t\t}\n\t\tif (capability == LogisticsPipes.ITEM_HANDLER_CAPABILITY) {\n\t\t\tif (facing == null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tTileEntity tile = getTile(facing);\n\t\t\tif (tile != null) {\n\t\t\t\tif (pipeInventoryConnectionChecker.shouldLPProvideInventoryTo(tile)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (bcCapProvider.hasCapability(capability, facing)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (imcmpltgpCompanion.hasCapability(capability, facing)) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn super.hasCapability(capability, facing);\n\t}\n\n\t@Nullable\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == LogisticsPipes.FLUID_HANDLER_CAPABILITY && LogisticsBlockGenericPipe.isValid(pipe) && pipe.transport instanceof PipeFluidTransportLogistics && facing != null) {\n\t\t\treturn (T) ((PipeFluidTransportLogistics) pipe.transport).getIFluidHandler(facing);\n\t\t}\n\t\tif (capability == LogisticsPipes.ITEM_HANDLER_CAPABILITY) {\n\t\t\tif (facing == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tTileEntity tile = getTile(facing);\n\t\t\tif (tile != null) {\n\t\t\t\tif (pipeInventoryConnectionChecker.shouldLPProvideInventoryTo(tile)) {\n\t\t\t\t\treturn (T) itemInsertionHandlers.get(facing);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (bcCapProvider.hasCapability(capability, facing)) {\n\t\t\treturn bcCapProvider.getCapability(capability, facing);\n\t\t}\n\t\tif (imcmpltgpCompanion.hasCapability(capability, facing)) {\n\t\t\treturn imcmpltgpCompanion.getCapability(capability, facing);\n\t\t}\n\t\treturn super.getCapability(capability, facing);\n\t}\n\n\tpublic void scheduleRenderUpdate() {\n\t\trefreshRenderState = true;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic IIconProvider getPipeIcons() {\n\t\tif (pipe == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn pipe.getIconProvider();\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic double getMaxRenderDistanceSquared() {\n\t\treturn 64 * 4 * 64 * 4;\n\t}\n\n\tpublic Block getBlock() {\n\t\treturn getBlockType();\n\t}\n\n\tpublic boolean isUsableByPlayer(EntityPlayer player) {\n\t\treturn world.getTileEntity(pos) == this;\n\t}\n\n\t@Override\n\tpublic boolean isInvalid() {\n\t\tif (pipe != null && pipe.preventRemove()) {\n\t\t\treturn false;\n\t\t}\n\t\treturn super.isInvalid();\n\t}\n\n\t@Override\n\tpublic LogicController getLogicController() {\n\t\treturn logicController;\n\t}\n\n\t@Override\n\tpublic ILPPipe getLPPipe() {\n\t\treturn pipe;\n\t}\n\n\t@Override\n\tpublic BlockPos getBlockPos() {\n\t\treturn getPos();\n\t}\n\n\t@Override\n\tpublic void setWorld(@Nonnull World world) {\n\t\tsuper.setWorld(world);\n\t\ttdPart.setWorld_LP(world);\n\t}\n\n\t@Nonnull\n\t@SideOnly(Side.CLIENT)\n\t@Override\n\tpublic AxisAlignedBB getRenderBoundingBox() {\n\t\tif (renderBox != null) {\n\t\t\treturn renderBox;\n\t\t}\n\t\tif (pipe == null) {\n\t\t\treturn new AxisAlignedBB(getPos(), getPos().add(1, 1, 1));\n\t\t}\n\t\tif (!pipe.isMultiBlock()) {\n\t\t\trenderBox = new AxisAlignedBB(getPos(), getPos().add(1, 1, 1));\n\t\t} else {\n\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> set = ((CoreMultiBlockPipe) pipe).getRotatedSubBlocks();\n\t\t\tset.addToAll(pipe.getLPPosition());\n\t\t\tset.add(new DoubleCoordinatesType<>(getPos(), CoreMultiBlockPipe.SubBlockTypeForShare.NON_SHARE));\n\t\t\tset.add(new DoubleCoordinatesType<>(getPos().getX() + 1, getPos().getY() + 1, getPos().getZ() + 1, CoreMultiBlockPipe.SubBlockTypeForShare.NON_SHARE));\n\t\t\trenderBox = new AxisAlignedBB(set.getMinXD() - 1, set.getMinYD() - 1, set.getMinZD() - 1, set.getMaxXD() + 1, set.getMaxYD() + 1, set.getMaxZD() + 1);\n\t\t}\n\t\treturn renderBox;\n\t}\n\n\t@Override\n\tpublic double getDistanceTo(int destinationint, EnumFacing ignore, ItemIdentifier ident, boolean isActive, double traveled, double max,\n\t\t\tList<DoubleCoordinates> visited) {\n\t\tif (pipe == null || traveled > max) {\n\t\t\treturn Integer.MAX_VALUE;\n\t\t}\n\t\tdouble result = pipe.getDistanceTo(destinationint, ignore, ident, isActive, traveled + getDistance(), max, visited);\n\t\tif (result == Integer.MAX_VALUE) {\n\t\t\treturn result;\n\t\t}\n\t\treturn result + (int) getDistance();\n\t}\n\n\t@Override\n\tpublic boolean acceptItem(LPTravelingItem item, TileEntity from) {\n\t\tif (LogisticsBlockGenericPipe.isValid(pipe) && pipe.transport != null) {\n\t\t\tpipe.transport.injectItem(item, item.output);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void refreshTileCacheOnSide(EnumFacing side) {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache != null) {\n\t\t\tcache[side.ordinal()].refresh();\n\t\t}\n\t}\n\n\tpublic boolean nonNull() {\n\t\treturn Objects.nonNull(pipe);\n\t}\n\n\t@Override\n\tpublic boolean isMultiBlock() {\n\t\treturn nonNull() && pipe.isMultiBlock();\n\t}\n\n\tpublic boolean isPipeBlock() {\n\t\treturn nonNull() && pipe.isPipeBlock();\n\t}\n\n\t@Override\n\tpublic Stream<TileEntity> getPartsOfPipe() {\n\t\treturn this.subMultiBlock.stream().map(pos -> pos.getTileEntity(world));\n\t}\n\n\tpublic static class CoreState implements IClientState {\n\n\t\tpublic int pipeId = -1;\n\n\t\t@Override\n\t\tpublic void writeData(LPDataOutput output) {\n\t\t\toutput.writeInt(pipeId);\n\n\t\t}\n\n\t\t@Override\n\t\tpublic void readData(LPDataInput input) {\n\t\t\tpipeId = input.readInt();\n\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/LogisticsTileGenericSubMultiBlock.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagString;\nimport net.minecraft.network.NetworkManager;\nimport net.minecraft.network.play.server.SPacketUpdateTileEntity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ITickable;\nimport net.minecraft.util.math.BlockPos;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.multiblock.MultiBlockCoordinatesPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.renderer.state.PipeSubRenderState;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.routing.pathfinder.ISubMultiBlockPipeInformationProvider;\nimport logisticspipes.utils.TileBuffer;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsTileGenericSubMultiBlock extends TileEntity implements ISubMultiBlockPipeInformationProvider, ITickable {\n\n\tprivate Set<DoubleCoordinates> mainPipePos = new HashSet<>();\n\tprivate List<LogisticsTileGenericPipe> mainPipe;\n\tprivate List<CoreMultiBlockPipe.SubBlockTypeForShare> subTypes = new ArrayList<>();\n\tprivate TileBuffer[] tileBuffer;\n\tpublic final PipeSubRenderState renderState;\n\n\t@Deprecated\n\tpublic LogisticsTileGenericSubMultiBlock() {\n\t\trenderState = new PipeSubRenderState();\n\t}\n\n\tpublic LogisticsTileGenericSubMultiBlock(DoubleCoordinates pos) {\n\t\tif (pos != null) {\n\t\t\tmainPipePos.add(pos);\n\t\t}\n\t\tmainPipe = null;\n\t\trenderState = new PipeSubRenderState();\n\t}\n\n\t@Override\n\tpublic void setPos(BlockPos posIn) {\n\t\tsuper.setPos(posIn);\n\t\tif (MainProxy.isClient()) {\n\t\t\tSystem.out.println(\"Multi Pipe Created at: \" + posIn);\n\t\t}\n\t}\n\n\tpublic List<LogisticsTileGenericPipe> getMainPipe() {\n\t\tif (mainPipe == null) {\n\t\t\tmainPipe = new ArrayList<>();\n\t\t\tfor (DoubleCoordinates pos : mainPipePos) {\n\t\t\t\tTileEntity tile = pos.getTileEntity(getWorld());\n\t\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\t\tmainPipe.add((LogisticsTileGenericPipe) tile);\n\t\t\t\t}\n\t\t\t}\n\t\t\tmainPipe = Collections.unmodifiableList(mainPipe);\n\t\t}\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tboolean allInvalid = true;\n\t\t\tfor (LogisticsTileGenericPipe pipe : mainPipe) {\n\t\t\t\tif (!pipe.isInvalid()) {\n\t\t\t\t\tallInvalid = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (mainPipe.isEmpty() || allInvalid) {\n\t\t\t\tgetWorld().setBlockToAir(getPos());\n\t\t\t}\n\t\t}\n\t\tif (mainPipe != null) {\n\t\t\treturn mainPipe;\n\t\t}\n\t\treturn Collections.emptyList();\n\t}\n\n\tpublic List<CoreMultiBlockPipe.SubBlockTypeForShare> getSubTypes() {\n\t\treturn Collections.unmodifiableList(subTypes);\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tList<LogisticsTileGenericPipe> pipes = getMainPipe();\n\t\tfor (LogisticsTileGenericPipe pipe : pipes) {\n\t\t\tpipe.subMultiBlock.add(new DoubleCoordinates(this));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\tsuper.readFromNBT(nbt);\n\t\tif (nbt.hasKey(\"MainPipePos_xPos\")) {\n\t\t\tmainPipePos.clear();\n\t\t\tDoubleCoordinates pos = DoubleCoordinates.readFromNBT(\"MainPipePos_\", nbt);\n\t\t\tif (pos != null) {\n\t\t\t\tmainPipePos.add(pos);\n\t\t\t}\n\t\t}\n\t\tif (nbt.hasKey(\"MainPipePosList\")) {\n\t\t\tNBTTagList list = nbt.getTagList(\"MainPipePosList\", new NBTTagCompound().getId());\n\t\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\t\tDoubleCoordinates pos = DoubleCoordinates.readFromNBT(\"MainPipePos_\", list.getCompoundTagAt(i));\n\t\t\t\tif (pos != null) {\n\t\t\t\t\tmainPipePos.add(pos);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (nbt.hasKey(\"SubTypeList\")) {\n\t\t\tNBTTagList list = nbt.getTagList(\"SubTypeList\", new NBTTagString().getId());\n\t\t\tsubTypes.clear();\n\t\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\t\tString name = list.getStringTagAt(i);\n\t\t\t\tCoreMultiBlockPipe.SubBlockTypeForShare type = CoreMultiBlockPipe.SubBlockTypeForShare.valueOf(name);\n\t\t\t\tif (type != null) {\n\t\t\t\t\tsubTypes.add(type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tmainPipe = null;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\tnbt = super.writeToNBT(nbt);\n\t\tNBTTagList nbtList = new NBTTagList();\n\t\tfor (DoubleCoordinates pos : mainPipePos) {\n\t\t\tNBTTagCompound compound = new NBTTagCompound();\n\t\t\tpos.writeToNBT(\"MainPipePos_\", compound);\n\t\t\tnbtList.appendTag(compound);\n\t\t}\n\t\tnbt.setTag(\"MainPipePosList\", nbtList);\n\t\tNBTTagList nbtTypeList = new NBTTagList();\n\t\tfor (CoreMultiBlockPipe.SubBlockTypeForShare type : subTypes) {\n\t\t\tif (type == null) continue;\n\t\t\tnbtTypeList.appendTag(new NBTTagString(type.name()));\n\t\t}\n\t\tnbt.setTag(\"SubTypeList\", nbtTypeList);\n\t\treturn nbt;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic NBTTagCompound getUpdateTag() {\n\t\tNBTTagCompound nbt = super.getUpdateTag();\n\t\ttry {\n\t\t\tPacketHandler.addPacketToNBT(getLPDescriptionPacket(), nbt);\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn nbt;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void handleUpdateTag(@Nonnull NBTTagCompound tag) {\n\t\tPacketHandler.queueAndRemovePacketFromNBT(tag);\n\t\tsuper.handleUpdateTag(tag);\n\t}\n\n\t@Override\n\tpublic SPacketUpdateTileEntity getUpdatePacket() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\ttry {\n\t\t\tPacketHandler.addPacketToNBT(getLPDescriptionPacket(), nbt);\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn new SPacketUpdateTileEntity(getPos(), 1, nbt);\n\t}\n\n\t@Override\n\tpublic void onDataPacket(NetworkManager net, SPacketUpdateTileEntity packet) {\n\t\tPacketHandler.queueAndRemovePacketFromNBT(packet.getNbtCompound());\n\t}\n\n\tpublic ModernPacket getLPDescriptionPacket() {\n\t\tMultiBlockCoordinatesPacket packet = PacketHandler.getPacket(MultiBlockCoordinatesPacket.class);\n\t\tpacket.setTilePos(this);\n\t\tpacket.setTargetPos(mainPipePos);\n\t\tpacket.setSubTypes(subTypes);\n\t\treturn packet;\n\t}\n\n\tpublic void setPosition(Set<DoubleCoordinates> lpPosition, List<CoreMultiBlockPipe.SubBlockTypeForShare> subTypes) {\n\t\tmainPipePos = lpPosition;\n\t\tthis.subTypes = subTypes;\n\t\tmainPipe = null;\n\t}\n\n\tpublic TileEntity getTile() {\n\t\treturn this;\n\t}\n\n\tpublic TileEntity getTile(EnumFacing to) {\n\t\treturn getTile(to, false);\n\t}\n\n\tpublic TileEntity getTile(EnumFacing to, boolean force) {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache != null) {\n\t\t\tif (force) {\n\t\t\t\tcache[to.ordinal()].refresh();\n\t\t\t}\n\t\t\treturn cache[to.ordinal()].getTile();\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic Block getBlock(EnumFacing to) {\n\t\tTileBuffer[] cache = getTileCache();\n\t\tif (cache != null) {\n\t\t\treturn cache[to.ordinal()].getBlock();\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic TileBuffer[] getTileCache() {\n\t\tif (tileBuffer == null) {\n\t\t\ttileBuffer = TileBuffer.makeBuffer(world, getPos(), true);\n\t\t}\n\t\treturn tileBuffer;\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\ttileBuffer = null;\n\t}\n\n\t@Override\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\ttileBuffer = null;\n\t}\n\n\tpublic void scheduleNeighborChange() {\n\t\ttileBuffer = null;\n\t}\n\n\tpublic void addSubTypeTo(CoreMultiBlockPipe.SubBlockTypeForShare type) {\n\t\tif (type == null) throw new NullPointerException();\n\t\tsubTypes.add(type);\n\t}\n\n\tpublic void addMultiBlockMainPos(DoubleCoordinates placeAt) {\n\t\tif (mainPipePos.add(placeAt)) {\n\t\t\tmainPipe = null;\n\t\t}\n\t}\n\n\tpublic boolean removeMainPipe(DoubleCoordinates doubleCoordinates) {\n\t\tmainPipePos.remove(doubleCoordinates);\n\t\treturn mainPipePos.isEmpty();\n\t}\n\n\tpublic void removeSubType(CoreMultiBlockPipe.SubBlockTypeForShare type) {\n\t\tsubTypes.remove(type);\n\t}\n\n\t@Override\n\tpublic IPipeInformationProvider getMainTile() {\n\t\tList<LogisticsTileGenericPipe> mainTiles = this.getMainPipe();\n\t\tif (mainTiles.size() != 1) {\n\t\t\treturn null;\n\t\t}\n\t\treturn mainTiles.get(0);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/PowerSupplierHandler.java",
    "content": "package logisticspipes.pipes.basic;\n\nimport java.util.List;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagFloat;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerProviderTileEntity;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.cofh.subproxies.ICoFHEnergyReceiver;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntity;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper;\n\npublic class PowerSupplierHandler {\n\n\tprivate static final double INTERNAL_RF_BUFFER_MAX = 10000;\n\tprivate static final double INTERNAL_IC2_BUFFER_MAX = 2048 * 4;\n\n\tprivate final CoreRoutedPipe pipe;\n\n\tprivate double internalBufferRF = 0F;\n\tprivate double internalBufferIC2 = 0F;\n\n\tpublic PowerSupplierHandler(CoreRoutedPipe pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tif (internalBufferRF > 0) {\n\t\t\tnbttagcompound.setDouble(\"bufferRF\", internalBufferRF);\n\t\t}\n\t\tif (internalBufferIC2 > 0) {\n\t\t\tnbttagcompound.setDouble(\"bufferEU\", internalBufferIC2);\n\t\t}\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tif (nbttagcompound.getTag(\"bufferRF\") instanceof NBTTagFloat) { // support for old float\n\t\t\tinternalBufferRF = nbttagcompound.getFloat(\"bufferRF\");\n\t\t} else {\n\t\t\tinternalBufferRF = nbttagcompound.getDouble(\"bufferRF\");\n\t\t}\n\t\tif (nbttagcompound.getTag(\"bufferEU\") instanceof NBTTagFloat) { // support for old float\n\t\t\tinternalBufferRF = nbttagcompound.getFloat(\"bufferEU\");\n\t\t} else {\n\t\t\tinternalBufferRF = nbttagcompound.getDouble(\"bufferEU\");\n\t\t}\n\t}\n\n\tpublic void update() {\n\t\tif (SimpleServiceLocator.powerProxy.isAvailable() && pipe.getUpgradeManager().hasRFPowerSupplierUpgrade()) {\n\t\t\tif (requestRFPower()) return;\n\t\t}\n\t\tif (SimpleServiceLocator.IC2Proxy.hasIC2() && pipe.getUpgradeManager().getIC2PowerLevel() > 0) {\n\t\t\trequestICPower();\n\t\t}\n\t}\n\n\tprivate void requestICPower() {\n\t\t//Use Buffer\n\n\t\tfinal List<LPNeighborTileEntity<TileEntity>> adjacentTileEntities = new WorldCoordinatesWrapper(pipe.container).allNeighborTileEntities();\n\n\t\tdouble globalNeed = 0;\n\t\tdouble[] need = new double[adjacentTileEntities.size()];\n\t\tint i = 0;\n\t\tfor (NeighborTileEntity<TileEntity> adjacent : adjacentTileEntities) {\n\t\t\tif (SimpleServiceLocator.IC2Proxy.isEnergySink(adjacent.getTileEntity())) {\n\t\t\t\tif (pipe.canPipeConnect(adjacent.getTileEntity(), adjacent.getDirection())) {\n\t\t\t\t\tif (SimpleServiceLocator.IC2Proxy.acceptsEnergyFrom(adjacent.getTileEntity(), pipe.container, adjacent.getOurDirection())) { // TODO pipe.container must be IEnergySource\n\t\t\t\t\t\tglobalNeed += need[i] = SimpleServiceLocator.IC2Proxy.demandedEnergyUnits(adjacent.getTileEntity());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t++i;\n\t\t}\n\n\t\tif (globalNeed != 0 && !Double.isNaN(globalNeed)) {\n\t\t\tdouble fullfillable = Math.min(1, internalBufferIC2 / globalNeed);\n\t\t\ti = 0;\n\t\t\tfor (NeighborTileEntity<TileEntity> adjacent : adjacentTileEntities) {\n\t\t\t\tif (SimpleServiceLocator.IC2Proxy.isEnergySink(adjacent.getTileEntity()) && pipe.canPipeConnect(adjacent.getTileEntity(), adjacent.getDirection())\n\t\t\t\t\t\t&& SimpleServiceLocator.IC2Proxy.acceptsEnergyFrom(adjacent.getTileEntity(), pipe.container, adjacent.getOurDirection())) { // TODO pipe.container must be IEnergySource\n\t\t\t\t\tif (internalBufferIC2 + 1 < need[i] * fullfillable) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tdouble toUse = Math.min(pipe.getUpgradeManager().getIC2PowerLevel(), need[i] * fullfillable);\n\t\t\t\t\tdouble unUsed = SimpleServiceLocator.IC2Proxy.injectEnergyUnits(adjacent.getTileEntity(), adjacent.getOurDirection(), toUse);\n\t\t\t\t\tdouble used = toUse - unUsed;\n\t\t\t\t\tif (used > 0) {\n\t\t\t\t\t\t//MainProxy.sendPacketToAllWatchingChunk(this.pipe.getX(), this.pipe.getZ(), MainProxy.getDimensionForWorld(this.pipe.getWorld()), PacketHandler.getPacket(PowerPacketLaser.class).setColor(LogisticsPowerProviderTileEntity.IC2_COLOR).setPos(this.pipe.getLPPosition()).setRenderBall(true).setDir(adTile.orientation).setLength(0.5F));\n\t\t\t\t\t\tpipe.container.addLaser(adjacent.getDirection(), 0.5F, LogisticsPowerProviderTileEntity.IC2_COLOR, false, true);\n\t\t\t\t\t\tinternalBufferIC2 -= used;\n\t\t\t\t\t}\n\t\t\t\t\tif (internalBufferIC2 < 0) {\n\t\t\t\t\t\tinternalBufferIC2 = 0;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\n\t\t//Rerequest Buffer\n\t\tList<Pair<ISubSystemPowerProvider, List<IFilter>>> provider = pipe.getRouter().getSubSystemPowerProvider();\n\t\tdouble available = 0;\n\t\touter:\n\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> pair : provider) {\n\t\t\tfor (IFilter filter : pair.getValue2()) {\n\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pair.getValue1().usePaused()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!pair.getValue1().getBrand().equals(\"EU\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tavailable += pair.getValue1().getPowerLevel();\n\t\t}\n\t\tif (available > 0) {\n\t\t\tdouble neededPower = PowerSupplierHandler.INTERNAL_IC2_BUFFER_MAX - internalBufferIC2;\n\t\t\tif (neededPower > 0) {\n\t\t\t\tif (pipe.useEnergy((int) (neededPower / 10000), false)) {\n\t\t\t\t\touter:\n\t\t\t\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> pair : provider) {\n\t\t\t\t\t\tfor (IFilter filter : pair.getValue2()) {\n\t\t\t\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pair.getValue1().usePaused()) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!pair.getValue1().getBrand().equals(\"EU\")) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdouble requestamount = neededPower * (pair.getValue1().getPowerLevel() / available);\n\t\t\t\t\t\tpair.getValue1().requestPower(pipe.getRouterId(), requestamount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate boolean requestRFPower() {\n\t\t//Use Buffer\n\n\t\tfinal List<LPNeighborTileEntity<TileEntity>> adjacentTileEntities = new WorldCoordinatesWrapper(pipe.container).allNeighborTileEntities();\n\n\t\tdouble globalNeed = 0;\n\t\tdouble[] need = new double[adjacentTileEntities.size()];\n\t\tint i = 0;\n\t\tfor (NeighborTileEntity<TileEntity> adjacent : adjacentTileEntities) {\n\t\t\tif (SimpleServiceLocator.powerProxy.isEnergyReceiver(adjacent.getTileEntity(), adjacent.getOurDirection())) {\n\t\t\t\tif (pipe.canPipeConnect(adjacent.getTileEntity(), adjacent.getDirection())) {\n\t\t\t\t\tICoFHEnergyReceiver energyReceiver = SimpleServiceLocator.powerProxy.getEnergyReceiver(adjacent.getTileEntity(), adjacent.getOurDirection());\n\t\t\t\t\tglobalNeed += need[i] = (energyReceiver.getMaxEnergyStored() - energyReceiver.getEnergyStored());\n\t\t\t\t}\n\t\t\t}\n\t\t\t++i;\n\t\t}\n\n\t\tif (globalNeed != 0 && !Double.isNaN(globalNeed)) {\n\t\t\tdouble fullfillable = Math.min(1, internalBufferRF / globalNeed);\n\t\t\ti = 0;\n\t\t\tfor (NeighborTileEntity<TileEntity> adjacent : adjacentTileEntities) {\n\t\t\t\tif (SimpleServiceLocator.powerProxy.isEnergyReceiver(adjacent.getTileEntity(), adjacent.getOurDirection())) {\n\t\t\t\t\tif (pipe.canPipeConnect(adjacent.getTileEntity(), adjacent.getDirection())) {\n\t\t\t\t\t\tEnumFacing oppositeDir = adjacent.getOurDirection();\n\t\t\t\t\t\tICoFHEnergyReceiver energyReceiver = SimpleServiceLocator.powerProxy.getEnergyReceiver(adjacent.getTileEntity(), oppositeDir);\n\t\t\t\t\t\tif (internalBufferRF + 1 < need[i] * fullfillable) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tint used = energyReceiver.receiveEnergy(oppositeDir, (int) (need[i] * fullfillable), false);\n\t\t\t\t\t\tif (used > 0) {\n\t\t\t\t\t\t\tpipe.container.addLaser(adjacent.getDirection(), 0.5F, LogisticsPowerProviderTileEntity.RF_COLOR, false, true);\n\t\t\t\t\t\t\tinternalBufferRF -= used;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (internalBufferRF < 0) {\n\t\t\t\t\t\t\tinternalBufferRF = 0;\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\t//Rerequest Buffer\n\t\tList<Pair<ISubSystemPowerProvider, List<IFilter>>> provider = pipe.getRouter().getSubSystemPowerProvider();\n\t\tdouble available = 0;\n\t\touter:\n\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> pair : provider) {\n\t\t\tfor (IFilter filter : pair.getValue2()) {\n\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (pair.getValue1().usePaused()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!pair.getValue1().getBrand().equals(\"RF\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tavailable += pair.getValue1().getPowerLevel();\n\t\t}\n\t\tif (available > 0) {\n\t\t\tdouble neededPower = PowerSupplierHandler.INTERNAL_RF_BUFFER_MAX - internalBufferRF;\n\t\t\tif (neededPower > 0) {\n\t\t\t\tif (pipe.useEnergy((int) (neededPower / 100), false)) {\n\t\t\t\t\touter:\n\t\t\t\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> pair : provider) {\n\t\t\t\t\t\tfor (IFilter filter : pair.getValue2()) {\n\t\t\t\t\t\t\tif (filter.blockPower()) {\n\t\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pair.getValue1().usePaused()) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!pair.getValue1().getBrand().equals(\"RF\")) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdouble requestamount = neededPower * (pair.getValue1().getPowerLevel() / available);\n\t\t\t\t\t\tpair.getValue1().requestPower(pipe.getRouterId(), requestamount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void addRFPower(double toSend) {\n\t\tinternalBufferRF += toSend;\n\t}\n\n\tpublic void addIC2Power(double toSend) {\n\t\tinternalBufferIC2 += toSend;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/debug/DebugLogController.java",
    "content": "package logisticspipes.pipes.basic.debug;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.debug.SendNewLogLine;\nimport logisticspipes.network.packets.debug.SendNewLogWindow;\nimport logisticspipes.network.packets.debug.UpdateStatusEntries;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.PlayerCollectionList;\n\npublic class DebugLogController {\n\n\tprivate static int nextID = 0;\n\tprivate final int ID = DebugLogController.nextID++;\n\tpublic final CoreUnroutedPipe pipe;\n\tpublic boolean debugThisPipe = false;\n\tprivate List<StatusEntry> oldList = new ArrayList<>();\n\tprivate PlayerCollectionList players = new PlayerCollectionList();\n\n\tpublic DebugLogController(CoreUnroutedPipe pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\tpublic void log(String info) {\n\t\tif (players.isEmptyWithoutCheck()) {\n\t\t\treturn;\n\t\t}\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(SendNewLogLine.class).setWindowID(ID).setLine(info), players);\n\t}\n\n\tpublic void tick() {\n\t\tif (players.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tgenerateStatus();\n\t}\n\n\tpublic void generateStatus() {\n\t\tList<StatusEntry> status = new ArrayList<>();\n\t\tpipe.addStatusInformation(status);\n\t\tif (!status.equals(oldList)) {\n\t\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(UpdateStatusEntries.class).setWindowID(ID).setStatus(status), players);\n\t\t\toldList = status;\n\t\t}\n\t}\n\n\tpublic void openForPlayer(EntityPlayer player) {\n\t\tplayers.add(player);\n\t\tList<StatusEntry> status = new ArrayList<>();\n\t\tpipe.addStatusInformation(status);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SendNewLogWindow.class).setWindowID(ID).setTitle(pipe.toString()), player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(UpdateStatusEntries.class).setWindowID(ID).setStatus(status), player);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/debug/LogWindow.java",
    "content": "package logisticspipes.pipes.basic.debug;\n\nimport java.awt.BorderLayout;\nimport java.awt.GridLayout;\nimport java.awt.event.KeyEvent;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.swing.JFrame;\nimport javax.swing.JPanel;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTabbedPane;\nimport javax.swing.JTextPane;\nimport javax.swing.JTree;\nimport javax.swing.text.BadLocationException;\nimport javax.swing.text.Document;\nimport javax.swing.text.SimpleAttributeSet;\nimport javax.swing.text.StyleConstants;\nimport javax.swing.tree.DefaultMutableTreeNode;\nimport javax.swing.tree.DefaultTreeModel;\n\n@SuppressWarnings(\"serial\")\npublic class LogWindow extends JPanel {\n\n\tprivate static Map<Integer, LogWindow> map = new HashMap<>();\n\n\tpublic static LogWindow getWindow(int id) {\n\t\tLogWindow window = LogWindow.map.get(id);\n\t\tif (window == null) {\n\t\t\twindow = new LogWindow();\n\t\t\tLogWindow.map.put(id, window);\n\t\t}\n\t\treturn window;\n\t}\n\n\tprivate JTextPane logArea;\n\tprivate DefaultMutableTreeNode baseNode;\n\tprivate JTree tree;\n\tprivate List<StatusEntry> currentLayout = new ArrayList<>(0);\n\tprivate JFrame frame;\n\n\tprivate LogWindow() {\n\t\tsuper(new GridLayout(1, 1));\n\t\tJTabbedPane tabbedPane = new JTabbedPane();\n\n\t\tlogArea = new JTextPane();\n\t\tJScrollPane logPane = new JScrollPane(logArea);\n\t\ttabbedPane.addTab(\"Console\", null, logPane, \"\");\n\t\ttabbedPane.setMnemonicAt(0, KeyEvent.VK_1);\n\n\t\tbaseNode = new DefaultMutableTreeNode(\"State Information\");\n\t\ttree = new JTree(baseNode);\n\t\t// tree.addTreeExpansionListener(this);\n\t\t// tree.addMouseListener(this);\n\t\tJScrollPane treeView = new JScrollPane(tree);\n\t\ttabbedPane.addTab(\"Status List\", null, treeView, \"\");\n\t\ttabbedPane.setMnemonicAt(1, KeyEvent.VK_2);\n\t\tadd(tabbedPane);\n\t\tcreateAndShowGUI();\n\t}\n\n\tprivate void createAndShowGUI() {\n\t\tframe = new JFrame(\"\");\n\t\t//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\n\t\tframe.add(this, BorderLayout.CENTER);\n\t\tframe.pack();\n\t\tframe.setVisible(true);\n\t}\n\n\tpublic void newLine(String data) {\n\t\tSimpleAttributeSet attr = new SimpleAttributeSet();\n\t\tStyleConstants.setFontFamily(attr, \"SansSerif\");\n\t\tStyleConstants.setFontSize(attr, 12);\n\t\t// StyleConstants.setForeground(attr, color);\n\t\tDocument document = logArea.getDocument();\n\t\tif (document != null) {\n\t\t\ttry {\n\t\t\t\tdocument.insertString(document.getLength(), data + \"\\n\", attr);\n\t\t\t} catch (BadLocationException ignored) {}\n\t\t}\n\t\tvalidate();\n\t}\n\n\tpublic void clear() {\n\t\tlogArea.setText(\"\");\n\t\tvalidate();\n\t}\n\n\tpublic void updateStatus(List<StatusEntry> entries) {\n\t\tcompareLists(entries, currentLayout, baseNode);\n\t\tcurrentLayout = entries;\n\t\t// this.validate();\n\t}\n\n\tprivate void compareLists(List<StatusEntry> newList, List<StatusEntry> oldList, DefaultMutableTreeNode node) {\n\t\tfor (int i = 0; i < newList.size() && i < oldList.size(); i++) {\n\t\t\tif (!newList.get(i).equals(oldList.get(i))) {\n\t\t\t\tStatusEntry entry = newList.get(i);\n\t\t\t\tDefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);\n\t\t\t\tchild.setUserObject(entry.name);\n\t\t\t\tif (entry.subEntry != null) {\n\t\t\t\t\tif (oldList.get(i).subEntry != null) {\n\t\t\t\t\t\tcompareLists(entry.subEntry, oldList.get(i).subEntry, child);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcompareLists(entry.subEntry, new ArrayList<>(0), child);\n\t\t\t\t\t}\n\t\t\t\t} else if (oldList.get(i).subEntry != null) {\n\t\t\t\t\tchild.removeAllChildren();\n\t\t\t\t}\n\t\t\t\t((DefaultTreeModel) tree.getModel()).reload(child);\n\t\t\t}\n\t\t}\n\t\tfor (int i = newList.size(); i < oldList.size(); i++) {\n\t\t\tnode.remove(i);\n\t\t\t((DefaultTreeModel) tree.getModel()).reload(node);\n\t\t}\n\t\tfor (int i = oldList.size(); i < newList.size(); i++) {\n\t\t\tStatusEntry entry = newList.get(i);\n\t\t\tDefaultMutableTreeNode newNode = new DefaultMutableTreeNode(entry.name);\n\t\t\tnode.add(newNode);\n\t\t\tif (entry.subEntry != null) {\n\t\t\t\tcompareLists(entry.subEntry, new ArrayList<>(0), newNode);\n\t\t\t}\n\t\t\t((DefaultTreeModel) tree.getModel()).reload(node);\n\t\t}\n\t}\n\n\tpublic void setTitle(String title) {\n\t\tframe.setName(title);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/debug/StatusEntry.java",
    "content": "package logisticspipes.pipes.basic.debug;\n\nimport java.util.List;\n\nimport lombok.Data;\n\n@Data\npublic class StatusEntry {\n\n\tpublic String name;\n\tpublic List<StatusEntry> subEntry;\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/fluid/FluidRoutedPipe.java",
    "content": "package logisticspipes.pipes.basic.fluid;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fluids.FluidStack;\nimport net.minecraftforge.fluids.FluidTank;\nimport net.minecraftforge.fluids.capability.CapabilityFluidHandler;\nimport net.minecraftforge.fluids.capability.IFluidHandler;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITankUtil;\nimport logisticspipes.interfaces.routing.IRequireReliableFluidTransport;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.PipeFluidUtil;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.order.LogisticsFluidOrderManager;\nimport logisticspipes.routing.order.LogisticsOrderManager;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.textures.Textures.TextureType;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.CacheHolder.CacheTypes;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.FluidSinkReply;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntityKt;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\n\npublic abstract class FluidRoutedPipe extends CoreRoutedPipe {\n\n\tprivate LogisticsFluidOrderManager _orderFluidManager;\n\n\tpublic FluidRoutedPipe(Item item) {\n\t\tsuper(new PipeFluidTransportLogistics(), item);\n\t}\n\n\t@Override\n\tpublic void setTile(TileEntity tile) {\n\t\tsuper.setTile(tile);\n\t}\n\n\t@Override\n\tpublic boolean logisitcsIsPipeConnected(TileEntity tile, EnumFacing dir) {\n\t\tITankUtil tank = PipeFluidUtil.INSTANCE.getTankUtilForTE(tile, dir.getOpposite());\n\t\treturn (tank != null && tank.containsTanks()) || tile instanceof LogisticsTileGenericPipe;\n\t}\n\n\t@Override\n\tpublic ItemSendMode getItemSendMode() {\n\t\treturn ItemSendMode.Normal;\n\t}\n\n\t@Override\n\tpublic TextureType getNonRoutedTexture(EnumFacing connection) {\n\t\tif (isFluidSidedTexture(connection)) {\n\t\t\treturn Textures.LOGISTICSPIPE_LIQUID_TEXTURE;\n\t\t}\n\t\treturn super.getNonRoutedTexture(connection);\n\t}\n\n\tprivate boolean isFluidSidedTexture(EnumFacing connection) {\n\t\treturn getAvailableAdjacent().fluidTanks().stream()\n\t\t\t\t.filter(neighbor -> neighbor.getDirection() == connection)\n\t\t\t\t.findFirst()\n\t\t\t\t.map(neighbor -> {\n\t\t\t\t\tfinal ITankUtil tankUtil = LPNeighborTileEntityKt.getTankUtil(neighbor);\n\t\t\t\t\treturn tankUtil != null && tankUtil.containsTanks();\n\t\t\t\t})\n\t\t\t\t.orElse(false);\n\t}\n\n\t@Override\n\tpublic @Nullable LogisticsModule getLogisticsModule() {\n\t\treturn null;\n\t}\n\n\t/***\n\t * @param tile\n\t *            The connected TileEntity\n\t * @param dir\n\t *            The direction the TileEntity is in relative to the currect\n\t *            pipe\n\t * @param flag\n\t *            Weather to list a Nearby Pipe or not\n\t */\n\n\tpublic final boolean isConnectableTank(TileEntity tile, EnumFacing dir, boolean flag) {\n\t\tif (SimpleServiceLocator.specialTankHandler.hasHandlerFor(tile)) {\n\t\t\treturn true;\n\t\t}\n\t\tboolean fluidTile = false;\n\t\tif (tile != null && tile.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dir)) {\n\t\t\tIFluidHandler fluidHandler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dir);\n\t\t\tif (fluidHandler != null) {\n\t\t\t\tfluidTile = true;\n\t\t\t}\n\t\t}\n\t\tif (tile instanceof IFluidHandler) {\n\t\t\tfluidTile = true;\n\t\t}\n\t\tif (!fluidTile) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!this.canPipeConnect(tile, dir)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tif (((LogisticsTileGenericPipe) tile).pipe instanceof FluidRoutedPipe) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!flag) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (((LogisticsTileGenericPipe) tile).pipe == null || !(((LogisticsTileGenericPipe) tile).pipe.transport instanceof IFluidHandler)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void enabledUpdateEntity() {\n\t\tsuper.enabledUpdateEntity();\n\t\tif (canInsertFromSideToTanks()) {\n\t\t\tint validDirections = 0;\n\t\t\tfinal List<Pair<NeighborTileEntity<TileEntity>, ITankUtil>> list =\n\t\t\t\t\tPipeFluidUtil.INSTANCE.getAdjacentTanks(this, true);\n\t\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> pair : list) {\n\t\t\t\tif (pair.getValue2() instanceof LogisticsTileGenericPipe) {\n\t\t\t\t\tif (((LogisticsTileGenericPipe) pair.getValue2()).pipe instanceof CoreRoutedPipe) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tFluidTank internalTank = ((PipeFluidTransportLogistics) transport).sideTanks[pair.getValue1().getDirection().ordinal()];\n\t\t\t\tvalidDirections++;\n\t\t\t\tif (internalTank.getFluid() == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tint filled = pair.getValue2().fill(FluidIdentifierStack.getFromStack(internalTank.getFluid()), true);\n\t\t\t\tif (filled == 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tFluidStack drain = internalTank.drain(filled, true);\n\t\t\t\tif (drain == null || filled != drain.amount) {\n\t\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Fluid Multiplication\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (validDirections == 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tFluidTank tank = ((PipeFluidTransportLogistics) transport).internalTank;\n\t\t\tFluidStack stack = tank.getFluid();\n\t\t\tif (stack == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> pair : list) {\n\t\t\t\tif (pair.getValue1().isLogisticsPipe()) {\n\t\t\t\t\tif (((LogisticsTileGenericPipe) pair.getValue1().getTileEntity()).pipe instanceof CoreRoutedPipe) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tFluidTank tankSide = ((PipeFluidTransportLogistics) transport).sideTanks[pair.getValue1().getDirection().ordinal()];\n\t\t\t\tstack = tank.getFluid();\n\t\t\t\tif (stack == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tstack = stack.copy();\n\t\t\t\tint filled = tankSide.fill(stack, true);\n\t\t\t\tif (filled == 0) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tFluidStack drain = tank.drain(filled, true);\n\t\t\t\tif (drain == null || filled != drain.amount) {\n\t\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Fluid Multiplication\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int countOnRoute(FluidIdentifier ident) {\n\t\tint amount = 0;\n\t\tfor (ItemRoutingInformation next : _inTransitToMe) {\n\t\t\tItemIdentifierStack item = next.getItem();\n\t\t\tif (item.getItem().isFluidContainer()) {\n\t\t\t\tFluidIdentifierStack liquid = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(item);\n\t\t\t\tif (liquid.getFluid().equals(ident)) {\n\t\t\t\t\tamount += liquid.getAmount();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn amount;\n\t}\n\n\tpublic abstract boolean canInsertFromSideToTanks();\n\n\tpublic abstract boolean canInsertToTanks();\n\n\tpublic abstract boolean canReceiveFluid();\n\n\tpublic boolean endReached(LPTravelingItemServer arrivingItem, TileEntity tile) {\n\t\tif (canInsertToTanks() && MainProxy.isServer(getWorld())) {\n\t\t\tgetCacheHolder().trigger(CacheTypes.Inventory);\n\t\t\tif (arrivingItem.getItemIdentifierStack() == null || !(arrivingItem.getItemIdentifierStack().getItem().isFluidContainer())) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (getRouter().getSimpleID() != arrivingItem.getDestination()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tint filled;\n\t\t\tFluidIdentifierStack liquid = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(arrivingItem.getItemIdentifierStack());\n\t\t\tif (isConnectableTank(tile, arrivingItem.output, false)) {\n\t\t\t\t//Try to put liquid into all adjacent tanks.\n\t\t\t\tfor (Pair<NeighborTileEntity<TileEntity>, ITankUtil> util : PipeFluidUtil.INSTANCE.getAdjacentTanks(this, false)) {\n\t\t\t\t\tfilled = util.getValue2().fill(liquid, true);\n\t\t\t\t\tliquid.lowerAmount(filled);\n\t\t\t\t\tif (liquid.getAmount() != 0) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t//Try inserting the liquid into the pipe side tank\n\t\t\t\tfilled = ((PipeFluidTransportLogistics) transport).sideTanks[arrivingItem.output.ordinal()].fill(liquid.makeFluidStack(), true);\n\t\t\t\tif (filled == liquid.getAmount()) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tliquid.lowerAmount(filled);\n\t\t\t}\n\t\t\t//Try inserting the liquid into the pipe internal tank\n\t\t\tfilled = ((PipeFluidTransportLogistics) transport).internalTank.fill(liquid.makeFluidStack(), true);\n\t\t\tif (filled == liquid.getAmount()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t//If liquids still exist,\n\t\t\tliquid.lowerAmount(filled);\n\n\t\t\t//TODO: FIX THIS\n\t\t\tif (this instanceof IRequireReliableFluidTransport) {\n\t\t\t\t((IRequireReliableFluidTransport) this).liquidNotInserted(liquid.getFluid(), liquid.getAmount());\n\t\t\t}\n\n\t\t\tIRoutedItem routedItem = SimpleServiceLocator.routedItemHelper.createNewTravelItem(SimpleServiceLocator.logisticsFluidManager.getFluidContainer(liquid));\n\t\t\tPair<Integer, FluidSinkReply> replies = SimpleServiceLocator.logisticsFluidManager.getBestReply(liquid, getRouter(), routedItem.getJamList());\n\t\t\tif (replies == null) {\n\t\t\t\t// clear destination without marking item as lost\n\t\t\t\troutedItem.setDestination(0);\n\t\t\t} else {\n\t\t\t\tint dest = replies.getValue1();\n\t\t\t\troutedItem.setDestination(dest);\n\t\t\t}\n\t\t\troutedItem.setTransportMode(TransportMode.Passive);\n\t\t\tthis.queueRoutedItem(routedItem, arrivingItem.output.getOpposite());\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isFluidPipe() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isOnSameContainer(CoreRoutedPipe other) {\n\t\tif (!(other instanceof FluidRoutedPipe)) {\n\t\t\treturn false;\n\t\t}\n\t\tList<TileEntity> theirs = PipeFluidUtil.INSTANCE.getAllTankTiles((FluidRoutedPipe) other);\n\t\tfor (TileEntity tile : PipeFluidUtil.INSTANCE.getAllTankTiles(this)) {\n\t\t\tif (theirs.contains(tile)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic LogisticsFluidOrderManager getFluidOrderManager() {\n\t\t_orderFluidManager = _orderFluidManager != null ? _orderFluidManager : new LogisticsFluidOrderManager(this);\n\t\treturn _orderFluidManager;\n\t}\n\n\t@Override\n\tpublic LogisticsOrderManager<?, ?> getOrderManager() {\n\t\treturn getFluidOrderManager();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/ltgpmodcompat/LPDuctHolderTileEntity.java",
    "content": "package logisticspipes.pipes.basic.ltgpmodcompat;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.util.math.BlockPos;\n\nimport cofh.thermaldynamics.duct.tiles.DuctToken;\nimport cofh.thermaldynamics.duct.tiles.DuctUnit;\nimport cofh.thermaldynamics.duct.tiles.IDuctHolder;\nimport cofh.thermaldynamics.multiblock.MultiBlockGrid;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.proxy.td.subproxies.ITDPart;\n\n@ModDependentInterface(modId = { LPConstants.thermalDynamicsModID }, interfacePath = { \"cofh.thermaldynamics.duct.tiles.IDuctHolder\" })\npublic abstract class LPDuctHolderTileEntity extends LPMicroblockTileEntity implements IDuctHolder {\n\n\tpublic ITDPart tdPart;\n\n\t@Nullable\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.thermalDynamicsModID)\n\tpublic <T extends DuctUnit<T, G, C>, G extends MultiBlockGrid<T>, C> T getDuct(DuctToken<T, G, C> ductToken) {\n\t\treturn ((IDuctHolder) tdPart.getInternalDuct()).getDuct(ductToken);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.thermalDynamicsModID)\n\tpublic boolean isSideBlocked(int i) {\n\t\treturn tdPart.isLPSideBlocked(i);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.thermalDynamicsModID)\n\tpublic void setPos(BlockPos pos) {\n\t\tsuper.setPos(pos);\n\t\ttdPart.setPos(pos);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/ltgpmodcompat/LPMicroblockBlock.java",
    "content": "package logisticspipes.pipes.basic.ltgpmodcompat;\n\nimport java.util.Optional;\nimport java.util.Random;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.BlockContainer;\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.state.BlockFaceShape;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.particle.ParticleDigging;\nimport net.minecraft.client.particle.ParticleManager;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.EntityLiving;\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumBlockRenderType;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.EnumHand;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.Explosion;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.IPlantable;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport mcmultipart.MCMultiPart;\nimport mcmultipart.RayTraceHelper;\nimport mcmultipart.api.container.IMultipartContainerBlock;\nimport mcmultipart.api.container.IPartInfo;\nimport mcmultipart.api.slot.IPartSlot;\nimport static mcmultipart.block.BlockMultipartContainer.getTile;\nimport mcmultipart.block.TileMultipartContainer;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPBlockAccess;\n\n@ModDependentInterface(modId = { LPConstants.mcmpModID }, interfacePath = { \"mcmultipart.api.container.IMultipartContainerBlock\" })\npublic abstract class LPMicroblockBlock extends BlockContainer implements IMultipartContainerBlock {\n\n\tpublic static IMCMPBlockAccess mcmpBlockAccess = SimpleServiceLocator.mcmpProxy.createMCMPBlockAccess();\n\n\tpublic LPMicroblockBlock(Material materialIn) {\n\t\tsuper(materialIn);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean getWeakChanges(IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getWeakChanges(world, pos) : super.getWeakChanges(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isFertile(@Nonnull World world, @Nonnull BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isFertile(world, pos) : super.isFertile(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Boolean isEntityInsideMaterial(IBlockAccess world, BlockPos pos, IBlockState state, Entity entity, double yToTest, Material material,\n\t\t\tboolean testingHead) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isEntityInsideMaterial(world, pos, state, entity, yToTest, material, testingHead) : super.isEntityInsideMaterial(world, pos, state, entity, yToTest, material, testingHead);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isPassable(IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isPassable(world, pos) : super.isPassable(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onPlantGrow(IBlockState state, @Nonnull World world, @Nonnull BlockPos pos, BlockPos source) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.onPlantGrow(state, world, pos, source);\n\t\t} else {\n\t\t\tsuper.onPlantGrow(state, world, pos, source);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic int getStrongPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getStrongPower(state, world, pos, side) : super.getStrongPower(state, world, pos, side);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean getTickRandomly() {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getTickRandomly() : super.getTickRandomly();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Boolean isAABBInsideMaterial(World world, BlockPos pos, AxisAlignedBB boundingBox, Material material) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isAABBInsideMaterial(world, pos, boundingBox, material) : super.isAABBInsideMaterial(world, pos, boundingBox, material);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random rand) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.randomDisplayTick(state, world, pos, rand);\n\t\t} else {\n\t\t\tsuper.randomDisplayTick(state, world, pos, rand);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onEntityCollision(World worldIn, BlockPos pos, IBlockState state, Entity entityIn) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.onEntityCollision(worldIn, pos, state, entityIn);\n\t\t} else {\n\t\t\tsuper.onEntityCollision(worldIn, pos, state, entityIn);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean hasCustomBreakingProgress(IBlockState state) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.hasCustomBreakingProgress(state) : super.hasCustomBreakingProgress(state);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void updateTick(World world, BlockPos pos, IBlockState state, Random rand) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.updateTick(world, pos, state, rand);\n\t\t} else {\n\t\t\tsuper.updateTick(world, pos, state, rand);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isBurning(IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isBurning(world, pos) : super.isBurning(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean canSustainLeaves(IBlockState state, IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.canSustainLeaves(state, world, pos) : super.canSustainLeaves(state, world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic int getComparatorInputOverride(IBlockState blockState, World world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getComparatorInputOverride(blockState, world, pos) : super.getComparatorInputOverride(blockState, world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void randomTick(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Random random) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.randomTick(world, pos, state, random);\n\t\t} else {\n\t\t\tsuper.randomTick(world, pos, state, random);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isSideSolid(IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos, EnumFacing side) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isSideSolid(state, world, pos, side) : super.isSideSolid(state, world, pos, side);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic int getLightOpacity(IBlockState state, IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getLightOpacity(state, world, pos) : super.getLightOpacity(state, world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic float getEnchantPowerBonus(World world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getEnchantPowerBonus(world, pos) : super.getEnchantPowerBonus(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isLadder(IBlockState state, IBlockAccess world, BlockPos pos, EntityLivingBase entity) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isLadder(state, world, pos, entity) : super.isLadder(state, world, pos, entity);\n\t}\n\n\t@Nonnull\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic BlockFaceShape getBlockFaceShape(IBlockAccess world, IBlockState state, BlockPos pos, EnumFacing face) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getBlockFaceShape(world, state, pos, face) : super.getBlockFaceShape(world, state, pos, face);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isLeaves(IBlockState state, IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isLeaves(state, world, pos) : super.isLeaves(state, world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic float getExplosionResistance(World world, BlockPos pos, Entity exploder, Explosion explosion) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getExplosionResistance(world, pos, exploder, explosion) : super.getExplosionResistance(world, pos, exploder, explosion);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.neighborChanged(state, worldIn, pos, blockIn, fromPos);\n\t\t} else {\n\t\t\tsuper.neighborChanged(state, worldIn, pos, blockIn, fromPos);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getLightValue(state, world, pos) : super.getLightValue(state, world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isFoliage(IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isFoliage(world, pos) : super.isFoliage(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean canConnectRedstone(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.canConnectRedstone(state, world, pos, side) : super.canConnectRedstone(state, world, pos, side);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void fillWithRain(World world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.fillWithRain(world, pos);\n\t\t} else {\n\t\t\tsuper.fillWithRain(world, pos);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isBeaconBase(IBlockAccess world, BlockPos pos, BlockPos beacon) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isBeaconBase(world, pos, beacon) : super.isBeaconBase(world, pos, beacon);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isFlammable(@Nonnull IBlockAccess world, @Nonnull BlockPos pos, @Nonnull EnumFacing face) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isFlammable(world, pos, face) : super.isFlammable(world, pos, face);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic int getWeakPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.getWeakPower(state, world, pos, side) : super.getWeakPower(state, world, pos, side);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean canSustainPlant(@Nonnull IBlockState state, @Nonnull IBlockAccess world, BlockPos pos, @Nonnull EnumFacing direction, IPlantable plantable) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.canSustainPlant(state, world, pos, direction, plantable) : super.canSustainPlant(state, world, pos, direction, plantable);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isWood(IBlockAccess world, BlockPos pos) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isWood(world, pos) : super.isWood(world, pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean canCreatureSpawn(@Nonnull IBlockState state, @Nonnull IBlockAccess world, @Nonnull BlockPos pos, EntityLiving.SpawnPlacementType type) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.canCreatureSpawn(state, world, pos, type) : super.canCreatureSpawn(state, world, pos, type);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean isFireSource(@Nonnull World world, BlockPos pos, EnumFacing side) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\treturn block != null ? block.isFireSource(world, pos, side) : super.isFireSource(world, pos, side);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) {\n\t\tBlock block = mcmpBlockAccess.getBlock();\n\t\tif (block != null) {\n\t\t\tblock.onNeighborChange(world, pos, neighbor);\n\t\t} else {\n\t\t\tsuper.onNeighborChange(world, pos, neighbor);\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean removedByPlayer(@Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull EntityPlayer player, boolean willHarvest) {\n\t\tPair<Vec3d, Vec3d> vectors = RayTraceHelper.getRayTraceVectors(player);\n\t\tRayTraceResult hit = collisionRayTrace(state, world, pos, vectors.getLeft(), vectors.getRight());\n\t\tOptional<TileMultipartContainer> tile = getTile(world, pos);\n\t\tif (hit != null && tile.isPresent() && hit.subHit >= 0) {\n\t\t\tif (!world.isRemote) {\n\t\t\t\tIPartSlot slot = MCMultiPart.slotRegistry.getValue(hit.subHit);\n\t\t\t\tboolean canRemove = tile.get().get(slot).map(i -> {\n\t\t\t\t\tif (i.getPart().canPlayerDestroy(i, player)) {\n\t\t\t\t\t\ti.getPart().onPartHarvested(i, player);\n\t\t\t\t\t\tif (player == null || !player.capabilities.isCreativeMode) {\n\t\t\t\t\t\t\ti.getPart().getDrops(i.getPartWorld(), pos, i, 0).forEach(s -> spawnAsEntity(world, pos, s));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}).orElse(true);\n\t\t\t\tif (canRemove)\n\t\t\t\t\ttile.get().removePart(slot);\n\t\t\t}\n\t\t}\n\t\tif (hit != null && hit.subHit == -1) {\n\t\t\treturn super.removedByPlayer(state, world, pos, player, willHarvest);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic float getPlayerRelativeBlockHardness(IBlockState state, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull BlockPos pos) {\n\t\tPair<Vec3d, Vec3d> vectors = RayTraceHelper.getRayTraceVectors(player);\n\t\tRayTraceResult hit = collisionRayTrace(getDefaultState(), world, pos, vectors.getLeft(), vectors.getRight());\n\t\tif (hit != null && hit.subHit >= 0) {\n\t\t\treturn getTile(world, pos).map(t -> t.get(MCMultiPart.slotRegistry.getValue(hit.subHit)).get())\n\t\t\t\t\t.map(i -> i.getPart().getPlayerRelativePartHardness(i, (RayTraceResult) hit.hitInfo, player)).orElse(0F);\n\t\t}\n\t\tif (hit != null) {\n\t\t\treturn super.getPlayerRelativeBlockHardness(state, player, world, pos);\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean addDestroyEffects(World world, BlockPos pos, ParticleManager manager) {\n\t\tPair<Vec3d, Vec3d> vectors = RayTraceHelper.getRayTraceVectors(MCMultiPart.proxy.getPlayer());\n\t\tRayTraceResult hit = collisionRayTrace(getDefaultState(), world, pos, vectors.getLeft(), vectors.getRight());\n\t\tif (hit != null && hit.subHit >= 0) {\n\t\t\tIPartInfo part = getTile(world, pos).get().get(MCMultiPart.slotRegistry.getValue(hit.subHit)).get();\n\t\t\tif (!part.getPart().addDestroyEffects(part, manager)) {\n\t\t\t\tIBlockState state = part.getPart().getActualState(part.getPartWorld(), pos, part);\n\t\t\t\tfor (int i = 0; i < 4; ++i) {\n\t\t\t\t\tfor (int j = 0; j < 4; ++j) {\n\t\t\t\t\t\tfor (int k = 0; k < 4; ++k) {\n\t\t\t\t\t\t\tdouble xOff = (i + 0.5D) / 4.0D;\n\t\t\t\t\t\t\tdouble yOff = (j + 0.5D) / 4.0D;\n\t\t\t\t\t\t\tdouble zOff = (k + 0.5D) / 4.0D;\n\t\t\t\t\t\t\tmanager.addEffect(new ParticleDigging(world, pos.getX() + xOff, pos.getY() + yOff, pos.getZ() + zOff, xOff - 0.5D,\n\t\t\t\t\t\t\t\t\tyOff - 0.5D, zOff - 0.5D, state) {\n\t\t\t\t\t\t\t}.setBlockPos(pos));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean addHitEffects(IBlockState mpState, World world, RayTraceResult hit, ParticleManager manager) {\n\t\tif (hit != null && hit.subHit >= 0) {\n\t\t\tBlockPos pos = hit.getBlockPos();\n\t\t\tIPartInfo part = getTile(world, pos).get().get(MCMultiPart.slotRegistry.getValue(hit.subHit)).get();\n\t\t\tif (!part.getPart().addHitEffects(part, (RayTraceResult) hit.hitInfo, manager)) {\n\t\t\t\tif (part.getPart().getRenderType(part) != EnumBlockRenderType.INVISIBLE) {\n\t\t\t\t\tint x = pos.getX(), y = pos.getY(), z = pos.getZ();\n\t\t\t\t\tAxisAlignedBB aabb = part.getPart().getBoundingBox(part);\n\t\t\t\t\tdouble pX = x + world.rand.nextDouble() * (aabb.maxX - aabb.minX - 0.2) + 0.1 + aabb.minX;\n\t\t\t\t\tdouble pY = y + world.rand.nextDouble() * (aabb.maxY - aabb.minY - 0.2) + 0.1 + aabb.minY;\n\t\t\t\t\tdouble pZ = z + world.rand.nextDouble() * (aabb.maxZ - aabb.minZ - 0.2) + 0.1 + aabb.minZ;\n\n\t\t\t\t\tswitch (hit.sideHit) {\n\t\t\t\t\t\tcase DOWN:\n\t\t\t\t\t\t\tpY = y + aabb.minY - 0.1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase UP:\n\t\t\t\t\t\t\tpY = y + aabb.maxY + 0.1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase NORTH:\n\t\t\t\t\t\t\tpZ = z + aabb.minZ - 0.1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase SOUTH:\n\t\t\t\t\t\t\tpZ = z + aabb.maxZ + 0.1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase WEST:\n\t\t\t\t\t\t\tpX = x + aabb.minX - 0.1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase EAST:\n\t\t\t\t\t\t\tpX = x + aabb.maxX + 0.1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tmanager.addEffect(new ParticleDigging(world, pX, pY, pZ, 0.0D, 0.0D, 0.0D, part.getPart().getActualState(part.getPartWorld(), pos, part)) {\n\t\t\t\t\t}.setBlockPos(pos).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic ItemStack getPickBlock(IBlockState state, RayTraceResult hit, World world, BlockPos pos, EntityPlayer player) {\n\t\tif (hit != null && hit.subHit >= 0) {\n\t\t\treturn getTile(world, pos).map(t -> t.get(MCMultiPart.slotRegistry.getValue(hit.subHit))).filter(Optional::isPresent)\n\t\t\t\t\t.map(o -> o.get().getPart().getPickPart(o.get(), (RayTraceResult) hit.hitInfo, player)).orElse(ItemStack.EMPTY);\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing facing, float hitX,\n\t\t\tfloat hitY, float hitZ) {\n\t\tPair<Vec3d, Vec3d> vectors = RayTraceHelper.getRayTraceVectors(player);\n\t\tRayTraceResult hit = collisionRayTrace(getDefaultState(), world, pos, vectors.getLeft(), vectors.getRight());\n\t\tif (hit != null && hit.subHit >= 0) {\n\t\t\treturn getTile(world, pos).map(t -> t.get(MCMultiPart.slotRegistry.getValue(hit.subHit)).get())\n\t\t\t\t\t.map(i -> i.getPart().onPartActivated(i, player, hand, (RayTraceResult) hit.hitInfo)).orElse(false);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onBlockClicked(World world, BlockPos pos, EntityPlayer player) {\n\t\tPair<Vec3d, Vec3d> vectors = RayTraceHelper.getRayTraceVectors(player);\n\t\tRayTraceResult hit = collisionRayTrace(getDefaultState(), world, pos, vectors.getLeft(), vectors.getRight());\n\t\tif (hit != null && hit.subHit >= 0) {\n\t\t\tgetTile(world, pos).map(t -> t.get(MCMultiPart.slotRegistry.getValue(hit.subHit)).get())\n\t\t\t\t\t.ifPresent(i -> i.getPart().onPartClicked(i, player, (RayTraceResult) hit.hitInfo));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/basic/ltgpmodcompat/LPMicroblockTileEntity.java",
    "content": "package logisticspipes.pipes.basic.ltgpmodcompat;\n\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Optional;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.network.NetworkManager;\nimport net.minecraft.network.play.server.SPacketUpdateTileEntity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.Mirror;\nimport net.minecraft.util.Rotation;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport mcmultipart.api.container.IMultipartContainer;\nimport mcmultipart.api.container.IPartInfo;\nimport mcmultipart.api.multipart.IMultipart;\nimport mcmultipart.api.multipart.IMultipartTile;\nimport mcmultipart.api.slot.IPartSlot;\nimport mcmultipart.block.TileMultipartContainer;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.utils.ReflectionHelper;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPLTGPCompanion;\n\n@ModDependentInterface(modId = { LPConstants.mcmpModID }, interfacePath = { \"mcmultipart.api.container.IMultipartContainer\" })\npublic abstract class LPMicroblockTileEntity extends TileEntity implements IMultipartContainer {\n\n\tpublic IMCMPLTGPCompanion imcmpltgpCompanion;\n\n\tpublic abstract boolean isMultipartAllowedInPipe();\n\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic TileMultipartContainer getMultipartContainer() {\n\t\treturn (TileMultipartContainer) imcmpltgpCompanion.getMCMPTileEntity();\n\t}\n\n\t@Nonnull\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic NBTTagCompound getUpdateTag() {\n\t\tNBTTagCompound tag = super.getUpdateTag();\n\t\tif (this.getMultipartContainer() != null) tag.setTag(\"LogisticsPipes:MCMultiPartData\", this.getMultipartContainer().getUpdateTag());\n\t\treturn tag;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void handleUpdateTag(@Nonnull NBTTagCompound tag) {\n\t\tsuper.handleUpdateTag(tag);\n\t\tif (tag.hasKey(\"LogisticsPipes:MCMultiPartData\")) {\n\t\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().handleUpdateTag(tag.getCompoundTag(\"LogisticsPipes:MCMultiPartData\"));\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic SPacketUpdateTileEntity getUpdatePacket() {\n\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\tif (this.getMultipartContainer() != null) {\n\t\t\tSPacketUpdateTileEntity packet = this.getMultipartContainer().getUpdatePacket();\n\t\t\tnbt = ReflectionHelper.getPrivateField(SPacketUpdateTileEntity.class, packet, \"nbt\", \"field_148860_e\");\n\t\t}\n\t\tSPacketUpdateTileEntity superPacket = super.getUpdatePacket();\n\t\tif (superPacket != null) {\n\t\t\tnbt.setTag(\"LogisticsPipes:SuperUpdatePacket\", superPacket.getNbtCompound());\n\t\t}\n\t\treturn new SPacketUpdateTileEntity(this.getPartPos(), 0, nbt);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().onDataPacket(net, pkt);\n\t\tif (pkt.getNbtCompound().hasKey(\"LogisticsPipes:SuperUpdatePacket\")) {\n\t\t\tsuper.onDataPacket(net, new SPacketUpdateTileEntity(getPos(), 1, pkt.getNbtCompound().getCompoundTag(\"LogisticsPipes:SuperUpdatePacket\")));\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound tag) {\n\t\ttag = super.writeToNBT(tag);\n\t\tNBTTagCompound multiPartTag = new NBTTagCompound();\n\t\tif (this.getMultipartContainer() != null) multiPartTag = this.getMultipartContainer().writeToNBT(multiPartTag);\n\t\ttag.setTag(\"MCMultiPartData\", multiPartTag);\n\t\treturn tag;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void readFromNBT(NBTTagCompound tag) {\n\t\tsuper.readFromNBT(tag);\n\t\tif (tag.hasKey(\"MCMultiPartData\")) {\n\t\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().readFromNBT(tag.getCompoundTag(\"MCMultiPartData\"));\n\t\t}\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void mirror(Mirror mirror) {\n\t\tsuper.mirror(mirror);\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().mirror(mirror);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onLoad() {\n\t\tsuper.onLoad();\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().onLoad();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void onChunkUnload() {\n\t\tsuper.onChunkUnload();\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().onChunkUnload();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void rotate(Rotation rotation) {\n\t\tsuper.rotate(rotation);\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().rotate(rotation);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void setWorld(@Nonnull World world) {\n\t\tsuper.setWorld(world);\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().setWorld(world);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tprotected void setWorldCreate(World worldIn) {\n\t\tsuper.setWorldCreate(worldIn);\n\t\tif (this.getMultipartContainer() != null) ReflectionHelper.invokePrivateMethod(TileMultipartContainer.class, this.getMultipartContainer(), \"setWorldCreate\", \"func_190201_b\", new Class[] { World.class }, new Object[] { worldIn });\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void invalidate() {\n\t\tsuper.invalidate();\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().invalidate();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean shouldRenderInPass(int pass) {\n\t\tif (this.getMultipartContainer() == null) return super.shouldRenderInPass(pass);\n\t\treturn this.getMultipartContainer().shouldRenderInPass(pass) || super.shouldRenderInPass(pass);\n\t}\n\n\t/*\n\tpublic boolean canRenderBreaking() {\n\t\tsuper.canRenderBreaking()\n\t\treturn this.getMultipartContainer().canRenderBreaking();\n\t}\n\t*/\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void updateContainingBlockInfo() {\n\t\tsuper.updateContainingBlockInfo();\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().updateContainingBlockInfo();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void setPos(BlockPos pos) {\n\t\tsuper.setPos(pos);\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().setPos(pos);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void validate() {\n\t\tsuper.validate();\n\t\tif (this.getMultipartContainer() != null) this.getMultipartContainer().validate();\n\t}\n\n\t// IMultipartContainer implementation below\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Optional<IPartInfo> get(IPartSlot iPartSlot) {\n\t\tif (this.getMultipartContainer() == null) return Optional.empty();\n\t\treturn getMultipartContainer().get(iPartSlot);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Optional<IBlockState> getState(IPartSlot slot) {\n\t\tif (this.getMultipartContainer() == null) return Optional.empty();\n\t\treturn getMultipartContainer().getState(slot);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Map<IPartSlot, ? extends IPartInfo> getParts() {\n\t\tif (this.getMultipartContainer() == null) return Collections.emptyMap();\n\t\treturn getMultipartContainer().getParts();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean canAddPart(IPartSlot iPartSlot, IBlockState iBlockState, IMultipartTile iMultipartTile) {\n\t\tif (this.getMultipartContainer() == null) return false;\n\t\tif (!isMultipartAllowedInPipe()) return false;\n\t\treturn getMultipartContainer().canAddPart(iPartSlot, iBlockState, iMultipartTile);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic BlockPos getPartPos() {\n\t\tif (this.getMultipartContainer() == null) return new BlockPos(0, 1, 0);\n\t\treturn getMultipartContainer().getPartPos();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic boolean canAddPart(IPartSlot slot, IBlockState state) {\n\t\tif (this.getMultipartContainer() == null) return false;\n\t\tif (!isMultipartAllowedInPipe()) return false;\n\t\treturn getMultipartContainer().canAddPart(slot, state);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Optional<IMultipart> getPart(IPartSlot slot) {\n\t\tif (this.getMultipartContainer() == null) return Optional.empty();\n\t\treturn getMultipartContainer().getPart(slot);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic World getPartWorld() {\n\t\tif (this.getMultipartContainer() == null) return this.getWorld();\n\t\treturn getMultipartContainer().getPartWorld();\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic Optional<IMultipartTile> getPartTile(IPartSlot slot) {\n\t\tif (this.getMultipartContainer() == null) return Optional.empty();\n\t\treturn getMultipartContainer().getPartTile(slot);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void addPart(IPartSlot iPartSlot, IBlockState iBlockState, IMultipartTile iMultipartTile) {\n\t\tif (this.getMultipartContainer() == null) return;\n\t\tif (!isMultipartAllowedInPipe()) return;\n\t\tgetMultipartContainer().addPart(iPartSlot, iBlockState, iMultipartTile);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void removePart(IPartSlot iPartSlot) {\n\t\tif (this.getMultipartContainer() == null) return;\n\t\tgetMultipartContainer().removePart(iPartSlot);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void notifyChange(IPartInfo part) {\n\t\tif (this.getMultipartContainer() == null) return;\n\t\tgetMultipartContainer().notifyChange(part);\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.mcmpModID)\n\tpublic void addPart(IPartSlot slot, IBlockState state) {\n\t\tif (this.getMultipartContainer() == null) return;\n\t\tif (!isMultipartAllowedInPipe()) return;\n\t\tgetMultipartContainer().addPart(slot, state);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/signs/CraftingPipeSign.java",
    "content": "package logisticspipes.pipes.signs;\n\nimport java.util.List;\n\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.shader.Framebuffer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.jetbrains.annotations.Nullable;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.cpipe.CPipeSatelliteImportBack;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class CraftingPipeSign implements IPipeSign {\n\n\tpublic CoreRoutedPipe pipe;\n\tpublic EnumFacing dir;\n\n\tprivate Object fbo;\n\tprivate ItemIdentifierStack oldRenderedStack = null;\n\tprivate String oldSatelliteName = \"\";\n\n\t@Override\n\tpublic boolean isAllowedFor(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics;\n\t}\n\n\t@Override\n\tpublic void addSignTo(CoreRoutedPipe pipe, EnumFacing dir, EntityPlayer player) {\n\t\tpipe.addPipeSign(dir, new CraftingPipeSign(), player);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound tag) {}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound tag) {}\n\n\t@Override\n\tpublic ModernPacket getPacket() {\n\t\tPipeItemsCraftingLogistics cpipe = (PipeItemsCraftingLogistics) pipe;\n\t\treturn PacketHandler.getPacket(CPipeSatelliteImportBack.class)\n\t\t\t\t.setInventory(cpipe.getDummyInventory())\n\t\t\t\t.setType(ModulePositionType.IN_PIPE)\n\t\t\t\t.setPosX(cpipe.getX())\n\t\t\t\t.setPosY(cpipe.getY())\n\t\t\t\t.setPosZ(cpipe.getZ());\n\t}\n\n\t@Override\n\tpublic void updateServerSide() {}\n\n\t@Override\n\tpublic void init(CoreRoutedPipe pipe, EnumFacing dir) {\n\t\tthis.pipe = pipe;\n\t\tthis.dir = dir;\n\t}\n\n\t@Override\n\tpublic void activate(EntityPlayer player) {}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void render(CoreRoutedPipe pipe, LogisticsRenderPipe renderer) {\n\t\tPipeItemsCraftingLogistics cpipe = (PipeItemsCraftingLogistics) pipe;\n\t\tFontRenderer var17 = renderer.getFontRenderer();\n\t\toldRenderedStack = null;\n\t\tif (cpipe != null) {\n\t\t\tList<ItemIdentifierStack> craftables = cpipe.getCraftedItems();\n\n\t\t\tString name = \"\";\n\t\t\tif (craftables != null && craftables.size() > 0) {\n\t\t\t\tItemIdentifierStack itemstack = craftables.get(0);\n\t\t\t\toldRenderedStack = itemstack;\n\n\t\t\t\trenderer.renderItemStackOnSign(itemstack.unsafeMakeNormalStack());\n\t\t\t\tItem item = itemstack.getItem().item;\n\n\t\t\t\tGlStateManager.depthMask(false);\n\t\t\t\tGL11.glRotatef(-180.0F, 1.0F, 0.0F, 0.0F);\n\t\t\t\tGL11.glTranslatef(0.5F, +0.08F, 0.0F);\n\t\t\t\tGL11.glScalef(1.0F / 90.0F, 1.0F / 90.0F, 1.0F / 90.0F);\n\n\t\t\t\ttry {\n\t\t\t\t\tname = item.getItemStackDisplayName(itemstack.unsafeMakeNormalStack());\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tname = item.getTranslationKey();\n\t\t\t\t\t} catch (Exception ignored) {}\n\t\t\t\t}\n\n\t\t\t\tvar17.drawString(String.format(\"ID: %d\", Item.getIdFromItem(item)), -var17.getStringWidth(String.format(\"ID: %d\", Item.getIdFromItem(item))) / 2, 0 * 10 - 4 * 5, 0);\n\t\t\t\tModuleCrafter logisticsMod = cpipe.getLogisticsModule();\n\t\t\t\toldSatelliteName = logisticsMod.clientSideSatelliteNames.satelliteName;\n\t\t\t\tif (!oldSatelliteName.isEmpty()) {\n\t\t\t\t\tvar17.drawString(\"Sat: \" + oldSatelliteName, -var17.getStringWidth(\"Sat: \" + oldSatelliteName) / 2, 1 * 10 - 4 * 5, 0);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tGL11.glRotatef(-180.0F, 1.0F, 0.0F, 0.0F);\n\t\t\t\tGL11.glTranslatef(0.5F, +0.08F, 0.0F);\n\t\t\t\tGL11.glScalef(1.0F / 90.0F, 1.0F / 90.0F, 1.0F / 90.0F);\n\t\t\t\tname = \"Empty\";\n\t\t\t}\n\n\t\t\tname = renderer.cut(name, var17);\n\n\t\t\tvar17.drawString(name, -var17.getStringWidth(name) / 2 - 15, 3 * 10 - 4 * 5, 0);\n\n\t\t\tGlStateManager.depthMask(true);\n\t\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t}\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic Framebuffer getMCFrameBufferForSign() {\n\t\tif(!OpenGlHelper.isFramebufferEnabled()) {\n\t\t\treturn null;\n\t\t}\n\t\tif(fbo == null) {\n\t\t\tfbo = new Framebuffer(128, 128, true);\n\t\t}\n\t\treturn (Framebuffer) fbo;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic boolean doesFrameBufferNeedUpdating(CoreRoutedPipe pipe, LogisticsRenderPipe renderer) {\n\t\tItemIdentifierStack itemstack = getItemIdentifierStack((PipeItemsCraftingLogistics) pipe);\n\t\tif (itemstack != null && oldRenderedStack != null) {\n\t\t\treturn fbo == null || !oldRenderedStack.equals(itemstack);\n\t\t} else if (itemstack == null && oldRenderedStack == null) {\n\t\t\treturn fbo == null;\n\t\t} else {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t@Nullable\n\tprivate ItemIdentifierStack getItemIdentifierStack(PipeItemsCraftingLogistics cpipe) {\n\t\tif(cpipe == null) return null;\n\t\tList<ItemIdentifierStack> craftables = cpipe.getCraftedItems();\n\t\tItemIdentifierStack itemstack = null;\n\t\tif (craftables != null && craftables.size() > 0) {\n\t\t\titemstack = craftables.get(0);\n\t\t}\n\t\treturn itemstack;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/signs/IPipeSign.java",
    "content": "package logisticspipes.pipes.signs;\n\nimport net.minecraft.client.shader.Framebuffer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.renderer.LogisticsRenderPipe;\n\npublic interface IPipeSign {\n\n\t// Methods used when assigning a sign\n\tboolean isAllowedFor(CoreRoutedPipe pipe);\n\n\tvoid addSignTo(CoreRoutedPipe pipe, EnumFacing dir, EntityPlayer player);\n\n\t// For Final Pipe\n\tvoid readFromNBT(NBTTagCompound tag);\n\n\tvoid writeToNBT(NBTTagCompound tag);\n\n\tvoid init(CoreRoutedPipe pipe, EnumFacing dir);\n\n\tvoid activate(EntityPlayer player);\n\n\tModernPacket getPacket();\n\n\tvoid updateServerSide();\n\n\t@SideOnly(Side.CLIENT)\n\tvoid render(CoreRoutedPipe pipe, LogisticsRenderPipe renderer);\n\n\t@SideOnly(Side.CLIENT)\n\tFramebuffer getMCFrameBufferForSign();\n\n\t@SideOnly(Side.CLIENT)\n\tboolean doesFrameBufferNeedUpdating(CoreRoutedPipe pipe, LogisticsRenderPipe renderer);\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/signs/ItemAmountPipeSign.java",
    "content": "package logisticspipes.pipes.signs;\n\nimport java.util.BitSet;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.shader.Framebuffer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.guis.item.ItemAmountSignGui;\nimport logisticspipes.network.packets.pipe.ItemAmountSignUpdatePacket;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class ItemAmountPipeSign implements IPipeSign, ISimpleInventoryEventHandler {\n\n\tpublic ItemIdentifierInventory itemTypeInv = new ItemIdentifierInventory(1, \"\", 1);\n\tpublic int amount = 100;\n\tpublic CoreRoutedPipe pipe;\n\tpublic EnumFacing dir;\n\tprivate boolean hasUpdated = false;\n\n\t@SideOnly(Side.CLIENT)\n\tprivate Framebuffer fbo;\n\n\tpublic ItemAmountPipeSign() {\n\t\titemTypeInv.addListener(this);\n\t}\n\n\t@Override\n\tpublic boolean isAllowedFor(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void addSignTo(CoreRoutedPipe pipe, EnumFacing dir, EntityPlayer player) {\n\t\tpipe.addPipeSign(dir, new ItemAmountPipeSign(), player);\n\t\topenGUI(pipe, dir, player);\n\t}\n\n\tprivate void openGUI(CoreRoutedPipe pipe, EnumFacing dir, EntityPlayer player) {\n\t\tNewGuiHandler.getGui(ItemAmountSignGui.class).setDir(dir).setTilePos(pipe.container).open(player);\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound tag) {\n\t\titemTypeInv.readFromNBT(tag);\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound tag) {\n\t\titemTypeInv.writeToNBT(tag);\n\t}\n\n\t@Override\n\tpublic ModernPacket getPacket() {\n\t\treturn PacketHandler.getPacket(ItemAmountSignUpdatePacket.class).setStack(itemTypeInv.getIDStackInSlot(0)).setInteger2(amount).setInteger(dir.ordinal()).setTilePos(pipe.container);\n\t}\n\n\t@Override\n\tpublic void updateServerSide() {\n\t\tif (!pipe.isNthTick(20)) {\n\t\t\treturn;\n\t\t}\n\t\tif (hasUpdated) {\n\t\t\thasUpdated = false;\n\t\t\treturn;\n\t\t}\n\t\tint newAmount = 0;\n\t\tif (itemTypeInv.getIDStackInSlot(0) != null) {\n\t\t\tMap<ItemIdentifier, Integer> availableItems = SimpleServiceLocator.logisticsManager.getAvailableItems(pipe.getRouter().getIRoutersByCost());\n\t\t\tif (availableItems != null) {\n\t\t\t\tBitSet set = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\t\t\tspread(availableItems, set);\n\t\t\t\tif (availableItems.containsKey(itemTypeInv.getIDStackInSlot(0).getItem())) {\n\t\t\t\t\tnewAmount = availableItems.get(itemTypeInv.getIDStackInSlot(0).getItem());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (newAmount != amount) {\n\t\t\tamount = newAmount;\n\t\t\tsendUpdatePacket();\n\t\t}\n\t}\n\n\tprivate void spread(Map<ItemIdentifier, Integer> availableItems, BitSet set) { // Improve performance by updating a wall of Amount pipe signs all at once\n\t\tIRouter router = pipe.getRouter();\n\t\tif (set.get(router.getSimpleID())) return;\n\t\tset.set(router.getSimpleID());\n\t\tfor (ExitRoute exit : router.getIRoutersByCost()) {\n\t\t\tif (exit.distanceToDestination > 2) break; // Only when the signs are in one wall. To not spread to far.\n\t\t\tif (!exit.filters.isEmpty()) continue;\n\t\t\tif (set.get(exit.destination.getSimpleID())) continue;\n\t\t\tif (exit.connectionDetails.contains(PipeRoutingConnectionType.canRequestFrom) && exit.connectionDetails.contains(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\t\tCoreRoutedPipe cachedPipe = exit.destination.getCachedPipe();\n\t\t\t\tif (cachedPipe != null) {\n\t\t\t\t\tList<Pair<EnumFacing, IPipeSign>> pipeSigns = cachedPipe.getPipeSigns();\n\t\t\t\t\tpipeSigns.stream()\n\t\t\t\t\t\t\t.filter(signPair -> signPair != null && signPair.getValue2() instanceof ItemAmountPipeSign)\n\t\t\t\t\t\t\t.forEach(signPair -> ((ItemAmountPipeSign) signPair.getValue2()).updateStats(availableItems, set));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void updateStats(Map<ItemIdentifier, Integer> availableItems, BitSet set) {\n\t\thasUpdated = true;\n\t\tint newAmount = 0;\n\t\tif (itemTypeInv.getIDStackInSlot(0) != null) {\n\t\t\tif (availableItems.containsKey(itemTypeInv.getIDStackInSlot(0).getItem())) {\n\t\t\t\tnewAmount = availableItems.get(itemTypeInv.getIDStackInSlot(0).getItem());\n\t\t\t}\n\t\t}\n\t\tif (newAmount != amount) {\n\t\t\tamount = newAmount;\n\t\t\tsendUpdatePacket();\n\t\t}\n\t\tspread(availableItems, set);\n\t}\n\n\t@Override\n\tpublic void activate(EntityPlayer player) {\n\t\topenGUI(pipe, dir, player);\n\t}\n\n\t@Override\n\tpublic void init(CoreRoutedPipe pipe, EnumFacing dir) {\n\t\tthis.pipe = pipe;\n\t\tthis.dir = dir;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void render(CoreRoutedPipe pipe, LogisticsRenderPipe renderer) {\n\t\t//TODO !!!\n\t\tFontRenderer var17 = renderer.getFontRenderer();\n\t\tif (pipe != null) {\n\t\t\tString name = \"\";\n\t\t\tif (itemTypeInv != null && itemTypeInv.getIDStackInSlot(0) != null) {\n\t\t\t\tItemStack itemstack = itemTypeInv.getIDStackInSlot(0).unsafeMakeNormalStack();\n\n//\t\t\t\tGL11.glDepthMask(true);\n\t\t\t\trenderer.renderItemStackOnSign(itemstack);\n\t\t\t\tItem item = itemstack.getItem();\n\n\t\t\t\tGL11.glDepthMask(false);\n\t\t\t\t//GL11.glRotatef(-180.0F, 1.0F, 0.0F, 0.0F);\n\t\t\t\t//GlStateManager.translate(0.5F, +0.08F, 0.0F);\n\t\t\t\tGL11.glScalef(1.0F / 90.0F, 1.0F / 90.0F, 1.0F / 90.0F);\n\n\t\t\t\ttry {\n\t\t\t\t\tname = item.getItemStackDisplayName(itemstack);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tname = item.getTranslationKey();\n\t\t\t\t\t} catch (Exception ignored) {}\n\t\t\t\t}\n\n\t\t\t\tvar17.drawString(String.format(\"ID: %d\", Item.getIdFromItem(item)), -var17.getStringWidth(String.format(\"ID: %d\", Item.getIdFromItem(item))) / 2, 0 * 10 - 4 * 5, 0);\n\t\t\t\tString displayAmount = TextUtil.getThreeDigitFormattedNumber(amount, false);\n\t\t\t\tvar17.drawString(\"Amount:\", -var17.getStringWidth(\"Amount:\") / 2, 1 * 10 - 4 * 5, 0);\n\t\t\t\tvar17.drawString(displayAmount, -var17.getStringWidth(displayAmount) / 2, 2 * 10 - 4 * 5, 0);\n\t\t\t} else {\n\t\t\t\tGL11.glRotatef(-180.0F, 1.0F, 0.0F, 0.0F);\n\t\t\t\tGL11.glTranslatef(0.5F, +0.08F, 0.0F);\n\t\t\t\tGL11.glScalef(1.0F / 90.0F, 1.0F / 90.0F, 1.0F / 90.0F);\n\t\t\t\tname = \"Empty\";\n\t\t\t}\n\n\t\t\tname = renderer.cut(name, var17);\n\n\t\t\tvar17.drawString(name, -var17.getStringWidth(name) / 2 - 15, 3 * 10 - 4 * 5, 0);\n\n\t\t\tGL11.glDepthMask(true);\n\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t}\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic Framebuffer getMCFrameBufferForSign() {\n\t\tif(!OpenGlHelper.isFramebufferEnabled()) {\n\t\t\treturn null;\n\t\t}\n\t\tif(fbo == null) {\n\t\t\tfbo = new Framebuffer(256, 256, true);\n\t\t}\n\t\treturn fbo;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic boolean doesFrameBufferNeedUpdating(CoreRoutedPipe pipe, LogisticsRenderPipe renderer) {\n\t\treturn fbo == null;\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tif (inventory == itemTypeInv) {\n\t\t\tsendUpdatePacket();\n\t\t}\n\t}\n\n\tprivate void sendUpdatePacket() {\n\t\tif (MainProxy.isServer(pipe.getWorld())) {\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(pipe.container, getPacket());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/tubes/HSTubeCurve.java",
    "content": "package logisticspipes.pipes.tubes;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.interfaces.ITubeRenderOrientation;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.tube.CurveTubeRenderer;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeMultiBlockTransportLogistics;\nimport logisticspipes.utils.IPositionRotateble;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class HSTubeCurve extends CoreMultiBlockPipe {\n\n\t@Getter\n\tprivate CurveOrientation orientation;\n\n\tpublic HSTubeCurve(Item item) {\n\t\tsuper(new PipeMultiBlockTransportLogistics(), item);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tif (orientation == null) {\n\t\t\toutput.writeBoolean(false);\n\t\t} else {\n\t\t\toutput.writeBoolean(true);\n\t\t\toutput.writeEnum(orientation);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tif (input.readBoolean()) {\n\t\t\torientation = input.readEnum(CurveOrientation.class);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getIconIndex(EnumFacing direction) {\n\t\t// TODO Auto-generated method stub\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\t// TODO Auto-generated method stub\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> list = new LPPositionSet<>(DoubleCoordinatesType.class);\n\t\tlist.add(new DoubleCoordinatesType<>(-1, 0, 0, SubBlockTypeForShare.CURVE_INNER_A));\n\t\tlist.add(new DoubleCoordinatesType<>(0, 0, 1, SubBlockTypeForShare.CURVE_OUT_A));\n\t\tlist.add(new DoubleCoordinatesType<>(-1, 0, 1, SubBlockTypeForShare.NON_SHARE));\n\t\tlist.add(new DoubleCoordinatesType<>(-2, 0, 1, SubBlockTypeForShare.CURVE_INNER_B));\n\t\tlist.add(new DoubleCoordinatesType<>(-1, 0, 2, SubBlockTypeForShare.CURVE_OUT_B));\n\t\tlist.add(new DoubleCoordinatesType<>(-2, 0, 2, SubBlockTypeForShare.NON_SHARE));\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getRotatedSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> set = getSubBlocks();\n\t\torientation.rotatePositions(set);\n\t\treturn set;\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxesToList(List<AxisAlignedBB> arraylist, AxisAlignedBB axisalignedbb) {\n\t\tdouble x = getX();\n\t\tdouble y = getY();\n\t\tdouble z = getZ();\n\t\tdouble angle = 0;\n\t\tdouble addOne = 0;\n\t\tdouble addTwo = 0;\n\t\tif (orientation.getRenderOrientation() == TurnDirection.NORTH_EAST) {\n\t\t\tangle = 3 * Math.PI / 2;\n\t\t\taddOne = LPConstants.PIPE_MAX_POS;\n\t\t\taddTwo = LPConstants.PIPE_MIN_POS;\n\t\t\tz -= 2;\n\t\t\tx += 1;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.EAST_SOUTH) {\n\t\t\tangle = 2 * Math.PI / 2;\n\t\t\taddOne = LPConstants.PIPE_MIN_POS;\n\t\t\taddTwo = LPConstants.PIPE_MAX_POS;\n\t\t\tx += 3;\n\t\t\tz += 1;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.SOUTH_WEST) {\n\t\t\tangle = Math.PI / 2;\n\t\t\taddOne = LPConstants.PIPE_MAX_POS;\n\t\t\taddTwo = LPConstants.PIPE_MIN_POS;\n\t\t\tz += 3;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.WEST_NORTH) {\n\t\t\tangle = 0;\n\t\t\taddOne = LPConstants.PIPE_MIN_POS;\n\t\t\taddTwo = LPConstants.PIPE_MAX_POS;\n\t\t\tx -= 2;\n\t\t}\n\t\tfor (int i = 0; i < 49; i++) {\n\t\t\tdouble xOne = x;\n\t\t\tdouble yMin = y + LPConstants.PIPE_MIN_POS;\n\t\t\tdouble zOne = z;\n\t\t\tdouble xTwo = x;\n\t\t\tdouble yMax = y + LPConstants.PIPE_MAX_POS;\n\t\t\tdouble zTwo = z;\n\t\t\txOne += (2 + addOne) * Math.sin(angle + (2 * Math.PI / 200 * (i)));\n\t\t\tzOne += (2 + addOne) * Math.cos(angle + (2 * Math.PI / 200 * (i + 2)));\n\t\t\txTwo += (2 + addTwo) * Math.sin(angle + (2 * Math.PI / 200 * (i + 1)));\n\t\t\tzTwo += (2 + addTwo) * Math.cos(angle + (2 * Math.PI / 200 * (i)));\n\t\t\tAxisAlignedBB box = new AxisAlignedBB(Math.min(xOne, xTwo), yMin, Math.min(zOne, zTwo), Math.max(xOne, xTwo), yMax, Math.max(zOne, zTwo));\n\t\t\tif (axisalignedbb == null || axisalignedbb.intersects(box)) {\n\t\t\t\tarraylist.add(box);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic AxisAlignedBB getCompleteBox() {\n\t\treturn CurveTubeRenderer.tubeCurve.get(orientation.getRenderOrientation()).bounds().toAABB();\n\t}\n\n\t@Override\n\tpublic ITubeOrientation getTubeOrientation(EntityPlayer player, int xPos, int zPos) {\n\t\tdouble x = xPos + 0.5 - player.posX;\n\t\tdouble z = zPos + 0.5 - player.posZ;\n\t\tdouble w = Math.atan2(x, z);\n\t\tdouble halfPI = Math.PI / 2;\n\t\tdouble halfhalfPI = halfPI / 2;\n\t\tw -= halfhalfPI;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir = null;\n\t\tEnumFacing dir1 = null;\n\t\tEnumFacing dir2 = null;\n\t\tdouble addition = 0;\n\t\tif (0 < w && w <= halfPI) {\n\t\t\tdir = EnumFacing.WEST;\n\t\t\tdir1 = EnumFacing.NORTH;\n\t\t\tdir2 = EnumFacing.SOUTH;\n\t\t\taddition = halfPI;\n\t\t} else if (halfPI < w && w <= 2 * halfPI) {\n\t\t\tdir = EnumFacing.SOUTH;\n\t\t\tdir1 = EnumFacing.EAST;\n\t\t\tdir2 = EnumFacing.WEST;\n\t\t} else if (2 * halfPI < w && w <= 3 * halfPI) {\n\t\t\tdir = EnumFacing.EAST;\n\t\t\tdir1 = EnumFacing.NORTH;\n\t\t\tdir2 = EnumFacing.SOUTH;\n\t\t\taddition = halfPI;\n\t\t} else if (3 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir = EnumFacing.NORTH;\n\t\t\tdir1 = EnumFacing.EAST;\n\t\t\tdir2 = EnumFacing.WEST;\n\t\t}\n\t\tw = Math.atan2(player.getLookVec().x, player.getLookVec().z);\n\t\tw -= addition;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir3 = null;\n\t\tif (0 < w && w <= 2 * halfPI) {\n\t\t\tdir3 = dir1;\n\t\t} else if (2 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir3 = dir2;\n\t\t}\n\t\tfor (CurveOrientation curve : CurveOrientation.values()) {\n\t\t\tif (curve.from.equals(dir)) {\n\t\t\t\tif (curve.looking.equals(dir3)) {\n\t\t\t\t\treturn curve;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound data) {\n\t\tsuper.writeToNBT(data);\n\t\tdata.setString(\"orientation\", orientation.name());\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound data) {\n\t\tsuper.readFromNBT(data);\n\t\torientation = CurveOrientation.valueOf(data.getString(\"orientation\"));\n\t}\n\n\t@Override\n\tpublic float getPipeLength() {\n\t\treturn (float) (Math.PI / 2 * 2.5);\n\t}\n\n\t@Override\n\tpublic EnumFacing getExitForInput(EnumFacing commingFrom) {\n\t\tTurnDirection ori = orientation.getRenderOrientation();\n\t\tif (ori.dir1 == commingFrom) {\n\t\t\treturn ori.dir2;\n\t\t}\n\t\tif (ori.dir2 == commingFrom) {\n\t\t\treturn ori.dir1;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic TileEntity getConnectedEndTile(EnumFacing output) {\n\t\tTurnDirection ori = orientation.getRenderOrientation();\n\t\tif (ori.dir2 == output) {\n\t\t\treturn container.getTile(output);\n\t\t}\n\t\tif (ori.dir1 == output) {\n\t\t\tDoubleCoordinates pos = new DoubleCoordinates(-2, 0, 2);\n\t\t\tLPPositionSet<DoubleCoordinates> set = new LPPositionSet<>(DoubleCoordinates.class);\n\t\t\tset.add(pos);\n\t\t\torientation.rotatePositions(set);\n\t\t\tTileEntity subTile = pos.add(getLPPosition()).getTileEntity(getWorld());\n\t\t\tif (subTile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\treturn ((LogisticsTileGenericSubMultiBlock) subTile).getTile(output);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean actAsNormalPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic ISpecialPipeRenderer getSpecialRenderer() {\n\t\treturn CurveTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn CurveTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getItemRenderPos(float fPos, LPTravelingItem travelItem) {\n\t\tif (orientation.getRenderOrientation().getDir1().getOpposite() != travelItem.input) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\t\tdouble angle = 0;\n\t\tint x = 0;\n\t\tint y = 0;\n\t\tint z = 0;\n\t\tif (orientation.getRenderOrientation() == TurnDirection.NORTH_EAST) {\n\t\t\tangle = 3 * Math.PI / 2;\n\t\t\tz -= 2;\n\t\t\tx += 1;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.EAST_SOUTH) {\n\t\t\tangle = 2 * Math.PI / 2;\n\t\t\tx += 3;\n\t\t\tz += 1;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.SOUTH_WEST) {\n\t\t\tangle = Math.PI / 2;\n\t\t\tz += 3;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.WEST_NORTH) {\n\t\t\tangle = 0;\n\t\t\tx -= 2;\n\t\t}\n\t\tdouble xOne = x;\n\t\tdouble yMin = y + 0.5;\n\t\tdouble zOne = z;\n\t\txOne += (2.5) * Math.sin(angle + (2 * Math.PI / 4 / transport.getPipeLength() * fPos));\n\t\tzOne += (2.5) * Math.cos(angle + (2 * Math.PI / 4 / transport.getPipeLength() * fPos));\n\t\treturn new DoubleCoordinates(xOne, yMin, zOne);\n\t}\n\n\t@Override\n\tpublic double getItemRenderPitch(float fPos, LPTravelingItem travelItem) {\n\t\t// TODO Auto-generated method stub\n\t\treturn super.getItemRenderPitch(fPos, travelItem);\n\t}\n\n\t@Override\n\tpublic double getItemRenderYaw(float fPos, LPTravelingItem travelItem) {\n\t\tif (orientation.getRenderOrientation().getDir1().getOpposite() != travelItem.input) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\t\tdouble angle = 0;\n\t\tif (orientation.getRenderOrientation() == TurnDirection.NORTH_EAST) {\n\t\t\tangle = 3 * Math.PI / 2;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.EAST_SOUTH) {\n\t\t\tangle = 2 * Math.PI / 2;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.SOUTH_WEST) {\n\t\t\tangle = Math.PI / 2;\n\t\t} else if (orientation.getRenderOrientation() == TurnDirection.WEST_NORTH) {\n\t\t\tangle = 0;\n\t\t}\n\t\treturn 360 * (angle + 2 * Math.PI / 4 / transport.getPipeLength() * fPos) / (2 * Math.PI);\n\t}\n\n\t@Override\n\tpublic double getBoxRenderScale(float fPos, LPTravelingItem travelItem) {\n\t\tif (orientation.getRenderOrientation().getDir1().getOpposite() != travelItem.input) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\t\tif (fPos > this.transport.getPipeLength() - 0.5) {\n\t\t\treturn 1 - (this.transport.getPipeLength() - fPos) * 0.1D;\n\t\t} else if (fPos > 0.5) {\n\t\t\treturn 0.95D;\n\t\t} else {\n\t\t\treturn 1 - fPos * 0.1D;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isHSTube() {\n\t\treturn true;\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum CurveOrientation implements ITubeOrientation {\n\t\t//@formatter:off\n\t\t// Name: Placement from  _ TurnDirection\n\t\tNORTH_NORTH_EAST(TurnDirection.NORTH_EAST, new DoubleCoordinates(2, 0, 2), EnumFacing.NORTH, EnumFacing.EAST),\n\t\tNORTH_WEST_NORTH(TurnDirection.WEST_NORTH, new DoubleCoordinates(0, 0, 0), EnumFacing.NORTH, EnumFacing.WEST),\n\t\tWEST_WEST_NORTH(TurnDirection.WEST_NORTH, new DoubleCoordinates(2, 0, -2), EnumFacing.WEST, EnumFacing.NORTH),\n\t\tWEST_SOUTH_WEST(TurnDirection.SOUTH_WEST, new DoubleCoordinates(0, 0, 0), EnumFacing.WEST, EnumFacing.SOUTH),\n\t\tSOUTH_SOUTH_WEST(TurnDirection.SOUTH_WEST, new DoubleCoordinates(-2, 0, -2), EnumFacing.SOUTH, EnumFacing.WEST),\n\t\tSOUTH_EAST_SOUTH(TurnDirection.EAST_SOUTH, new DoubleCoordinates(0, 0, 0), EnumFacing.SOUTH, EnumFacing.EAST),\n\t\tEAST_EAST_SOUTH(TurnDirection.EAST_SOUTH, new DoubleCoordinates(-2, 0, 2), EnumFacing.EAST, EnumFacing.SOUTH),\n\t\tEAST_NORTH_EAST(TurnDirection.NORTH_EAST, new DoubleCoordinates(0, 0, 0), EnumFacing.EAST, EnumFacing.NORTH);\n\t\t//@formatter:on\n\t\t@Getter\n\t\tTurnDirection renderOrientation;\n\t\t@Getter\n\t\tDoubleCoordinates offset;\n\t\t@Getter\n\t\tEnumFacing from;\n\t\t@Getter\n\t\tEnumFacing looking;\n\n\t\t@Override\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\trenderOrientation.rotatePositions(set);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setOnPipe(CoreMultiBlockPipe pipe) {\n\t\t\t((HSTubeCurve) pipe).orientation = this;\n\t\t}\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum TurnDirection implements ITubeRenderOrientation {\n\t\t//@formatter:off\n\t\tNORTH_EAST(EnumFacing.NORTH, EnumFacing.EAST),\n\t\tEAST_SOUTH(EnumFacing.EAST, EnumFacing.SOUTH),\n\t\tSOUTH_WEST(EnumFacing.SOUTH, EnumFacing.WEST),\n\t\tWEST_NORTH(EnumFacing.WEST, EnumFacing.NORTH);\n\t\t//@formatter:on\n\t\t@Getter\n\t\tEnumFacing dir1;\n\t\tEnumFacing dir2;\n\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\tif (this == WEST_NORTH) {\n\t\t\t\treturn;\n\t\t\t} else if (this == NORTH_EAST) {\n\t\t\t\tset.rotateRight();\n\t\t\t} else if (this == EAST_SOUTH) {\n\t\t\t\tset.rotateLeft();\n\t\t\t\tset.rotateLeft();\n\t\t\t} else if (this == SOUTH_WEST) {\n\t\t\t\tset.rotateLeft();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/tubes/HSTubeGain.java",
    "content": "package logisticspipes.pipes.tubes;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.interfaces.ITubeRenderOrientation;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.tube.GainTubeRenderer;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeMultiBlockTransportLogistics;\nimport logisticspipes.utils.IPositionRotateble;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class HSTubeGain extends CoreMultiBlockPipe {\n\n\t@Getter\n\tprivate TubeGainOrientation orientation;\n\tprivate List<AxisAlignedBB> boxes = null;\n\n\tpublic HSTubeGain(Item item) {\n\t\tsuper(new PipeMultiBlockTransportLogistics(), item);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tif (orientation == null) {\n\t\t\toutput.writeBoolean(false);\n\t\t} else {\n\t\t\toutput.writeBoolean(true);\n\t\t\toutput.writeEnum(orientation);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tif (input.readBoolean()) {\n\t\t\torientation = input.readEnum(TubeGainOrientation.class);\n\t\t}\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> list = new LPPositionSet<>(DoubleCoordinatesType.class);\n\t\tlist.add(new DoubleCoordinatesType<>(0, 0, -1, SubBlockTypeForShare.GAIN_B));\n\t\tlist.add(new DoubleCoordinatesType<>(0, 0, -2, SubBlockTypeForShare.GAIN_A));\n\t\tlist.add(new DoubleCoordinatesType<>(0, 1, -1, SubBlockTypeForShare.GAIN_A));\n\t\tlist.add(new DoubleCoordinatesType<>(0, 1, -2, SubBlockTypeForShare.GAIN_B));\n\t\tlist.add(new DoubleCoordinatesType<>(0, 1, -3, SubBlockTypeForShare.NON_SHARE));\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getRotatedSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> set = getSubBlocks();\n\t\torientation.rotatePositions(set);\n\t\treturn set;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound data) {\n\t\tsuper.writeToNBT(data);\n\t\tdata.setString(\"orientation\", orientation.name());\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound data) {\n\t\tsuper.readFromNBT(data);\n\t\torientation = TubeGainOrientation.valueOf(data.getString(\"orientation\"));\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxesToList(List<AxisAlignedBB> arraylist, AxisAlignedBB axisalignedbb) {\n\t\tif (boxes == null || boxes.isEmpty()) {\n\t\t\tboxes = new ArrayList<>();\n\t\t\tdouble x = getX();\n\t\t\tdouble y = getY();\n\t\t\tdouble z = getZ();\n\t\t\tfor (int i = -1; i < 54; i++) {\n\t\t\t\tdouble xOne = x;\n\t\t\t\tdouble yOne = y;\n\t\t\t\tdouble zOne = z;\n\t\t\t\tdouble xTwo = x;\n\t\t\t\tdouble yTwo = y + 2;\n\t\t\t\tdouble zTwo = z;\n\t\t\t\tif (orientation.getRenderOrientation() == TubeGainRenderOrientation.SOUTH) {\n\t\t\t\t\tzOne += 4.0F * (i - 4) / 50;\n\t\t\t\t\tzTwo += 4.0F * (i + 4) / 50;\n\t\t\t\t\txOne += 1;\n\t\t\t\t\txTwo -= 2;\n\t\t\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.WEST) {\n\t\t\t\t\txOne -= 3;\n\t\t\t\t\txTwo -= 3;\n\t\t\t\t\txOne += 4.0F * (i - 4) / 50;\n\t\t\t\t\txTwo += 4.0F * (i + 4) / 50;\n\t\t\t\t\tzOne -= 1;\n\t\t\t\t\tzTwo += 2;\n\t\t\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.NORTH) {\n\t\t\t\t\tzOne += 1;\n\t\t\t\t\tzTwo += 1;\n\t\t\t\t\tzOne -= 4.0F * (i - 4) / 50;\n\t\t\t\t\tzTwo -= 4.0F * (i + 4) / 50;\n\t\t\t\t\txOne -= 1;\n\t\t\t\t\txTwo += 2;\n\t\t\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.EAST) {\n\t\t\t\t\txOne += 4;\n\t\t\t\t\txTwo += 4;\n\t\t\t\t\txOne -= 4.0F * (i - 4) / 50;\n\t\t\t\t\txTwo -= 4.0F * (i + 4) / 50;\n\t\t\t\t\tzOne -= 1;\n\t\t\t\t\tzTwo += 2;\n\t\t\t\t}\n\t\t\t\tAxisAlignedBB box = GainTubeRenderer.getObjectBoundsAt(new AxisAlignedBB(Math.min(xOne, xTwo), Math.min(yOne, yTwo), Math.min(zOne, zTwo), Math.max(xOne, xTwo), Math.max(yOne, yTwo),\n\t\t\t\t\t\tMath.max(zOne, zTwo)).offset(-x, -y, -z), orientation);\n\t\t\t\tif (box != null) {\n\t\t\t\t\tLPPositionSet<DoubleCoordinates> lpBox = new LPPositionSet<>(DoubleCoordinates.class);\n\t\t\t\t\tlpBox.addFrom(box);\n\t\t\t\t\tDoubleCoordinates center = lpBox.getCenter();\n\t\t\t\t\tbox = new AxisAlignedBB(center.getXCoord() - 0.3D, center.getYCoord() - 0.3D, center.getZCoord() - 0.3D, center.getXCoord() + 0.3D,\n\t\t\t\t\t\t\tcenter.getYCoord() + 0.3D, center.getZCoord() + 0.3D);\n\t\t\t\t\tAxisAlignedBB cBox = getCompleteBox();\n\t\t\t\t\tdouble minX = Math.max(box.minX, cBox.minX);\n\t\t\t\t\tdouble minY = Math.max(box.minY, cBox.minY);\n\t\t\t\t\tdouble minZ = Math.max(box.minZ, cBox.minZ);\n\t\t\t\t\tdouble maxX = Math.min(box.maxX, cBox.maxX);\n\t\t\t\t\tdouble maxY = Math.min(box.maxY, cBox.maxY);\n\t\t\t\t\tdouble maxZ = Math.min(box.maxZ, cBox.maxZ);\n\t\t\t\t\tboxes.add(new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).offset(x, y, z));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tarraylist.addAll(boxes.stream()\n\t\t\t\t.filter(box -> box != null && (axisalignedbb == null || axisalignedbb.intersects(box)))\n\t\t\t\t.collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic AxisAlignedBB getCompleteBox() {\n\t\treturn GainTubeRenderer.tubeGain.get(orientation.getRenderOrientation()).bounds().toAABB();\n\t}\n\n\t@Override\n\tpublic ITubeOrientation getTubeOrientation(EntityPlayer player, int xPos, int zPos) {\n\t\tdouble x = xPos + 0.5 - player.posX;\n\t\tdouble z = zPos + 0.5 - player.posZ;\n\t\tdouble w = Math.atan2(x, z);\n\t\tdouble halfPI = Math.PI / 2;\n\t\tdouble halfhalfPI = halfPI / 2;\n\t\tw -= halfhalfPI;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir = null;\n\t\tif (0 < w && w <= halfPI) {\n\t\t\tdir = EnumFacing.EAST;\n\t\t} else if (halfPI < w && w <= 2 * halfPI) {\n\t\t\tdir = EnumFacing.NORTH;\n\t\t} else if (2 * halfPI < w && w <= 3 * halfPI) {\n\t\t\tdir = EnumFacing.WEST;\n\t\t} else if (3 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir = EnumFacing.SOUTH;\n\t\t}\n\t\tfor (TubeGainOrientation ori : TubeGainOrientation.values()) {\n\t\t\tif (ori.dir.equals(dir)) {\n\t\t\t\treturn ori;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic float getPipeLength() {\n\t\treturn 4;\n\t}\n\n\t@Override\n\tpublic EnumFacing getExitForInput(EnumFacing commingFrom) {\n\t\tif (orientation.dir.getOpposite() == commingFrom) {\n\t\t\treturn orientation.dir;\n\t\t}\n\t\tif (orientation.dir == commingFrom) {\n\t\t\treturn orientation.dir.getOpposite();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic TileEntity getConnectedEndTile(EnumFacing output) {\n\t\tif (orientation.dir.getOpposite() == output) {\n\t\t\treturn container.getTile(output);\n\t\t} else {\n\t\t\tDoubleCoordinates pos = new DoubleCoordinates(0, 1, -3);\n\t\t\tLPPositionSet<DoubleCoordinates> set = new LPPositionSet<>(DoubleCoordinates.class);\n\t\t\tset.add(pos);\n\t\t\torientation.rotatePositions(set);\n\t\t\tTileEntity subTile = pos.add(getLPPosition()).getTileEntity(getWorld());\n\t\t\tif (subTile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\treturn ((LogisticsTileGenericSubMultiBlock) subTile).getTile(output);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int getIconIndex(EnumFacing direction) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic boolean actAsNormalPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic ISpecialPipeRenderer getSpecialRenderer() {\n\t\treturn GainTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn GainTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getItemRenderPos(float fPos, LPTravelingItem travelItem) {\n\t\tif ((orientation.getDir().getOpposite() == travelItem.input) == (orientation.getOffset().getLength() != 0)) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\n\t\tfloat x = 0.5F;\n\t\tfloat y = 1.5F;\n\t\tfloat z = 0.5F;\n\t\tif (orientation.getRenderOrientation() == TubeGainRenderOrientation.SOUTH) {\n\t\t\tz -= fPos;\n\t\t\tz += 3.5F;\n\t\t\ty -= 0F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\ty += b * transport.getPipeLength() / 3;\n\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.NORTH) {\n\t\t\tz += fPos;\n\t\t\tz -= 3.5F;\n\t\t\tx -= 0F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\ty += b * transport.getPipeLength() / 3;\n\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.WEST) {\n\t\t\tx += fPos;\n\t\t\tx -= 3.5F;\n\t\t\tz -= 0F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\ty += b * transport.getPipeLength() / 3;\n\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.EAST) {\n\t\t\tx -= fPos;\n\t\t\tx += 3.5F;\n\t\t\tz += 0F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\ty += b * transport.getPipeLength() / 3;\n\t\t}\n\t\treturn new DoubleCoordinates(x, y, z);\n\t}\n\n\t@Override\n\tpublic double getItemRenderYaw(float fPos, LPTravelingItem travelItem) {\n\t\tboolean condition = ((orientation.getRenderOrientation() == TubeGainRenderOrientation.NORTH)\n\t\t\t\t|| (orientation.getRenderOrientation() == TubeGainRenderOrientation.SOUTH));\n\t\treturn condition ? 0 : 90;\n\t}\n\n\t@Override\n\tpublic double getItemRenderPitch(float fPos, LPTravelingItem travelItem) {\n\t\tif ((orientation.getDir().getOpposite() == travelItem.input) == (orientation.getOffset().getLength() != 0)) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\t\tdouble b;\n\t\tif (fPos < 0.5) {\n\t\t\tdouble a = 0.5 / transport.getPipeLength() * 3;\n\t\t\tb = -0.15119241907684 * Math.pow(a, 4) + 0.903656706092028 * Math.pow(a, 3) - 1.50813502012070 * Math.pow(a, 2) + 0.466513091531934 * a\n\t\t\t\t\t- 0.074807924321475;\n\t\t\tb = b * transport.getPipeLength() * -13;\n\t\t\tb = b * fPos / 0.5;\n\t\t} else if (fPos < 3.5) {\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tb = -0.15119241907684 * Math.pow(a, 4) + 0.903656706092028 * Math.pow(a, 3) - 1.50813502012070 * Math.pow(a, 2) + 0.466513091531934 * a\n\t\t\t\t\t- 0.074807924321475;\n\t\t\tb = b * transport.getPipeLength() * -13;\n\t\t} else {\n\t\t\tdouble a = 3.5 / transport.getPipeLength() * 3;\n\t\t\tb = -0.15119241907684 * Math.pow(a, 4) + 0.903656706092028 * Math.pow(a, 3) - 1.50813502012070 * Math.pow(a, 2) + 0.466513091531934 * a\n\t\t\t\t\t- 0.074807924321475;\n\t\t\tb = b * transport.getPipeLength() * -13;\n\t\t\tb = b * (transport.getPipeLength() - fPos) / (transport.getPipeLength() - 3.5);\n\t\t}\n\t\tif (orientation.getRenderOrientation() == TubeGainRenderOrientation.NORTH) {\n\t\t\treturn b;\n\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.SOUTH) {\n\t\t\treturn -b;\n\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.EAST) {\n\t\t\treturn -b;\n\t\t} else if (orientation.getRenderOrientation() == TubeGainRenderOrientation.WEST) {\n\t\t\treturn b;\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic double getBoxRenderScale(float fPos, LPTravelingItem travelItem) {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic boolean isHSTube() {\n\t\treturn true;\n\t}\n\n\tpublic enum TubeGainOrientation implements ITubeOrientation {\n\t\tNORTH(TubeGainRenderOrientation.NORTH, new DoubleCoordinates(0, 0, 0), EnumFacing.NORTH),\n\t\tSOUTH(TubeGainRenderOrientation.SOUTH, new DoubleCoordinates(0, 0, 0), EnumFacing.SOUTH),\n\t\tEAST(TubeGainRenderOrientation.EAST, new DoubleCoordinates(0, 0, 0), EnumFacing.EAST),\n\t\tWEST(TubeGainRenderOrientation.WEST, new DoubleCoordinates(0, 0, 0), EnumFacing.WEST);\n\n\t\t@Getter\n\t\tTubeGainRenderOrientation renderOrientation;\n\t\t@Getter\n\t\tDoubleCoordinates offset;\n\t\t@Getter\n\t\tEnumFacing dir;\n\n\t\tTubeGainOrientation(TubeGainRenderOrientation render, DoubleCoordinates off, EnumFacing dir) {\n\t\t\trenderOrientation = render;\n\t\t\toffset = off;\n\t\t\tthis.dir = dir;\n\t\t}\n\n\t\t@Override\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\trenderOrientation.rotateOrientation(set);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setOnPipe(CoreMultiBlockPipe pipe) {\n\t\t\t((HSTubeGain) pipe).orientation = this;\n\t\t}\n\t}\n\n\tpublic enum TubeGainRenderOrientation implements ITubeRenderOrientation {\n\t\tNORTH(EnumFacing.NORTH),\n\t\tSOUTH(EnumFacing.SOUTH),\n\t\tWEST(EnumFacing.WEST),\n\t\tEAST(EnumFacing.EAST);\n\n\t\t@Getter\n\t\tprivate EnumFacing dir;\n\n\t\tTubeGainRenderOrientation(EnumFacing dir) {\n\t\t\tthis.dir = dir;\n\t\t}\n\n\t\tpublic void rotateOrientation(IPositionRotateble set) {\n\t\t\tif (this == EAST) {\n\t\t\t\tset.rotateRight();\n\t\t\t} else if (this == WEST) {\n\t\t\t\tset.rotateLeft();\n\t\t\t} else if (this == SOUTH) {\n\t\t\t\tset.rotateLeft();\n\t\t\t\tset.rotateLeft();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/tubes/HSTubeLine.java",
    "content": "package logisticspipes.pipes.tubes;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.interfaces.ITubeRenderOrientation;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.tube.LineTubeRenderer;\nimport logisticspipes.transport.PipeMultiBlockTransportLogistics;\nimport logisticspipes.utils.IPositionRotateble;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class HSTubeLine extends CoreMultiBlockPipe {\n\n\t@Getter\n\tprivate TubeLineOrientation orientation;\n\n\tpublic HSTubeLine(Item item) {\n\t\tsuper(new PipeMultiBlockTransportLogistics(), item);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tif (orientation == null) {\n\t\t\toutput.writeBoolean(false);\n\t\t} else {\n\t\t\toutput.writeBoolean(true);\n\t\t\toutput.writeEnum(orientation);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tif (input.readBoolean()) {\n\t\t\torientation = input.readEnum(TubeLineOrientation.class);\n\t\t}\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getSubBlocks() {\n\t\treturn new LPPositionSet<>(DoubleCoordinatesType.class);\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getRotatedSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> set = getSubBlocks();\n\t\torientation.rotatePositions(set);\n\t\treturn set;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound data) {\n\t\tsuper.writeToNBT(data);\n\t\tdata.setString(\"orientation\", orientation.name());\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound data) {\n\t\tsuper.readFromNBT(data);\n\t\torientation = TubeLineOrientation.valueOf(data.getString(\"orientation\"));\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxesToList(List<AxisAlignedBB> arraylist, AxisAlignedBB axisalignedbb) {\n\t\tDoubleCoordinates pos = getLPPosition();\n\t\tLPPositionSet<DoubleCoordinates> set = new LPPositionSet<>(DoubleCoordinates.class);\n\t\tset.addFrom(LineTubeRenderer.tubeLine.get(orientation.getRenderOrientation()).bounds().toAABB());\n\t\tset.forEach(o -> o.add(pos));\n\t\tAxisAlignedBB box = set.toABB();\n\t\tif (box != null && (axisalignedbb == null || axisalignedbb.intersects(box))) {\n\t\t\tarraylist.add(box);\n\t\t}\n\t}\n\n\t@Override\n\tpublic AxisAlignedBB getCompleteBox() {\n\t\treturn LineTubeRenderer.tubeLine.get(orientation.getRenderOrientation()).bounds().toAABB();\n\t}\n\n\t@Override\n\tpublic ITubeOrientation getTubeOrientation(EntityPlayer player, int xPos, int zPos) {\n\t\tdouble x = xPos + 0.5 - player.posX;\n\t\tdouble z = zPos + 0.5 - player.posZ;\n\t\tdouble w = Math.atan2(x, z);\n\t\tdouble halfPI = Math.PI / 2;\n\t\tdouble halfhalfPI = halfPI / 2;\n\t\tw -= halfhalfPI;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir = null;\n\t\tif (0 < w && w <= halfPI) {\n\t\t\tdir = EnumFacing.WEST;\n\t\t} else if (halfPI < w && w <= 2 * halfPI) {\n\t\t\tdir = EnumFacing.SOUTH;\n\t\t} else if (2 * halfPI < w && w <= 3 * halfPI) {\n\t\t\tdir = EnumFacing.EAST;\n\t\t} else if (3 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir = EnumFacing.NORTH;\n\t\t}\n\t\tfor (TubeLineOrientation ori : TubeLineOrientation.values()) {\n\t\t\tif (ori.dir.equals(dir)) {\n\t\t\t\treturn ori;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic float getPipeLength() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic EnumFacing getExitForInput(EnumFacing commingFrom) {\n\t\treturn commingFrom.getOpposite();\n\t}\n\n\t@Override\n\tpublic TileEntity getConnectedEndTile(EnumFacing output) {\n\t\tif (output == this.orientation.dir || output.getOpposite() == this.orientation.dir) {\n\t\t\treturn container.getTile(output);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int getIconIndex(EnumFacing direction) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic boolean actAsNormalPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic ISpecialPipeRenderer getSpecialRenderer() {\n\t\treturn LineTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn LineTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic boolean isHSTube() {\n\t\treturn true;\n\t}\n\n\tpublic enum TubeLineOrientation implements ITubeOrientation {\n\t\tNORTH(TubeLineRenderOrientation.NORTH_SOUTH, new DoubleCoordinates(0, 0, 0), EnumFacing.NORTH),\n\t\tSOUTH(TubeLineRenderOrientation.NORTH_SOUTH, new DoubleCoordinates(0, 0, 0), EnumFacing.SOUTH),\n\t\tEAST(TubeLineRenderOrientation.EAST_WEST, new DoubleCoordinates(0, 0, 0), EnumFacing.EAST),\n\t\tWEST(TubeLineRenderOrientation.EAST_WEST, new DoubleCoordinates(0, 0, 0), EnumFacing.WEST);\n\n\t\t@Getter\n\t\tTubeLineRenderOrientation renderOrientation;\n\t\t@Getter\n\t\tDoubleCoordinates offset;\n\t\t@Getter\n\t\tEnumFacing dir;\n\n\t\tTubeLineOrientation(TubeLineRenderOrientation render, DoubleCoordinates off, EnumFacing dir) {\n\t\t\trenderOrientation = render;\n\t\t\toffset = off;\n\t\t\tthis.dir = dir;\n\t\t}\n\n\t\t@Override\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\trenderOrientation.rotateOrientation(set);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setOnPipe(CoreMultiBlockPipe pipe) {\n\t\t\t((HSTubeLine) pipe).orientation = this;\n\t\t}\n\t}\n\n\tpublic enum TubeLineRenderOrientation implements ITubeRenderOrientation {\n\t\tNORTH_SOUTH(EnumFacing.NORTH),\n\t\tEAST_WEST(EnumFacing.EAST);\n\n\t\t@Getter\n\t\tprivate EnumFacing dir;\n\n\t\tTubeLineRenderOrientation(EnumFacing dir) {\n\t\t\tthis.dir = dir;\n\t\t}\n\n\t\tpublic void rotateOrientation(IPositionRotateble set) {\n\t\t\tif (this == EAST_WEST) {\n\t\t\t\tset.rotateLeft();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/tubes/HSTubeSCurve.java",
    "content": "package logisticspipes.pipes.tubes;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.interfaces.ITubeRenderOrientation;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.tube.SCurveTubeRenderer;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeMultiBlockTransportLogistics;\nimport logisticspipes.utils.IPositionRotateble;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class HSTubeSCurve extends CoreMultiBlockPipe {\n\n\t@Getter\n\tprivate CurveSOrientation orientation;\n\tprivate List<AxisAlignedBB> boxes = null;\n\n\tpublic HSTubeSCurve(Item item) {\n\t\tsuper(new PipeMultiBlockTransportLogistics(), item);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tif (orientation == null) {\n\t\t\toutput.writeBoolean(false);\n\t\t} else {\n\t\t\toutput.writeBoolean(true);\n\t\t\toutput.writeEnum(orientation);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tif (input.readBoolean()) {\n\t\t\torientation = input.readEnum(CurveSOrientation.class);\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getIconIndex(EnumFacing direction) {\n\t\t// TODO Auto-generated method stub\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\t// TODO Auto-generated method stub\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> list = new LPPositionSet<>(DoubleCoordinatesType.class);\n\t\tlist.add(new DoubleCoordinatesType<>(0, 0, -1, SubBlockTypeForShare.S_CURVE_B));\n\t\tlist.add(new DoubleCoordinatesType<>(0, 0, -2, SubBlockTypeForShare.S_CURVE_A));\n\t\tlist.add(new DoubleCoordinatesType<>(1, 0, -1, SubBlockTypeForShare.S_CURVE_A));\n\t\tlist.add(new DoubleCoordinatesType<>(1, 0, -2, SubBlockTypeForShare.S_CURVE_B));\n\t\tlist.add(new DoubleCoordinatesType<>(1, 0, -3, SubBlockTypeForShare.NON_SHARE));\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getRotatedSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> set = getSubBlocks();\n\t\torientation.rotatePositions(set);\n\t\treturn set;\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxesToList(List<AxisAlignedBB> arraylist, AxisAlignedBB axisalignedbb) {\n\t\tif (boxes == null || boxes.isEmpty()) {\n\t\t\tboxes = new ArrayList<>();\n\t\t\tdouble x = getX();\n\t\t\tdouble y = getY();\n\t\t\tdouble z = getZ();\n\t\t\tfor (int i = -1; i < 54; i++) {\n\t\t\t\tdouble xOne = x;\n\t\t\t\tdouble yOne = y;\n\t\t\t\tdouble zOne = z;\n\t\t\t\tdouble xTwo = x;\n\t\t\t\tdouble yTwo = y + 1;\n\t\t\t\tdouble zTwo = z;\n\t\t\t\tif (orientation.getRenderOrientation() == TurnSDirection.NORTH_INV || orientation.getRenderOrientation() == TurnSDirection.NORTH) {\n\t\t\t\t\tzOne += 1;\n\t\t\t\t\tzTwo += 1;\n\t\t\t\t\tzOne -= 4.0F * (i - 4) / 50;\n\t\t\t\t\tzTwo -= 4.0F * (i + 4) / 50;\n\t\t\t\t\txOne -= 1;\n\t\t\t\t\txTwo += 2;\n\t\t\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.EAST_INV || orientation.getRenderOrientation() == TurnSDirection.EAST) {\n\t\t\t\t\txOne += 4;\n\t\t\t\t\txTwo += 4;\n\t\t\t\t\txOne -= 4.0F * (i - 4) / 50;\n\t\t\t\t\txTwo -= 4.0F * (i + 4) / 50;\n\t\t\t\t\tzOne -= 1;\n\t\t\t\t\tzTwo += 2;\n\t\t\t\t}\n\t\t\t\tAxisAlignedBB box = SCurveTubeRenderer.getObjectBoundsAt(new AxisAlignedBB(Math.min(xOne, xTwo), Math.min(yOne, yTwo), Math.min(zOne, zTwo), Math.max(xOne, xTwo), Math.max(yOne, yTwo),\n\t\t\t\t\t\tMath.max(zOne, zTwo)).offset(-x, -y, -z), orientation);\n\t\t\t\tif (box != null) {\n\t\t\t\t\tLPPositionSet<DoubleCoordinates> lpBox = new LPPositionSet<>(DoubleCoordinates.class);\n\t\t\t\t\tlpBox.addFrom(box);\n\t\t\t\t\tDoubleCoordinates center = lpBox.getCenter();\n\t\t\t\t\tbox = new AxisAlignedBB(center.getXCoord() - 0.3D, center.getYCoord() - 0.3D, center.getZCoord() - 0.3D, center.getXCoord() + 0.3D,\n\t\t\t\t\t\t\tcenter.getYCoord() + 0.3D, center.getZCoord() + 0.3D);\n\t\t\t\t\tAxisAlignedBB cBox = getCompleteBox();\n\t\t\t\t\tdouble minX = Math.max(box.minX, cBox.minX);\n\t\t\t\t\tdouble minY = Math.max(box.minY, cBox.minY);\n\t\t\t\t\tdouble minZ = Math.max(box.minZ, cBox.minZ);\n\t\t\t\t\tdouble maxX = Math.min(box.maxX, cBox.maxX);\n\t\t\t\t\tdouble maxY = Math.min(box.maxY, cBox.maxY);\n\t\t\t\t\tdouble maxZ = Math.min(box.maxZ, cBox.maxZ);\n\t\t\t\t\tboxes.add(new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).offset(x, y, z));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tarraylist.addAll(boxes.stream()\n\t\t\t\t.filter(box -> box != null && (axisalignedbb == null || axisalignedbb.intersects(box)))\n\t\t\t\t.collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic AxisAlignedBB getCompleteBox() {\n\t\treturn SCurveTubeRenderer.tubeSCurve.get(orientation.getRenderOrientation()).bounds().toAABB();\n\t}\n\n\t@Override\n\tpublic ITubeOrientation getTubeOrientation(EntityPlayer player, int xPos, int zPos) {\n\t\tdouble x = xPos + 0.5 - player.posX;\n\t\tdouble z = zPos + 0.5 - player.posZ;\n\t\tdouble w = Math.atan2(x, z);\n\t\tdouble halfPI = Math.PI / 2;\n\t\tdouble halfhalfPI = halfPI / 2;\n\t\tw -= halfhalfPI;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir = null;\n\t\tEnumFacing dir1 = null;\n\t\tEnumFacing dir2 = null;\n\t\tdouble addition = 0;\n\t\tif (0 < w && w <= halfPI) {\n\t\t\tdir = EnumFacing.EAST;\n\t\t\tdir1 = EnumFacing.NORTH;\n\t\t\tdir2 = EnumFacing.SOUTH;\n\t\t\taddition = halfPI;\n\t\t} else if (halfPI < w && w <= 2 * halfPI) {\n\t\t\tdir = EnumFacing.NORTH;\n\t\t\tdir1 = EnumFacing.EAST;\n\t\t\tdir2 = EnumFacing.WEST;\n\t\t} else if (2 * halfPI < w && w <= 3 * halfPI) {\n\t\t\tdir = EnumFacing.WEST;\n\t\t\tdir1 = EnumFacing.NORTH;\n\t\t\tdir2 = EnumFacing.SOUTH;\n\t\t\taddition = halfPI;\n\t\t} else if (3 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir = EnumFacing.SOUTH;\n\t\t\tdir1 = EnumFacing.EAST;\n\t\t\tdir2 = EnumFacing.WEST;\n\t\t}\n\t\tw = Math.atan2(player.getLookVec().x, player.getLookVec().z);\n\t\tw -= addition;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir3 = null;\n\t\tif (0 < w && w <= 2 * halfPI) {\n\t\t\tdir3 = dir1;\n\t\t} else if (2 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir3 = dir2;\n\t\t}\n\t\tfor (CurveSOrientation curve : CurveSOrientation.values()) {\n\t\t\tif (curve.dir.equals(dir)) {\n\t\t\t\tif (curve.looking.equals(dir3)) {\n\t\t\t\t\treturn curve;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound data) {\n\t\tsuper.writeToNBT(data);\n\t\tdata.setString(\"orientation\", orientation.name());\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound data) {\n\t\tsuper.readFromNBT(data);\n\t\torientation = CurveSOrientation.valueOf(data.getString(\"orientation\"));\n\t}\n\n\t@Override\n\tpublic float getPipeLength() {\n\t\treturn 4;\n\t}\n\n\t@Override\n\tpublic EnumFacing getExitForInput(EnumFacing commingFrom) {\n\t\tif (orientation.dir.getOpposite() == commingFrom) {\n\t\t\treturn orientation.dir;\n\t\t}\n\t\tif (orientation.dir == commingFrom) {\n\t\t\treturn orientation.dir.getOpposite();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic TileEntity getConnectedEndTile(EnumFacing output) {\n\t\tboolean useOwn;\n\t\tif (orientation.getOffset().getLength() != 0) {\n\t\t\tif (orientation.dir.getOpposite() == output) {\n\t\t\t\tuseOwn = false;\n\t\t\t} else if (orientation.dir == output) {\n\t\t\t\tuseOwn = true;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t} else {\n\t\t\tif (orientation.dir.getOpposite() == output) {\n\t\t\t\tuseOwn = true;\n\t\t\t} else if (orientation.dir == output) {\n\t\t\t\tuseOwn = false;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tif (useOwn) {\n\t\t\treturn container.getTile(output);\n\t\t} else {\n\t\t\tDoubleCoordinates pos = new DoubleCoordinates(1, 0, -3);\n\t\t\tLPPositionSet<DoubleCoordinates> set = new LPPositionSet<>(DoubleCoordinates.class);\n\t\t\tset.add(pos);\n\t\t\torientation.rotatePositions(set);\n\t\t\tTileEntity subTile = pos.add(getLPPosition()).getTileEntity(getWorld());\n\t\t\tif (subTile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\treturn ((LogisticsTileGenericSubMultiBlock) subTile).getTile(output);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean actAsNormalPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic ISpecialPipeRenderer getSpecialRenderer() {\n\t\treturn SCurveTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn SCurveTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getItemRenderPos(float fPos, LPTravelingItem travelItem) {\n\t\tif ((orientation.getDir().getOpposite() == travelItem.input) == (orientation.getOffset().getLength() != 0)) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\n\t\tfloat x = 0.5F;\n\t\tfloat y = 0.5F;\n\t\tfloat z = 0.5F;\n\t\tif (orientation.getRenderOrientation() == TurnSDirection.NORTH) {\n\t\t\tz -= fPos;\n\t\t\tz += 0.5F;\n\t\t\tx -= 0F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\tx += b * transport.getPipeLength() / 3;\n\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.NORTH_INV) {\n\t\t\tz -= fPos;\n\t\t\tz += 0.5F;\n\t\t\tx -= 0F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\tx -= b * transport.getPipeLength() / 3;\n\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.EAST) {\n\t\t\tx -= fPos;\n\t\t\tx += 3.5F;\n\t\t\tz -= 1F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\tz -= b * transport.getPipeLength() / 3;\n\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.EAST_INV) {\n\t\t\tx -= fPos;\n\t\t\tx += 3.5F;\n\t\t\tz += 1F;\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tdouble b = -0.030238483815369 * Math.pow(a, 5) + 0.225914176523007 * Math.pow(a, 4) - 0.502711673373567 * Math.pow(a, 3) + 0.233256545765967 * Math\n\t\t\t\t\t.pow(a, 2) - 0.074807924321475 * a + 0.000099653425518;\n\t\t\tz += b * transport.getPipeLength() / 3;\n\t\t}\n\t\treturn new DoubleCoordinates(x, y, z);\n\t}\n\n\t@Override\n\tpublic double getItemRenderPitch(float fPos, LPTravelingItem travelItem) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic double getItemRenderYaw(float fPos, LPTravelingItem travelItem) {\n\t\tif ((orientation.getDir().getOpposite() == travelItem.input) == (orientation.getOffset().getLength() != 0)) {\n\t\t\tfPos = transport.getPipeLength() - fPos;\n\t\t}\n\t\tdouble b;\n\t\tif (fPos < 0.5) {\n\t\t\tdouble a = 0.5 / transport.getPipeLength() * 3;\n\t\t\tb = -0.15119241907684 * Math.pow(a, 4) + 0.903656706092028 * Math.pow(a, 3) - 1.50813502012070 * Math.pow(a, 2) + 0.466513091531934 * a\n\t\t\t\t\t- 0.074807924321475;\n\t\t\tb = b * transport.getPipeLength() * -13;\n\t\t\tb = b * fPos / 0.5;\n\t\t} else if (fPos < 3.5) {\n\t\t\tdouble a = fPos / transport.getPipeLength() * 3;\n\t\t\tb = -0.15119241907684 * Math.pow(a, 4) + 0.903656706092028 * Math.pow(a, 3) - 1.50813502012070 * Math.pow(a, 2) + 0.466513091531934 * a\n\t\t\t\t\t- 0.074807924321475;\n\t\t\tb = b * transport.getPipeLength() * -13;\n\t\t} else {\n\t\t\tdouble a = 3.5 / transport.getPipeLength() * 3;\n\t\t\tb = -0.15119241907684 * Math.pow(a, 4) + 0.903656706092028 * Math.pow(a, 3) - 1.50813502012070 * Math.pow(a, 2) + 0.466513091531934 * a\n\t\t\t\t\t- 0.074807924321475;\n\t\t\tb = b * transport.getPipeLength() * -13;\n\t\t\tb = b * (transport.getPipeLength() - fPos) / (transport.getPipeLength() - 3.5);\n\t\t}\n\t\tif (orientation.getRenderOrientation() == TurnSDirection.NORTH) {\n\t\t\treturn b;\n\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.NORTH_INV) {\n\t\t\treturn -b;\n\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.EAST) {\n\t\t\treturn 90 + b;\n\t\t} else if (orientation.getRenderOrientation() == TurnSDirection.EAST_INV) {\n\t\t\treturn 90 - b;\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic double getBoxRenderScale(float fPos, LPTravelingItem travelItem) {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic boolean isHSTube() {\n\t\treturn true;\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum CurveSOrientation implements ITubeOrientation {\n\t\t//@formatter:off\n\t\t// Name: Placement from  _ TurnDirection\n\t\tNORTH_EAST(TurnSDirection.NORTH_INV, new DoubleCoordinates(0, 0, 0), EnumFacing.NORTH, EnumFacing.EAST),\n\t\tNORTH_WEST(TurnSDirection.NORTH, new DoubleCoordinates(0, 0, 0), EnumFacing.NORTH, EnumFacing.WEST),\n\t\tEAST_SOUTH(TurnSDirection.EAST_INV, new DoubleCoordinates(0, 0, 0), EnumFacing.EAST, EnumFacing.SOUTH),\n\t\tEAST_NORTH(TurnSDirection.EAST, new DoubleCoordinates(0, 0, 0), EnumFacing.EAST, EnumFacing.NORTH),\n\t\tSOUTH_WEST(TurnSDirection.NORTH_INV, new DoubleCoordinates(-1, 0, 3), EnumFacing.SOUTH, EnumFacing.WEST),\n\t\tSOUTH_EAST(TurnSDirection.NORTH, new DoubleCoordinates(1, 0, 3), EnumFacing.SOUTH, EnumFacing.EAST),\n\t\tWEST_NORTH(TurnSDirection.EAST_INV, new DoubleCoordinates(-3, 0, -1), EnumFacing.WEST, EnumFacing.NORTH),\n\t\tWEST_SOUTH(TurnSDirection.EAST, new DoubleCoordinates(-3, 0, 1), EnumFacing.WEST, EnumFacing.SOUTH);\n\t\t//@formatter:on\n\n\t\t@Getter\n\t\tTurnSDirection renderOrientation;\n\t\t@Getter\n\t\tDoubleCoordinates offset;\n\t\t@Getter\n\t\tEnumFacing dir;\n\t\t@Getter\n\t\tEnumFacing looking;\n\n\t\t@Override\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\trenderOrientation.rotatePositions(set);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setOnPipe(CoreMultiBlockPipe pipe) {\n\t\t\t((HSTubeSCurve) pipe).orientation = this;\n\t\t}\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum TurnSDirection implements ITubeRenderOrientation {\n\t\t//@formatter:off\n\t\tNORTH(EnumFacing.NORTH),\n\t\tEAST(EnumFacing.EAST),\n\t\tNORTH_INV(EnumFacing.SOUTH),\n\t\tEAST_INV(EnumFacing.WEST);\n\t\t//@formatter:on\n\n\t\t@Getter\n\t\tprivate EnumFacing dir1;\n\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\tif (this == NORTH) {\n\t\t\t\tset.mirrorX();\n\t\t\t} else if (this == EAST) {\n\t\t\t\tset.mirrorX();\n\t\t\t\tset.rotateRight();\n\t\t\t} else if (this == EAST_INV) {\n\t\t\t\tset.rotateRight();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/tubes/HSTubeSpeedup.java",
    "content": "package logisticspipes.pipes.tubes;\n\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.interfaces.ITubeRenderOrientation;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.tube.SpeedupTubeRenderer;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemClient;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.transport.PipeMultiBlockTransportLogistics;\nimport logisticspipes.utils.IPositionRotateble;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class HSTubeSpeedup extends CoreMultiBlockPipe {\n\n\t@Getter\n\tprivate SpeedupDirection orientation;\n\n\tpublic HSTubeSpeedup(Item item) {\n\t\tsuper(new PipeMultiBlockTransportLogistics() {\n\n\t\t\t@Override\n\t\t\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing side) {\n\t\t\t\tif (side.getOpposite() == ((HSTubeSpeedup) getMultiPipe()).orientation.dir1) {\n\t\t\t\t\treturn super.canPipeConnect_internal(tile, side);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected void handleTileReachedServer(LPTravelingItemServer arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\t\t\tif (dir.getOpposite() == ((HSTubeSpeedup) getMultiPipe()).orientation.dir1) {\n\t\t\t\t\tarrivingItem.setSpeed(LPConstants.PIPE_NORMAL_SPEED * 20);\n\t\t\t\t\thandleTileReachedServer_internal(arrivingItem, tile, dir);\n\t\t\t\t} else {\n\t\t\t\t\tsuper.handleTileReachedServer(arrivingItem, tile, dir);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected void handleTileReachedClient(LPTravelingItemClient arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\t\t\tif (dir.getOpposite() == ((HSTubeSpeedup) getMultiPipe()).orientation.dir1) {\n\t\t\t\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\t\t\t\tarrivingItem.setSpeed(LPConstants.PIPE_NORMAL_SPEED * 20);\n\t\t\t\t\t\tpassToNextPipe(arrivingItem, tile);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tsuper.handleTileReachedClient(arrivingItem, tile, dir);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}, item);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeEnum(orientation);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\torientation = input.readEnum(SpeedupDirection.class);\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> set = new LPPositionSet<>(DoubleCoordinatesType.class);\n\t\tset.add(new DoubleCoordinatesType<>(0, 0, -1, SubBlockTypeForShare.NON_SHARE));\n\t\tset.add(new DoubleCoordinatesType<>(0, 0, -2, SubBlockTypeForShare.NON_SHARE));\n\t\tset.add(new DoubleCoordinatesType<>(0, 0, -3, SubBlockTypeForShare.NON_SHARE));\n\t\treturn set;\n\t}\n\n\t@Override\n\tpublic LPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> getRotatedSubBlocks() {\n\t\tLPPositionSet<DoubleCoordinatesType<SubBlockTypeForShare>> set = getSubBlocks();\n\t\torientation.rotatePositions(set);\n\t\treturn set;\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxesToList(List<AxisAlignedBB> arraylist, AxisAlignedBB axisalignedbb) {\n\t\tDoubleCoordinates pos = getLPPosition();\n\t\tDoubleCoordinates posMin = new DoubleCoordinates(LPConstants.PIPE_MIN_POS, LPConstants.PIPE_MIN_POS, LPConstants.PIPE_MIN_POS);\n\t\tDoubleCoordinates posMax = new DoubleCoordinates(LPConstants.PIPE_MAX_POS, LPConstants.PIPE_MAX_POS, -3);\n\t\torientation.rotatePositions(posMin);\n\t\torientation.rotatePositions(posMax);\n\t\tif (orientation == SpeedupDirection.EAST) {\n\t\t\tpos.add(new DoubleCoordinates(1, 0, 0));\n\t\t} else if (orientation == SpeedupDirection.SOUTH) {\n\t\t\tpos.add(new DoubleCoordinates(1, 0, 1));\n\t\t} else if (orientation == SpeedupDirection.WEST) {\n\t\t\tpos.add(new DoubleCoordinates(0, 0, 1));\n\t\t}\n\t\tposMin.add(pos);\n\t\tposMax.add(pos);\n\t\tLPPositionSet<DoubleCoordinates> set = new LPPositionSet<>(DoubleCoordinates.class);\n\t\tset.add(posMin);\n\t\tset.add(posMax);\n\t\tAxisAlignedBB box = set.toABB();\n\t\tif (box != null && (axisalignedbb == null || axisalignedbb.intersects(box))) {\n\t\t\tarraylist.add(box);\n\t\t}\n\t}\n\n\t@Override\n\tpublic AxisAlignedBB getCompleteBox() {\n\t\treturn SpeedupTubeRenderer.tubeSpeedup.get(orientation).bounds().toAABB();\n\t}\n\n\t@Override\n\tpublic ITubeOrientation getTubeOrientation(EntityPlayer player, int xPos, int zPos) {\n\t\tdouble x = xPos + 0.5 - player.posX;\n\t\tdouble z = zPos + 0.5 - player.posZ;\n\t\tdouble w = Math.atan2(x, z);\n\t\tdouble halfPI = Math.PI / 2;\n\t\tdouble halfhalfPI = halfPI / 2;\n\t\tw -= halfhalfPI;\n\t\tif (w < 0) {\n\t\t\tw += 2 * Math.PI;\n\t\t}\n\t\tEnumFacing dir = null;\n\t\tif (0 < w && w <= halfPI) {\n\t\t\tdir = EnumFacing.WEST;\n\t\t} else if (halfPI < w && w <= 2 * halfPI) {\n\t\t\tdir = EnumFacing.SOUTH;\n\t\t} else if (2 * halfPI < w && w <= 3 * halfPI) {\n\t\t\tdir = EnumFacing.EAST;\n\t\t} else if (3 * halfPI < w && w <= 4 * halfPI) {\n\t\t\tdir = EnumFacing.NORTH;\n\t\t}\n\t\tfor (SpeedupDirection ori : SpeedupDirection.values()) {\n\t\t\tif (ori.dir1.getOpposite().equals(dir)) {\n\t\t\t\treturn ori;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound data) {\n\t\tsuper.writeToNBT(data);\n\t\tdata.setString(\"orientation\", orientation.name());\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound data) {\n\t\tsuper.readFromNBT(data);\n\t\torientation = SpeedupDirection.valueOf(data.getString(\"orientation\"));\n\t}\n\n\t@Override\n\tpublic float getPipeLength() {\n\t\treturn 4;\n\t}\n\n\t@Override\n\tpublic EnumFacing getExitForInput(EnumFacing commingFrom) {\n\t\treturn commingFrom.getOpposite();\n\t}\n\n\t@Override\n\tpublic TileEntity getConnectedEndTile(EnumFacing output) {\n\t\tif (orientation.dir1 == output) {\n\t\t\tDoubleCoordinates pos = new DoubleCoordinates(0, 0, -3);\n\t\t\tLPPositionSet<DoubleCoordinates> set = new LPPositionSet<>(DoubleCoordinates.class);\n\t\t\tset.add(pos);\n\t\t\torientation.rotatePositions(set);\n\t\t\tTileEntity subTile = pos.add(getLPPosition()).getTileEntity(getWorld());\n\t\t\tif (subTile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\treturn ((LogisticsTileGenericSubMultiBlock) subTile).getTile(output);\n\t\t\t}\n\t\t} else if (orientation.dir1.getOpposite() == output) {\n\t\t\treturn container.getTile(output);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean actAsNormalPipe() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic ISpecialPipeRenderer getSpecialRenderer() {\n\t\treturn SpeedupTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn SpeedupTubeRenderer.instance;\n\t}\n\n\t@Override\n\tpublic int getIconIndex(EnumFacing direction) {\n\t\t// TODO Auto-generated method stub\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\t// TODO Auto-generated method stub\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic boolean hasSpecialPipeEndAt(EnumFacing dir) {\n\t\treturn dir == orientation.dir1;\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getItemRenderPos(float fPos, LPTravelingItem travelItem) {\n\t\tDoubleCoordinates pos = new DoubleCoordinates(0.5D, 0.5D, 0.5D);\n\t\tfloat pPos = fPos;\n\t\tif (travelItem.input.getOpposite() == orientation.dir1) {\n\t\t\tCoordinateUtils.add(pos, orientation.dir1, 3);\n\t\t\tpPos = this.getPipeLength() - fPos;\n\t\t}\n\t\tif (pPos < 0.5) {\n\t\t\tif (travelItem.input == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!container.renderState.pipeConnectionMatrix.isConnected(travelItem.input.getOpposite())) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tCoordinateUtils.add(pos, travelItem.input.getOpposite(), 0.5 - fPos);\n\t\t} else {\n\t\t\tif (travelItem.output == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tCoordinateUtils.add(pos, travelItem.output, fPos - 0.5);\n\t\t}\n\t\treturn pos;\n\t}\n\n\t@Override\n\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing side) {\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tif (this.getOrientation().getDir1() != side) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn super.canPipeConnect(tile, side);\n\t}\n\n\t@Override\n\tpublic boolean isHSTube() {\n\t\treturn true;\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum SpeedupDirection implements ITubeRenderOrientation, ITubeOrientation {\n\t\t//@formatter:off\n\t\tNORTH(EnumFacing.NORTH),\n\t\tSOUTH(EnumFacing.SOUTH),\n\t\tEAST(EnumFacing.EAST),\n\t\tWEST(EnumFacing.WEST);\n\t\t//@formatter:on\n\t\t@Getter\n\t\tEnumFacing dir1;\n\n\t\t@Override\n\t\tpublic void rotatePositions(IPositionRotateble set) {\n\t\t\tif (this == SOUTH) {\n\t\t\t\tset.rotateLeft();\n\t\t\t\tset.rotateLeft();\n\t\t\t} else if (this == EAST) {\n\t\t\t\tset.rotateRight();\n\t\t\t} else if (this == WEST) {\n\t\t\t\tset.rotateLeft();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic ITubeRenderOrientation getRenderOrientation() {\n\t\t\treturn this;\n\t\t}\n\n\t\t@Override\n\t\tpublic DoubleCoordinates getOffset() {\n\t\t\treturn new DoubleCoordinates(0, 0, 0);\n\t\t}\n\n\t\t@Override\n\t\tpublic void setOnPipe(CoreMultiBlockPipe pipe) {\n\t\t\t((HSTubeSpeedup) pipe).orientation = this;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/unrouted/PipeItemsBasicTransport.java",
    "content": "package logisticspipes.pipes.unrouted;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.transport.PipeTransportLogistics;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class PipeItemsBasicTransport extends CoreUnroutedPipe {\n\n\tpublic PipeItemsBasicTransport(Item item) {\n\t\tsuper(new PipeTransportLogistics(false), item);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {}\n\n\t@Override\n\tpublic int getIconIndex(EnumFacing direction) {\n\t\treturn Textures.LOGISTICSPIPE_BASIC_TRANSPORT_TEXTURE.normal;\n\t}\n\n\t@Override\n\tpublic int getTextureIndex() {\n\t\treturn Textures.LOGISTICSPIPE_BASIC_TRANSPORT_TEXTURE.newTexture;\n\t}\n\n\t@Override\n\tpublic IHighlightPlacementRenderer getHighlightRenderer() {\n\t\treturn LogisticsRenderPipe.secondRenderer;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/ActionSpeedUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.module.AsyncExtractorModule;\n\npublic class ActionSpeedUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"action_speed\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule module) {\n\t\treturn module instanceof AsyncExtractorModule || module instanceof AsyncAdvancedExtractor;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] {};\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"extractor\", \"aextractor\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/AdvancedSatelliteUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class AdvancedSatelliteUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"satellite_advanced\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule module) {\n\t\treturn module instanceof ModuleCrafter;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/CCRemoteControlUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class CCRemoteControlUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"cc_remote_control\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/CombinedSneakyUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class CombinedSneakyUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"sneaky_combination\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/ConnectionUpgradeConfig.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport java.util.Arrays;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractguis.UpgradeCoordinatesGuiProvider;\nimport logisticspipes.network.guis.upgrade.DisconnectionUpgradeConfigGuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class ConnectionUpgradeConfig implements IConfigPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"disconnection\";\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum Sides {\n\t\tUP(EnumFacing.UP, \"LPDIS-UP\"),\n\t\tDOWN(EnumFacing.DOWN, \"LPDIS-DOWN\"),\n\t\tNORTH(EnumFacing.NORTH, \"LPDIS-NORTH\"),\n\t\tSOUTH(EnumFacing.SOUTH, \"LPDIS-SOUTH\"),\n\t\tEAST(EnumFacing.EAST, \"LPDIS-EAST\"),\n\t\tWEST(EnumFacing.WEST, \"LPDIS-WEST\");\n\t\t@Getter\n\t\tprivate EnumFacing dir;\n\t\t@Getter\n\t\tprivate String lpName;\n\n\t\tpublic static String getNameForDirection(EnumFacing fd) {\n\t\t\tOptional<Sides> opt = Arrays.stream(values()).filter(side -> side.getDir() == fd).findFirst();\n\t\t\tif (opt.isPresent()) {\n\t\t\t\treturn opt.get().getLpName();\n\t\t\t}\n\t\t\treturn \"LPDIS-UNKNWON\";\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n\n\t@Override\n\tpublic UpgradeCoordinatesGuiProvider getGUI() {\n\t\treturn NewGuiHandler.getGui(DisconnectionUpgradeConfigGuiProvider.class);\n\t}\n\n\t@Nonnull\n\tpublic Stream<EnumFacing> getSides(@Nonnull ItemStack stack) {\n\t\tif (stack.isEmpty()) return Stream.empty();\n\t\tif (!stack.hasTagCompound()) {\n\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t}\n\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\treturn Arrays.stream(Sides.values()).filter(side -> tag.getBoolean(side.getLpName())).map(Sides::getDir);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/CraftingByproductUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class CraftingByproductUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"crafting_byproduct\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn pipe instanceof ModuleCrafter;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/CraftingCleanupUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class CraftingCleanupUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"crafting_cleanup\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn pipe instanceof ModuleCrafter;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/CraftingMonitoringUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class CraftingMonitoringUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"crafting_monitoring\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeBlockRequestTable;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"requestblock\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/FluidCraftingUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class FluidCraftingUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"fluid_crafting\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn pipe instanceof ModuleCrafter;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"crafting\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/FuzzyUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\r\n\r\nimport logisticspipes.modules.LogisticsModule;\r\nimport logisticspipes.modules.ModuleCrafter;\r\nimport logisticspipes.modules.ModuleItemSink;\r\nimport logisticspipes.pipes.PipeItemsBasicLogistics;\r\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\r\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\r\n\r\npublic class FuzzyUpgrade implements IPipeUpgrade {\r\n\r\n\tpublic static String getName() {\r\n\t\treturn \"fuzzy\";\r\n\t}\r\n\r\n\t@Override\r\n\tpublic boolean needsUpdate() {\r\n\t\treturn false;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\r\n\t\treturn pipe instanceof PipeItemsCraftingLogistics || pipe instanceof PipeItemsBasicLogistics;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\r\n\t\treturn pipe instanceof ModuleCrafter || pipe instanceof ModuleItemSink;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic String[] getAllowedPipes() {\r\n\t\treturn new String[] { \"crafting\", \"basic\" };\r\n\t}\r\n\r\n\t@Override\r\n\tpublic String[] getAllowedModules() {\r\n\t\treturn new String[] { \"crafting\", \"itemsink\" };\r\n\t}\r\n}\r\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/IConfigPipeUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.network.abstractguis.UpgradeCoordinatesGuiProvider;\n\npublic interface IConfigPipeUpgrade extends IPipeUpgrade {\n\n\tUpgradeCoordinatesGuiProvider getGUI();\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/IPipeUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic interface IPipeUpgrade {\n\n\tboolean needsUpdate();\n\n\tboolean isAllowedForPipe(CoreRoutedPipe pipe);\n\n\tboolean isAllowedForModule(LogisticsModule pipe);\n\n\tString[] getAllowedPipes();\n\n\tString[] getAllowedModules();\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/ItemExtractionUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.PipeItemsProviderLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.module.AsyncExtractorModule;\n\npublic class ItemExtractionUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"item_extraction\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics || pipe instanceof PipeItemsProviderLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule module) {\n\t\treturn module instanceof ModuleCrafter || module instanceof ModuleProvider || module instanceof AsyncExtractorModule || module instanceof AsyncAdvancedExtractor;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"crafting\", \"provider\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"crafting\", \"provider\", \"extractor\", \"aextractor\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/ItemStackExtractionUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.pipes.PipeItemsCraftingLogistics;\nimport logisticspipes.pipes.PipeItemsProviderLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.module.AsyncExtractorModule;\n\npublic class ItemStackExtractionUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"item_stack_extraction\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsCraftingLogistics || pipe instanceof PipeItemsProviderLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule module) {\n\t\treturn module instanceof ModuleCrafter || module instanceof ModuleProvider\n\t\t\t\t|| module instanceof AsyncExtractorModule || module instanceof AsyncAdvancedExtractor;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"crafting\", \"provider\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"crafting\", \"provider\", \"extractor\", \"aextractor\" };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/LogicControllerUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class LogicControllerUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"logic_controller\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/ModuleUpgradeManager.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.item.SimpleStackInventory;\nimport network.rs485.logisticspipes.property.SimpleInventoryProperty;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class ModuleUpgradeManager implements ISimpleInventoryEventHandler, ISlotUpgradeManager {\n\n\tprivate final UpgradeManager parent;\n\tprivate final SimpleStackInventory internalInv;\n\t@Getter\n\tprivate final SimpleInventoryProperty inv;\n\tprivate final IPipeUpgrade[] upgrades = new IPipeUpgrade[2];\n\tprivate final PipeLogisticsChassis pipe; // FIXME: get rid of this pipe reference\n\n\tprivate EnumFacing sneakyOrientation = null;\n\tprivate boolean isAdvancedCrafter = false;\n\tprivate boolean isFuzzyUpgrade = false;\n\tprivate int liquidCrafter = 0;\n\tprivate boolean hasByproductExtractor = false;\n\tprivate boolean hasPatternUpgrade = false;\n\tprivate int craftingCleanup = 0;\n\tprivate int actionSpeedUpgrade = 0;\n\tprivate int itemExtractionUpgrade = 0;\n\tprivate int itemStackExtractionUpgrade = 0;\n\n\tprivate boolean[] guiUpgrades = new boolean[2];\n\n\tprivate ModuleUpgradeManager(PipeLogisticsChassis pipe, UpgradeManager parentUpgradeManager, SimpleStackInventory internalInv) {\n\t\tthis.internalInv = internalInv;\n\t\tthis.inv = new SimpleInventoryProperty(this.internalInv, \"moduleUpgrades\");\n\t\tthis.internalInv.addListener(this);\n\t\tthis.pipe = pipe;\n\t\tthis.parent = parentUpgradeManager;\n\t}\n\n\tpublic ModuleUpgradeManager(PipeLogisticsChassis pipe, UpgradeManager parentUpgradeManager) {\n\t\tthis(pipe, parentUpgradeManager, new SimpleStackInventory(2, \"UpgradeInventory\", 16));\n\t}\n\n\tpublic ModuleUpgradeManager(ModuleUpgradeManager copy) {\n\t\tthis(copy.pipe, copy.parent, new SimpleStackInventory(copy.internalInv));\n\t\tInventoryChanged(internalInv);\n\t}\n\n\t@Override\n\tpublic boolean hasPatternUpgrade() {\n\t\treturn hasPatternUpgrade || parent.hasPatternUpgrade();\n\t}\n\n\t@Override\n\tpublic boolean isAdvancedSatelliteCrafter() {\n\t\treturn isAdvancedCrafter || parent.isAdvancedSatelliteCrafter();\n\t}\n\n\t@Override\n\tpublic boolean hasByproductExtractor() {\n\t\treturn hasByproductExtractor || parent.hasByproductExtractor();\n\t}\n\n\t@Override\n\tpublic int getFluidCrafter() {\n\t\treturn Math.min(liquidCrafter + parent.getFluidCrafter(), ItemUpgrade.MAX_LIQUID_CRAFTER);\n\t}\n\n\t@Override\n\tpublic boolean isFuzzyUpgrade() {\n\t\treturn isFuzzyUpgrade || parent.isFuzzyUpgrade();\n\t}\n\n\t@Override\n\tpublic int getCrafterCleanup() {\n\t\treturn Math.min(craftingCleanup + parent.getCrafterCleanup(), ItemUpgrade.MAX_CRAFTING_CLEANUP);\n\t}\n\n\t@Override\n\tpublic boolean hasSneakyUpgrade() {\n\t\tif (sneakyOrientation != null) {\n\t\t\treturn true;\n\t\t}\n\t\treturn parent.hasSneakyUpgrade();\n\t}\n\n\t@Override\n\tpublic EnumFacing getSneakyOrientation() {\n\t\tif (sneakyOrientation != null) {\n\t\t\treturn sneakyOrientation;\n\t\t}\n\t\treturn parent.getSneakyOrientation();\n\t}\n\n\t@Override\n\tpublic boolean hasOwnSneakyUpgrade() {\n\t\treturn sneakyOrientation != null;\n\t}\n\n\t@Override\n\tpublic IPipeUpgrade getUpgrade(int slot) {\n\t\treturn upgrades[slot];\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getPipePosition() {\n\t\treturn pipe.getLPPosition();\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tboolean needUpdate = false;\n\t\tfor (int i = 0; i < inv.getSizeInventory(); i++) {\n\t\t\tif (inv.isSlotEmpty(i)) {\n\t\t\t\tif (upgrades[i] != null) {\n\t\t\t\t\tneedUpdate |= removeUpgrade(i, upgrades);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tneedUpdate |= updateModule(i, upgrades, inv);\n\t\t\t}\n\t\t}\n\t\t//update sneaky direction, speed upgrade count and disconnection\n\t\tsneakyOrientation = null;\n\t\tisAdvancedCrafter = false;\n\t\tisFuzzyUpgrade = false;\n\t\tliquidCrafter = 0;\n\t\thasByproductExtractor = false;\n\t\thasPatternUpgrade = false;\n\t\tcraftingCleanup = 0;\n\t\tactionSpeedUpgrade = 0;\n\t\titemExtractionUpgrade = 0;\n\t\titemStackExtractionUpgrade = 0;\n\t\tguiUpgrades = new boolean[2];\n\t\tfor (int i = 0; i < upgrades.length; i++) {\n\t\t\tIPipeUpgrade upgrade = upgrades[i];\n\t\t\tif (upgrade instanceof SneakyUpgradeConfig && sneakyOrientation == null) {\n\t\t\t\tItemStack stack = inv.getStackInSlot(i);\n\t\t\t\tsneakyOrientation = ((SneakyUpgradeConfig) upgrade).getSide(stack);\n\t\t\t} else if (upgrade instanceof AdvancedSatelliteUpgrade) {\n\t\t\t\tisAdvancedCrafter = true;\n\t\t\t} else if (upgrade instanceof FuzzyUpgrade) {\n\t\t\t\tisFuzzyUpgrade = true;\n\t\t\t} else if (upgrade instanceof FluidCraftingUpgrade) {\n\t\t\t\tliquidCrafter += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof CraftingByproductUpgrade) {\n\t\t\t\thasByproductExtractor = true;\n\t\t\t} else if (upgrade instanceof PatternUpgrade) {\n\t\t\t\thasPatternUpgrade = true;\n\t\t\t} else if (upgrade instanceof CraftingCleanupUpgrade) {\n\t\t\t\tcraftingCleanup += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof ActionSpeedUpgrade) {\n\t\t\t\tactionSpeedUpgrade += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof ItemExtractionUpgrade) {\n\t\t\t\titemExtractionUpgrade += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof ItemStackExtractionUpgrade) {\n\t\t\t\titemStackExtractionUpgrade += inv.getStackInSlot(i).getCount();\n\t\t\t}\n\t\t\tif (upgrade instanceof IConfigPipeUpgrade) {\n\t\t\t\tguiUpgrades[i] = true;\n\t\t\t}\n\t\t}\n\t\tliquidCrafter = Math.min(liquidCrafter, ItemUpgrade.MAX_LIQUID_CRAFTER);\n\t\tcraftingCleanup = Math.min(craftingCleanup, ItemUpgrade.MAX_CRAFTING_CLEANUP);\n\t\titemExtractionUpgrade = Math.min(itemExtractionUpgrade, ItemUpgrade.MAX_ITEM_EXTRACTION);\n\t\titemStackExtractionUpgrade = Math.min(itemStackExtractionUpgrade, ItemUpgrade.MAX_ITEM_STACK_EXTRACTION);\n\t\tif (needUpdate) {\n\t\t\tMainProxy.runOnServer(null, () -> () -> {\n\t\t\t\tpipe.connectionUpdate();\n\t\t\t\tif (pipe.container != null) {\n\t\t\t\t\tpipe.container.sendUpdateToClient();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound, String prefix) {\n\t\tinternalInv.readFromNBT(nbttagcompound, \"ModuleUpgradeInventory_\" + prefix);\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound, String prefix) {\n\t\tinternalInv.writeToNBT(nbttagcompound, \"ModuleUpgradeInventory_\" + prefix);\n\t\tInventoryChanged(inv);\n\t}\n\n\tprivate boolean updateModule(int slot, IPipeUpgrade[] upgrades, IInventory inv) {\n\t\tItemStack stackInSlot = inv.getStackInSlot(slot);\n\t\tif (stackInSlot.isEmpty() || !(stackInSlot.getItem() instanceof ItemUpgrade)) {\n\t\t\tupgrades[slot] = null;\n\t\t} else {\n\t\t\tupgrades[slot] = ((ItemUpgrade) stackInSlot.getItem()).getUpgradeForItem(stackInSlot, upgrades[slot]);\n\t\t}\n\t\tif (upgrades[slot] == null) {\n\t\t\tinv.setInventorySlotContents(slot, ItemStack.EMPTY);\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn upgrades[slot].needsUpdate();\n\t\t}\n\t}\n\n\tprivate boolean removeUpgrade(int slot, IPipeUpgrade[] upgrades) {\n\t\tboolean needUpdate = upgrades[slot].needsUpdate();\n\t\tupgrades[slot] = null;\n\t\treturn needUpdate;\n\t}\n\n\tpublic boolean hasGuiUpgrade(int i) {\n\t\treturn guiUpgrades[i];\n\t}\n\n\t@Override\n\tpublic int getActionSpeedUpgrade() {\n\t\treturn actionSpeedUpgrade;\n\t}\n\n\t@Override\n\tpublic int getItemExtractionUpgrade() {\n\t\treturn itemExtractionUpgrade;\n\t}\n\n\t@Override\n\tpublic int getItemStackExtractionUpgrade() {\n\t\treturn itemStackExtractionUpgrade;\n\t}\n\n\tpublic void dropUpgrades() {\n\t\tinv.dropContents(pipe.getWorld(), pipe.getPos());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/OpaqueUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class OpaqueUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"opaque\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/PatternUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.pipes.PipeItemsSupplierLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class PatternUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"pattern\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeItemsSupplierLogistics;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn pipe instanceof ModuleActiveSupplier;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"supplier\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/PowerTransportationUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class PowerTransportationUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_transportation\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/SneakyUpgradeConfig.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport java.util.Arrays;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.ModuleCreativeTabBasedItemSink;\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.modules.ModuleModBasedItemSink;\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.modules.ModulePolymorphicItemSink;\nimport logisticspipes.network.NewGuiHandler;\nimport logisticspipes.network.abstractguis.UpgradeCoordinatesGuiProvider;\nimport logisticspipes.network.guis.upgrade.SneakyUpgradeConfigGuiProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class SneakyUpgradeConfig implements IConfigPipeUpgrade {\n\n\tpublic static final String SIDE_KEY = \"LPSNEAKY-SIDE\";\n\n\tpublic static String getName() {\n\t\treturn \"sneaky\";\n\t}\n\n\t@AllArgsConstructor\n\tpublic enum Sides {\n\t\tUP(EnumFacing.UP, \"LPSNEAKY-UP\"),\n\t\tDOWN(EnumFacing.DOWN, \"LPSNEAKY-DOWN\"),\n\t\tNORTH(EnumFacing.NORTH, \"LPSNEAKY-NORTH\"),\n\t\tSOUTH(EnumFacing.SOUTH, \"LPSNEAKY-SOUTH\"),\n\t\tEAST(EnumFacing.EAST, \"LPSNEAKY-EAST\"),\n\t\tWEST(EnumFacing.WEST, \"LPSNEAKY-WEST\");\n\n\t\t@Getter\n\t\tprivate EnumFacing dir;\n\t\t@Getter\n\t\tprivate String lpName;\n\n\t\tpublic static String getNameForDirection(EnumFacing fd) {\n\t\t\treturn Arrays.stream(values())\n\t\t\t\t\t.filter(side -> side.getDir() == fd)\n\t\t\t\t\t.map(Sides::getLpName)\n\t\t\t\t\t.findFirst()\n\t\t\t\t\t.orElse(\"LPSNEAKY-UNKNWON\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule module) {\n\t\treturn module instanceof ModuleItemSink || module instanceof ModulePolymorphicItemSink || module instanceof ModuleModBasedItemSink\n\t\t\t\t|| module instanceof ModuleOreDictItemSink || module instanceof ModuleCreativeTabBasedItemSink;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] { \"itemsink\" };\n\t}\n\n\t@Override\n\tpublic UpgradeCoordinatesGuiProvider getGUI() {\n\t\treturn NewGuiHandler.getGui(SneakyUpgradeConfigGuiProvider.class);\n\t}\n\n\t@Nullable\n\tpublic EnumFacing getSide(@Nonnull ItemStack stack) {\n\t\tif (stack.isEmpty()) return null;\n\t\tif (!stack.hasTagCompound()) {\n\t\t\tstack.setTagCompound(new NBTTagCompound());\n\t\t}\n\t\tNBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\tString sideString = tag.getString(SIDE_KEY);\n\t\treturn Arrays.stream(Sides.values())\n\t\t\t\t.filter(side -> side.getLpName().equals(sideString))\n\t\t\t\t.map(Sides::getDir)\n\t\t\t\t.findFirst()\n\t\t\t\t.orElse(null);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/SpeedUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class SpeedUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"speed\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/UpgradeManager.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport java.util.EnumSet;\nimport java.util.Objects;\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.IPipeUpgradeManager;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.items.ItemUpgrade;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.upgrades.power.BCPowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.IC2PowerSupplierUpgrade;\nimport logisticspipes.pipes.upgrades.power.RFPowerSupplierUpgrade;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.SimpleStackInventory;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class UpgradeManager implements ISimpleInventoryEventHandler, ISlotUpgradeManager, IPipeUpgradeManager {\n\n\tpublic final SimpleStackInventory inv = new SimpleStackInventory(9, \"UpgradeInventory\", 16);\n\tpublic final SimpleStackInventory sneakyInv = new SimpleStackInventory(9, \"SneakyUpgradeInventory\", 1);\n\tpublic final SimpleStackInventory secInv = new SimpleStackInventory(1, \"SecurityInventory\", 16);\n\tprivate IPipeUpgrade[] upgrades = new IPipeUpgrade[9];\n\tprivate IPipeUpgrade[] sneakyUpgrades = new IPipeUpgrade[9];\n\tprivate CoreRoutedPipe pipe;\n\tprivate int securityDelay = 0;\n\n\t/* cached attributes */\n\tprivate EnumFacing sneakyOrientation = null;\n\tprivate EnumFacing[] combinedSneakyOrientation = new EnumFacing[9];\n\tprivate int speedUpgradeCount = 0;\n\tprivate final EnumSet<EnumFacing> disconnectedSides = EnumSet.noneOf(EnumFacing.class);\n\tprivate boolean isAdvancedCrafter = false;\n\tprivate boolean isFuzzyUpgrade = false;\n\tprivate boolean isCombinedSneakyUpgrade = false;\n\tprivate int liquidCrafter = 0;\n\tprivate boolean hasByproductExtractor = false;\n\tprivate UUID uuid = null;\n\tprivate String uuidS = null;\n\tprivate boolean hasPatternUpgrade = false;\n\tprivate boolean hasPowerPassUpgrade = false;\n\tprivate boolean hasRFPowerUpgrade = false;\n\tprivate boolean hasBCPowerUpgrade = false;\n\tprivate int getIC2PowerLevel = 0;\n\tprivate boolean hasCCRemoteControlUpgrade = false;\n\tprivate boolean hasCraftingMonitoringUpgrade = false;\n\tprivate boolean hasOpaqueUpgrade = false;\n\tprivate int craftingCleanup = 0;\n\tprivate boolean hasLogicControll = false;\n\tprivate boolean hasUpgradeModuleUpgarde = false;\n\tprivate int actionSpeedUpgrade = 0;\n\tprivate int itemExtractionUpgrade = 0;\n\tprivate int itemStackExtractionUpgrade = 0;\n\n\tprivate boolean[] guiUpgrades = new boolean[18];\n\n\tprivate boolean needsContainerPositionUpdate = false;\n\n\tpublic UpgradeManager(CoreRoutedPipe pipe) {\n\t\tthis.pipe = pipe;\n\t\tinv.addListener(this);\n\t\tsneakyInv.addListener(this);\n\t\tsecInv.addListener(this);\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tinv.readFromNBT(nbttagcompound, \"UpgradeInventory_\");\n\t\tsneakyInv.readFromNBT(nbttagcompound, \"SneakyUpgradeInventory_\");\n\t\tsecInv.readFromNBT(nbttagcompound, \"SecurityInventory_\");\n\n\t\tif (!sneakyInv.getStackInSlot(8).isEmpty()) {\n\t\t\tif (sneakyInv.getStackInSlot(8).getItem() == LPItems.itemCard && sneakyInv.getStackInSlot(8).getItemDamage() == LogisticsItemCard.SEC_CARD) {\n\t\t\t\tsecInv.setInventorySlotContents(0, sneakyInv.getStackInSlot(8));\n\t\t\t\tsneakyInv.setInventorySlotContents(8, ItemStack.EMPTY);\n\t\t\t}\n\t\t}\n\n\t\tInventoryChanged(inv);\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tinv.writeToNBT(nbttagcompound, \"UpgradeInventory_\");\n\t\tsneakyInv.writeToNBT(nbttagcompound, \"SneakyUpgradeInventory_\");\n\t\tsecInv.writeToNBT(nbttagcompound, \"SecurityInventory_\");\n\t\tInventoryChanged(inv);\n\t}\n\n\tprivate boolean updateModule(int slot, IPipeUpgrade[] upgrades, IInventory inv) {\n\t\tItemStack stack = inv.getStackInSlot(slot);\n\t\tif (stack.getItem() instanceof ItemUpgrade) {\n\t\t\tupgrades[slot] = ((ItemUpgrade) stack.getItem()).getUpgradeForItem(stack, upgrades[slot]);\n\t\t} else {\n\t\t\tupgrades[slot] = null;\n\t\t}\n\t\tif (upgrades[slot] == null) {\n\t\t\tinv.setInventorySlotContents(slot, ItemStack.EMPTY);\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn upgrades[slot].needsUpdate();\n\t\t}\n\t}\n\n\tprivate boolean removeUpgrade(int slot, IPipeUpgrade[] upgrades) {\n\t\tboolean needUpdate = upgrades[slot].needsUpdate();\n\t\tupgrades[slot] = null;\n\t\treturn needUpdate;\n\t}\n\n\t@Override\n\tpublic void InventoryChanged(IInventory inventory) {\n\t\tboolean needUpdate = false;\n\t\tfor (int i = 0; i < inv.getSizeInventory(); i++) {\n\t\t\tItemStack item = inv.getStackInSlot(i);\n\t\t\tif (!item.isEmpty()) {\n\t\t\t\tneedUpdate |= updateModule(i, upgrades, inv);\n\t\t\t} else if (upgrades[i] != null) {\n\t\t\t\tneedUpdate |= removeUpgrade(i, upgrades);\n\t\t\t}\n\t\t}\n\t\t//update sneaky direction, speed upgrade count and disconnection\n\t\tsneakyOrientation = null;\n\t\tspeedUpgradeCount = 0;\n\t\tisAdvancedCrafter = false;\n\t\tisFuzzyUpgrade = false;\n\t\tboolean combinedBuffer = isCombinedSneakyUpgrade;\n\t\tisCombinedSneakyUpgrade = false;\n\t\tliquidCrafter = 0;\n\t\tdisconnectedSides.clear();\n\t\thasByproductExtractor = false;\n\t\thasPatternUpgrade = false;\n\t\thasPowerPassUpgrade = false;\n\t\thasRFPowerUpgrade = false;\n\t\thasBCPowerUpgrade = false;\n\t\tgetIC2PowerLevel = 0;\n\t\thasCCRemoteControlUpgrade = false;\n\t\thasCraftingMonitoringUpgrade = false;\n\t\thasOpaqueUpgrade = false;\n\t\tcraftingCleanup = 0;\n\t\thasLogicControll = false;\n\t\thasUpgradeModuleUpgarde = false;\n\t\tactionSpeedUpgrade = 0;\n\t\titemExtractionUpgrade = 0;\n\t\titemStackExtractionUpgrade = 0;\n\n\t\tguiUpgrades = new boolean[18];\n\t\tfor (int i = 0; i < upgrades.length; i++) {\n\t\t\tIPipeUpgrade upgrade = upgrades[i];\n\t\t\tif (upgrade instanceof SneakyUpgradeConfig && sneakyOrientation == null && !isCombinedSneakyUpgrade) {\n\t\t\t\tsneakyOrientation = ((SneakyUpgradeConfig) upgrade).getSide(getInv().getStackInSlot(i));\n\t\t\t} else if (upgrade instanceof SpeedUpgrade) {\n\t\t\t\tspeedUpgradeCount += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof ConnectionUpgradeConfig) {\n\t\t\t\t((ConnectionUpgradeConfig) upgrade).getSides(getInv().getStackInSlot(i)).forEach(disconnectedSides::add);\n\t\t\t} else if (upgrade instanceof AdvancedSatelliteUpgrade) {\n\t\t\t\tisAdvancedCrafter = true;\n\t\t\t} else if (upgrade instanceof FuzzyUpgrade) {\n\t\t\t\tisFuzzyUpgrade = true;\n\t\t\t} else if (upgrade instanceof CombinedSneakyUpgrade && sneakyOrientation == null) {\n\t\t\t\tisCombinedSneakyUpgrade = true;\n\t\t\t} else if (upgrade instanceof FluidCraftingUpgrade) {\n\t\t\t\tliquidCrafter += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof CraftingByproductUpgrade) {\n\t\t\t\thasByproductExtractor = true;\n\t\t\t} else if (upgrade instanceof PatternUpgrade) {\n\t\t\t\thasPatternUpgrade = true;\n\t\t\t} else if (upgrade instanceof PowerTransportationUpgrade) {\n\t\t\t\thasPowerPassUpgrade = true;\n\t\t\t} else if (upgrade instanceof RFPowerSupplierUpgrade) {\n\t\t\t\thasRFPowerUpgrade = true;\n\t\t\t} else if (upgrade instanceof BCPowerSupplierUpgrade) {\n\t\t\t\thasBCPowerUpgrade = true;\n\t\t\t} else if (upgrade instanceof IC2PowerSupplierUpgrade) {\n\t\t\t\tgetIC2PowerLevel = Math.max(getIC2PowerLevel, ((IC2PowerSupplierUpgrade) upgrade).getPowerLevel());\n\t\t\t} else if (upgrade instanceof CCRemoteControlUpgrade) {\n\t\t\t\thasCCRemoteControlUpgrade = true;\n\t\t\t} else if (upgrade instanceof CraftingMonitoringUpgrade) {\n\t\t\t\thasCraftingMonitoringUpgrade = true;\n\t\t\t} else if (upgrade instanceof OpaqueUpgrade) {\n\t\t\t\thasOpaqueUpgrade = true;\n\t\t\t} else if (upgrade instanceof CraftingCleanupUpgrade) {\n\t\t\t\tcraftingCleanup += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof LogicControllerUpgrade) {\n\t\t\t\thasLogicControll = true;\n\t\t\t} else if (upgrade instanceof UpgradeModuleUpgrade) {\n\t\t\t\thasUpgradeModuleUpgarde = true;\n\t\t\t} else if (upgrade instanceof ActionSpeedUpgrade) {\n\t\t\t\tactionSpeedUpgrade += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof ItemExtractionUpgrade) {\n\t\t\t\titemExtractionUpgrade += inv.getStackInSlot(i).getCount();\n\t\t\t} else if (upgrade instanceof ItemStackExtractionUpgrade) {\n\t\t\t\titemStackExtractionUpgrade += inv.getStackInSlot(i).getCount();\n\t\t\t}\n\t\t\tif (upgrade instanceof IConfigPipeUpgrade) {\n\t\t\t\tguiUpgrades[i] = true;\n\t\t\t}\n\t\t}\n\t\tliquidCrafter = Math.min(liquidCrafter, ItemUpgrade.MAX_LIQUID_CRAFTER);\n\t\tcraftingCleanup = Math.min(craftingCleanup, ItemUpgrade.MAX_CRAFTING_CLEANUP);\n\t\titemExtractionUpgrade = Math.min(itemExtractionUpgrade, ItemUpgrade.MAX_ITEM_EXTRACTION);\n\t\titemStackExtractionUpgrade = Math.min(itemStackExtractionUpgrade, ItemUpgrade.MAX_ITEM_STACK_EXTRACTION);\n\t\tif (combinedBuffer != isCombinedSneakyUpgrade) {\n\t\t\tneedsContainerPositionUpdate = true;\n\t\t}\n\t\tfor (int i = 0; i < sneakyInv.getSizeInventory(); i++) {\n\t\t\tItemStack item = sneakyInv.getStackInSlot(i);\n\t\t\tif (!item.isEmpty()) {\n\t\t\t\tneedUpdate |= updateModule(i, sneakyUpgrades, sneakyInv);\n\t\t\t} else if (sneakyUpgrades[i] != null) {\n\t\t\t\tneedUpdate |= removeUpgrade(i, sneakyUpgrades);\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < sneakyUpgrades.length; i++) {\n\t\t\tIPipeUpgrade upgrade = sneakyUpgrades[i];\n\t\t\tif (upgrade instanceof SneakyUpgradeConfig) {\n\t\t\t\tItemStack stack = sneakyInv.getStackInSlot(i);\n\t\t\t\tcombinedSneakyOrientation[i] = ((SneakyUpgradeConfig) upgrade).getSide(stack);\n\t\t\t}\n\t\t\tif (upgrade instanceof IConfigPipeUpgrade) {\n\t\t\t\tguiUpgrades[i + 9] = true;\n\t\t\t}\n\t\t}\n\t\tif (needUpdate) {\n\t\t\tMainProxy.runOnServer(null, () -> () -> {\n\t\t\t\tpipe.connectionUpdate();\n\t\t\t\tif (pipe.container != null) {\n\t\t\t\t\tpipe.container.sendUpdateToClient();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tuuid = null;\n\t\tuuidS = null;\n\t\tItemStack stack = secInv.getStackInSlot(0);\n\t\tif (stack.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tif (stack.getItem() != LPItems.itemCard || stack.getItemDamage() != LogisticsItemCard.SEC_CARD) {\n\t\t\treturn;\n\t\t}\n\t\tif (!stack.hasTagCompound()) {\n\t\t\treturn;\n\t\t}\n\t\tif (!stack.getTagCompound().hasKey(\"UUID\")) {\n\t\t\treturn;\n\t\t}\n\t\tuuid = UUID.fromString(stack.getTagCompound().getString(\"UUID\"));\n\t\tuuidS = uuid.toString();\n\t}\n\n\t/* Special implementations */\n\n\t@Override\n\tpublic boolean hasSneakyUpgrade() {\n\t\treturn sneakyOrientation != null;\n\t}\n\n\t@Override\n\tpublic EnumFacing getSneakyOrientation() {\n\t\treturn sneakyOrientation;\n\t}\n\n\t@Override\n\tpublic int getSpeedUpgradeCount() {\n\t\treturn speedUpgradeCount;\n\t}\n\n\t@Override\n\tpublic boolean hasCombinedSneakyUpgrade() {\n\t\treturn isCombinedSneakyUpgrade;\n\t}\n\n\t@Override\n\tpublic EnumFacing[] getCombinedSneakyOrientation() {\n\t\treturn combinedSneakyOrientation;\n\t}\n\n\tpublic IGuiOpenControler getGuiController() {\n\t\treturn new IGuiOpenControler() {\n\n\t\t\tPlayerCollectionList players = new PlayerCollectionList();\n\n\t\t\t@Override\n\t\t\tpublic void guiOpenedByPlayer(EntityPlayer player) {\n\t\t\t\tplayers.add(player);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void guiClosedByPlayer(EntityPlayer player) {\n\t\t\t\tplayers.remove(player);\n\t\t\t\tif (players.isEmpty() && !isCombinedSneakyUpgrade) {\n\t\t\t\t\tsneakyInv.dropContents(pipe.getWorld(), pipe.getPos());\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic boolean isNeedingContainerUpdate() {\n\t\tboolean tmp = needsContainerPositionUpdate;\n\t\tneedsContainerPositionUpdate = false;\n\t\treturn tmp;\n\t}\n\n\tpublic void dropUpgrades() {\n\t\tinv.dropContents(pipe.getWorld(), pipe.getPos());\n\t\tsneakyInv.dropContents(pipe.getWorld(), pipe.getPos());\n\t}\n\n\t@Override\n\tpublic boolean isSideDisconnected(EnumFacing side) {\n\t\treturn disconnectedSides.contains(side);\n\t}\n\n\tpublic boolean tryIserting(World world, EntityPlayer entityplayer) {\n\t\tItemStack itemStackInMainHand = entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND);\n\t\tif (!itemStackInMainHand.isEmpty() && itemStackInMainHand.getItem() instanceof ItemUpgrade) {\n\t\t\tif (MainProxy.isClient(world)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tIPipeUpgrade upgrade = ((ItemUpgrade) itemStackInMainHand.getItem()).getUpgradeForItem(itemStackInMainHand, null);\n\t\t\tif (upgrade.isAllowedForPipe(pipe)) {\n\t\t\t\tif (isCombinedSneakyUpgrade) {\n\t\t\t\t\tif (upgrade instanceof SneakyUpgradeConfig) {\n\t\t\t\t\t\tif (insertIntInv(entityplayer, sneakyInv)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (insertIntInv(entityplayer, inv)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!itemStackInMainHand.isEmpty() && itemStackInMainHand.getItem() == LPItems.itemCard && itemStackInMainHand.getItemDamage() == LogisticsItemCard.SEC_CARD) {\n\t\t\tif (MainProxy.isClient(world)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (secInv.getStackInSlot(0).isEmpty()) {\n\t\t\t\tItemStack newItem = itemStackInMainHand.splitStack(1);\n\t\t\t\tsecInv.setInventorySlotContents(0, newItem);\n\t\t\t\tInventoryChanged(secInv);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean insertIntInv(EntityPlayer entityplayer, SimpleStackInventory inv) {\n\t\tfor (int i = 0; i < inv.getSizeInventory(); i++) {\n\t\t\tItemStack item = inv.getStackInSlot(i);\n\t\t\tif (item.isEmpty()) {\n\t\t\t\tinv.setInventorySlotContents(i, entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).splitStack(1));\n\t\t\t\tInventoryChanged(inv);\n\t\t\t\treturn true;\n\t\t\t} else if (ItemIdentifier.get(item).equals(ItemIdentifier.get(entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND)))) {\n\t\t\t\tif (item.getCount() < inv.getInventoryStackLimit()) {\n\t\t\t\t\titem.grow(1);\n\t\t\t\t\tentityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).splitStack(1);\n\t\t\t\t\tinv.setInventorySlotContents(i, item);\n\t\t\t\t\tInventoryChanged(inv);\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic UUID getSecurityID() {\n\t\treturn uuid;\n\t}\n\n\tpublic void insetSecurityID(UUID id) {\n\t\tItemStack stack = new ItemStack(LPItems.itemCard, 1, LogisticsItemCard.SEC_CARD);\n\t\tstack.setTagCompound(new NBTTagCompound());\n\t\tfinal NBTTagCompound tag = Objects.requireNonNull(stack.getTagCompound());\n\t\ttag.setString(\"UUID\", id.toString());\n\t\tsecInv.setInventorySlotContents(0, stack);\n\t\tInventoryChanged(secInv);\n\t}\n\n\tpublic void securityTick() {\n\t\tif ((getSecurityID()) != null) {\n\t\t\tif (!SimpleServiceLocator.securityStationManager.isAuthorized(uuidS)) {\n\t\t\t\tsecurityDelay++;\n\t\t\t} else {\n\t\t\t\tsecurityDelay = 0;\n\t\t\t}\n\t\t\tif (securityDelay > 20) {\n\t\t\t\tsecInv.clearInventorySlotContents(0);\n\t\t\t\tInventoryChanged(secInv);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isAdvancedSatelliteCrafter() {\n\t\treturn isAdvancedCrafter;\n\t}\n\n\t@Override\n\tpublic boolean isFuzzyUpgrade() {\n\t\treturn isFuzzyUpgrade;\n\t}\n\n\t@Override\n\tpublic int getFluidCrafter() {\n\t\treturn liquidCrafter;\n\t}\n\n\t@Override\n\tpublic boolean hasByproductExtractor() {\n\t\treturn hasByproductExtractor;\n\t}\n\n\t@Override\n\tpublic boolean hasPatternUpgrade() {\n\t\treturn hasPatternUpgrade;\n\t}\n\n\t@Override\n\tpublic boolean hasPowerPassUpgrade() {\n\t\treturn hasPowerPassUpgrade || hasRFPowerUpgrade || hasBCPowerUpgrade || getIC2PowerLevel > 0;\n\t}\n\n\t@Override\n\tpublic boolean hasRFPowerSupplierUpgrade() {\n\t\treturn hasRFPowerUpgrade;\n\t}\n\n\t@Override\n\tpublic boolean hasBCPowerSupplierUpgrade() {\n\t\treturn hasBCPowerUpgrade;\n\t}\n\n\t@Override\n\tpublic int getIC2PowerLevel() {\n\t\treturn getIC2PowerLevel;\n\t}\n\n\t@Override\n\tpublic boolean hasCCRemoteControlUpgrade() {\n\t\treturn hasCCRemoteControlUpgrade;\n\t}\n\n\t@Override\n\tpublic boolean hasCraftingMonitoringUpgrade() {\n\t\treturn hasCraftingMonitoringUpgrade;\n\t}\n\n\t@Override\n\tpublic boolean isOpaque() {\n\t\treturn hasOpaqueUpgrade;\n\t}\n\n\t@Override\n\tpublic int getCrafterCleanup() {\n\t\treturn craftingCleanup;\n\t}\n\n\tpublic boolean hasLogicControll() {\n\t\treturn hasLogicControll;\n\t}\n\n\t@Override\n\tpublic boolean hasUpgradeModuleUpgrade() {\n\t\treturn hasUpgradeModuleUpgarde;\n\t}\n\n\t@Override\n\tpublic boolean hasOwnSneakyUpgrade() {\n\t\treturn false;\n\t}\n\n\tpublic boolean hasGuiUpgrade(int i) {\n\t\treturn guiUpgrades[i];\n\t}\n\n\tpublic IPipeUpgrade getUpgrade(int i) {\n\t\tif (i < upgrades.length) {\n\t\t\treturn upgrades[i];\n\t\t} else {\n\t\t\treturn sneakyUpgrades[i - upgrades.length];\n\t\t}\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getPipePosition() {\n\t\treturn pipe.getLPPosition();\n\t}\n\n\t@Override\n\tpublic int getActionSpeedUpgrade() {\n\t\treturn actionSpeedUpgrade;\n\t}\n\n\t@Override\n\tpublic int getItemExtractionUpgrade() {\n\t\treturn itemExtractionUpgrade;\n\t}\n\n\t@Override\n\tpublic int getItemStackExtractionUpgrade() {\n\t\treturn itemStackExtractionUpgrade;\n\t}\n\n\t@Override\n\tpublic SimpleStackInventory getInv() {\n\t\treturn this.inv;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/UpgradeModuleUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic class UpgradeModuleUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"module_upgrade\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn pipe instanceof PipeLogisticsChassis;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"chassis\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/BCPowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\n\npublic class BCPowerSupplierUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_supplier_mj\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/IC2EVPowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\npublic class IC2EVPowerSupplierUpgrade extends IC2PowerSupplierUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_supplier_eu_ev\";\n\t}\n\n\t@Override\n\tpublic int getPowerLevel() {\n\t\treturn 2048;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/IC2HVPowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\npublic class IC2HVPowerSupplierUpgrade extends IC2PowerSupplierUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_supplier_eu_hv\";\n\t}\n\n\t@Override\n\tpublic int getPowerLevel() {\n\t\treturn 512;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/IC2LVPowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\npublic class IC2LVPowerSupplierUpgrade extends IC2PowerSupplierUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_supplier_eu_lv\";\n\t}\n\n\t@Override\n\tpublic int getPowerLevel() {\n\t\treturn 32;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/IC2MVPowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\npublic class IC2MVPowerSupplierUpgrade extends IC2PowerSupplierUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_supplier_eu_mv\";\n\t}\n\n\t@Override\n\tpublic int getPowerLevel() {\n\t\treturn 128;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/IC2PowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\n\npublic abstract class IC2PowerSupplierUpgrade implements IPipeUpgrade {\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n\n\tpublic abstract int getPowerLevel();\n}\n"
  },
  {
    "path": "common/logisticspipes/pipes/upgrades/power/RFPowerSupplierUpgrade.java",
    "content": "package logisticspipes.pipes.upgrades.power;\n\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\n\npublic class RFPowerSupplierUpgrade implements IPipeUpgrade {\n\n\tpublic static String getName() {\n\t\treturn \"power_supplier_rf\";\n\t}\n\n\t@Override\n\tpublic boolean needsUpdate() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForPipe(CoreRoutedPipe pipe) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAllowedForModule(LogisticsModule pipe) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic String[] getAllowedPipes() {\n\t\treturn new String[] { \"all\" };\n\t}\n\n\t@Override\n\tpublic String[] getAllowedModules() {\n\t\treturn new String[] {};\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ConfigToolHandler.java",
    "content": "package logisticspipes.proxy;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.api.ILPPipeConfigTool;\nimport logisticspipes.api.ILPPipeTile;\nimport logisticspipes.asm.wrapper.LogisticsWrapperHandler;\nimport logisticspipes.proxy.buildcraft.BuildCraftToolWrench;\nimport logisticspipes.proxy.cofh.CoFHToolHammer;\nimport logisticspipes.proxy.interfaces.ILPPipeConfigToolWrapper;\n\npublic class ConfigToolHandler {\n\n\tpublic List<ILPPipeConfigToolWrapper> wrappers = new ArrayList<>();\n\n\tpublic boolean canWrench(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\tif (wrench.isEmpty()) return false;\n\t\tif (wrench.getItem() instanceof ILPPipeConfigTool) {\n\t\t\treturn ((ILPPipeConfigTool) wrench.getItem()).canWrench(player, wrench, pipe);\n\t\t}\n\t\tfor (ILPPipeConfigToolWrapper wrapper : wrappers) {\n\t\t\tILPPipeConfigTool wrapped = wrapper.getWrappedTool(wrench);\n\t\t\tif (wrapped != null) {\n\t\t\t\treturn wrapped.canWrench(player, wrench, pipe);\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void wrenchUsed(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\tif (wrench.isEmpty()) return;\n\t\tif (wrench.getItem() instanceof ILPPipeConfigTool) {\n\t\t\t((ILPPipeConfigTool) wrench.getItem()).wrenchUsed(player, wrench, pipe);\n\t\t\treturn;\n\t\t}\n\t\tfor (ILPPipeConfigToolWrapper wrapper : wrappers) {\n\t\t\tILPPipeConfigTool wrapped = wrapper.getWrappedTool(wrench);\n\t\t\tif (wrapped != null) {\n\t\t\t\twrapped.wrenchUsed(player, wrench, pipe);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tvoid registerWrapper() {\n\t\twrappers.add(LogisticsWrapperHandler.getWrappedPipeConfigToolWrapper(\"buildcraft.api.tools.IToolWrench\", \"BuildCraft\", BuildCraftToolWrench.class));\n\t\twrappers.add(LogisticsWrapperHandler.getWrappedPipeConfigToolWrapper(\"cofh.api.item.IToolHammer\", \"CoFH\", CoFHToolHammer.class));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/DontLoadProxy.java",
    "content": "package logisticspipes.proxy;\n\npublic class DontLoadProxy extends RuntimeException {\n\n\tprivate static final long serialVersionUID = -6475338000706884730L;\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/MainProxy.java",
    "content": "package logisticspipes.proxy;\n\nimport java.util.EnumMap;\nimport java.util.Map;\nimport java.util.WeakHashMap;\nimport java.util.function.Supplier;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.ChunkPos;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\nimport net.minecraft.world.WorldServer;\n\nimport net.minecraftforge.common.DimensionManager;\nimport net.minecraftforge.common.util.FakePlayer;\nimport net.minecraftforge.event.world.WorldEvent;\nimport net.minecraftforge.fml.common.SidedProxy;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.network.FMLEmbeddedChannel;\nimport net.minecraftforge.fml.common.network.FMLOutboundHandler;\nimport net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget;\nimport net.minecraftforge.fml.common.network.NetworkRegistry;\nimport net.minecraftforge.fml.relauncher.Side;\n\nimport com.google.common.collect.Maps;\nimport lombok.Getter;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.LogisticsEventListener;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.entity.FakePlayerLP;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.PacketInboundHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.proxy.interfaces.IProxy;\nimport logisticspipes.routing.debug.RoutingTableDebugUpdateThread;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.ticks.RoutingTableUpdateThread;\nimport logisticspipes.utils.PlayerCollectionList;\n\npublic class MainProxy {\n\n\tprivate MainProxy() {}\n\n\t@SidedProxy(clientSide = \"logisticspipes.proxy.side.ClientProxy\", serverSide = \"logisticspipes.proxy.side.ServerProxy\")\n\tpublic static IProxy proxy;\n\t@Getter\n\tprivate static int globalTick;\n\tpublic static EnumMap<Side, FMLEmbeddedChannel> channels;\n\n\tprivate static final WeakHashMap<Thread, Side> threadSideMap = new WeakHashMap<>();\n\tprivate static final Map<Integer, FakePlayerLP> fakePlayers = Maps.newHashMap();\n\n\tpublic static final String networkChannelName = \"LogisticsPipes\";\n\n\tprivate static Side getEffectiveSide() {\n\t\tThread thr = Thread.currentThread();\n\t\tif (MainProxy.threadSideMap.containsKey(thr)) {\n\t\t\treturn MainProxy.threadSideMap.get(thr);\n\t\t}\n\t\tSide side = MainProxy.getEffectiveSide(thr);\n\t\tif (MainProxy.threadSideMap.size() > 50) {\n\t\t\tMainProxy.threadSideMap.clear();\n\t\t}\n\t\tMainProxy.threadSideMap.put(thr, side);\n\t\treturn side;\n\t}\n\n\tprivate static Side getEffectiveSide(Thread thr) {\n\t\tif (thr.getName().equals(\"Server thread\") || (thr instanceof RoutingTableUpdateThread) || (thr instanceof RoutingTableDebugUpdateThread)) {\n\t\t\treturn Side.SERVER;\n\t\t}\n\t\tif (SimpleServiceLocator.ccProxy != null && SimpleServiceLocator.ccProxy.isLuaThread(thr)) {\n\t\t\treturn Side.SERVER;\n\t\t}\n\t\treturn Side.CLIENT;\n\t}\n\n\tpublic static boolean isClient(IBlockAccess blockAccess) {\n\t\tif (blockAccess instanceof World) {\n\t\t\tWorld world = (World) blockAccess;\n\t\t\ttry {\n\t\t\t\treturn world.isRemote;\n\t\t\t} catch (NullPointerException n) {\n\t\t\t\tLogisticsPipes.log.fatal(\"isClient called with a null world - using slow thread based fallback\");\n\t\t\t\tn.printStackTrace();\n\t\t\t}\n\t\t}\n\t\treturn MainProxy.isClient();\n\t}\n\n\t/**\n\t * isClient is slow, find a world and check isClient(world)\n\t */\n\t@Deprecated\n\tpublic static boolean isClient() {\n\t\treturn MainProxy.getEffectiveSide() == Side.CLIENT;\n\t}\n\n\tpublic static boolean isServer(IBlockAccess blockAccess) {\n\t\tif (blockAccess instanceof World) {\n\t\t\tWorld world = (World) blockAccess;\n\t\t\ttry {\n\t\t\t\treturn !world.isRemote;\n\t\t\t} catch (NullPointerException n) {\n\t\t\t\tLogisticsPipes.log.fatal(\"isServer called with a null world - using slow thread based fallback\");\n\t\t\t\tn.printStackTrace();\n\t\t\t}\n\t\t}\n\t\treturn MainProxy.isServer();\n\t}\n\n\t/**\n\t * isServer is slow, find a world and check isServer(world)\n\t */\n\t@Deprecated\n\tpublic static boolean isServer() {\n\t\treturn MainProxy.getEffectiveSide() == Side.SERVER;\n\t}\n\n\t/**\n\t * Simple function to run code on the server and which can be replaced by the DistExecutor later.\n\t */\n\tpublic static void runOnServer(@Nullable IBlockAccess world, @Nonnull Supplier<Runnable> runnableConsumer) {\n\t\tif (isServer(world)) runnableConsumer.get().run();\n\t}\n\n\tpublic static void runOnClient(@Nullable IBlockAccess world, @Nonnull Supplier<Runnable> runnableConsumer) {\n\t\tif (isClient(world)) runnableConsumer.get().run();\n\t}\n\n\tpublic static World getClientMainWorld() {\n\t\treturn MainProxy.proxy.getWorld();\n\t}\n\n\tpublic static void createChannels() {\n\t\tMainProxy.channels = NetworkRegistry.INSTANCE.newChannel(MainProxy.networkChannelName, new PacketHandler());\n\t\tfor (Side side : Side.values()) {\n\t\t\tFMLEmbeddedChannel channel = MainProxy.channels.get(side);\n\t\t\tString type = channel.findChannelHandlerNameForType(PacketHandler.class);\n\t\t\tchannel.pipeline().addAfter(type, PacketInboundHandler.class.getName(), new PacketInboundHandler());\n\t\t}\n\t}\n\n\tpublic static void sendPacketToServer(ModernPacket packet) {\n\t\tif (MainProxy.isServer()) {\n\t\t\tSystem.err.println(\"sendPacketToServer called serverside !\");\n\t\t\tnew Exception().printStackTrace();\n\t\t\treturn;\n\t\t}\n\t\tif (packet.isCompressable() || MainProxy.needsToBeCompressed(packet)) {\n\t\t\tSimpleServiceLocator.clientBufferHandler.addPacketToCompressor(packet);\n\t\t} else {\n\t\t\tMainProxy.channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(OutboundTarget.TOSERVER);\n\t\t\tMainProxy.channels.get(Side.CLIENT).writeOutbound(packet);\n\t\t}\n\t}\n\n\tpublic static void sendPacketToPlayer(ModernPacket packet, EntityPlayer player) {\n\t\tif (!MainProxy.isServer(player.world)) {\n\t\t\tSystem.err.println(\"sendPacketToPlayer called clientside !\");\n\t\t\tnew Exception().printStackTrace();\n\t\t\treturn;\n\t\t}\n\t\tif (packet.isCompressable() || MainProxy.needsToBeCompressed(packet)) {\n\t\t\tSimpleServiceLocator.serverBufferHandler.addPacketToCompressor(packet, player);\n\t\t} else {\n\t\t\tMainProxy.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);\n\t\t\tMainProxy.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);\n\t\t\tMainProxy.channels.get(Side.SERVER).writeOutbound(packet);\n\t\t}\n\t}\n\n\t// ignores dimension; more stringent check done inside sendPacketToAllWatching\n\tpublic static boolean isAnyoneWatching(BlockPos pos, int dimensionID) {\n\t\treturn isAnyoneWatching(pos.getX(), pos.getZ(), dimensionID);\n\t}\n\n\t// ignores dimension; more stringent check done inside sendPacketToAllWatching\n\tpublic static boolean isAnyoneWatching(int X, int Z, int dimensionID) {\n\t\tChunkPos chunk = new ChunkPos(X >> 4, Z >> 4);\n\t\tPlayerCollectionList players = LogisticsEventListener.watcherList.get(chunk);\n\t\tif (players == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn !players.isEmptyWithoutCheck();\n\t}\n\n\tpublic static void sendPacketToAllWatchingChunk(LogisticsModule module, ModernPacket packet) {\n\t\tif (module.getSlot().isInWorld()) {\n\t\t\tfinal World world = module.getWorld();\n\t\t\tif (world == null) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tthrow new IllegalStateException(\"sendPacketToAllWatchingChunk called without a world provider on the module\");\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinal BlockPos pos = module.getBlockPos();\n\t\t\tsendPacketToAllWatchingChunk(pos.getX(), pos.getZ(), world.provider.getDimension(), packet);\n\t\t} else {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tthrow new IllegalStateException(\"sendPacketToAllWatchingChunk for module in hand was called\");\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void sendPacketToAllWatchingChunk(TileEntity tile, ModernPacket packet) {\n\t\tsendPacketToAllWatchingChunk(tile.getPos().getX(), tile.getPos().getZ(), tile.getWorld().provider.getDimension(), packet);\n\t}\n\n\tpublic static void sendPacketToAllWatchingChunk(int X, int Z, int dimensionId, ModernPacket packet) {\n\t\tif (!MainProxy.isServer()) {\n\t\t\tSystem.err.println(\"sendPacketToAllWatchingChunk called clientside !\");\n\t\t\tnew Exception().printStackTrace();\n\t\t\treturn;\n\t\t}\n\t\tChunkPos chunk = new ChunkPos(X >> 4, Z >> 4);\n\t\tPlayerCollectionList players = LogisticsEventListener.watcherList.get(chunk);\n\t\tif (players != null) {\n\t\t\tfor (EntityPlayer player : players.players()) {\n\t\t\t\tif (player.world.provider.getDimension() == dimensionId) {\n\t\t\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void sendToPlayerList(ModernPacket packet, PlayerCollectionList players) {\n\t\tif (players.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tsendToPlayerList(packet, players.players());\n\t}\n\n\tpublic static void sendToPlayerList(ModernPacket packet, Iterable<EntityPlayer> players) {\n\n\t\tif (!MainProxy.isServer()) {\n\t\t\tSystem.err.println(\"sendToPlayerList called clientside !\");\n\t\t\tnew Exception().printStackTrace();\n\t\t\treturn;\n\t\t}\n\t\tif (packet.isCompressable() || MainProxy.needsToBeCompressed(packet)) {\n\t\t\tfor (EntityPlayer player : players) {\n\t\t\t\tSimpleServiceLocator.serverBufferHandler.addPacketToCompressor(packet, player);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (EntityPlayer player : players) {\n\t\t\t\tMainProxy.sendPacketToPlayer(packet, player);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void sendToPlayerList(ModernPacket packet, Stream<EntityPlayer> players) {\n\t\tif (!MainProxy.isServer()) {\n\t\t\tSystem.err.println(\"sendToPlayerList called clientside !\");\n\t\t\tnew Exception().printStackTrace();\n\t\t\treturn;\n\t\t}\n\t\tif (packet.isCompressable() || MainProxy.needsToBeCompressed(packet)) {\n\t\t\tplayers.forEach(player -> SimpleServiceLocator.serverBufferHandler.addPacketToCompressor(packet, player));\n\t\t} else {\n\t\t\tplayers.forEach(player -> MainProxy.sendPacketToPlayer(packet, player));\n\t\t}\n\t}\n\n\tpublic static void sendToAllPlayers(ModernPacket packet) {\n\t\tif (!MainProxy.isServer()) {\n\t\t\tSystem.err.println(\"sendToAllPlayers called clientside !\");\n\t\t\tnew Exception().printStackTrace();\n\t\t\treturn;\n\t\t}\n\t\tif (packet.isCompressable() || MainProxy.needsToBeCompressed(packet)) {\n\t\t\tfor (World world : DimensionManager.getWorlds()) {\n\t\t\t\tfor (Object playerObject : world.playerEntities) {\n\t\t\t\t\tEntityPlayer player = (EntityPlayer) playerObject;\n\t\t\t\t\tSimpleServiceLocator.serverBufferHandler.addPacketToCompressor(packet, player);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tMainProxy.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);\n\t\t\tMainProxy.channels.get(Side.SERVER).writeOutbound(packet);\n\t\t}\n\t}\n\n\tprivate static boolean needsToBeCompressed(ModernPacket packet) {\n\t\t/*if(packet.getData() != null) {\n\t\t\tif(packet.getData().length > 32767) {\n\t\t\t\treturn true; // Packet is to big\n\t\t\t}\n\t\t}*/\n\t\treturn false;\n\t}\n\n\tpublic static FakePlayer getFakePlayer(World world) {\n\t\tint dimId = world.provider.getDimension();\n\t\tif (fakePlayers.containsKey(dimId))\n\t\t\treturn fakePlayers.get(dimId);\n\t\tif (world instanceof WorldServer) {\n\t\t\tFakePlayerLP fp = new FakePlayerLP((WorldServer) world);\n\t\t\tfakePlayers.put(dimId, fp);\n\t\t\treturn fp;\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic static void addTick() {\n\t\tMainProxy.globalTick++;\n\t}\n\n\tpublic static EntityItem dropItems(World world, @Nonnull ItemStack stack, int xCoord, int yCoord, int zCoord) {\n\t\tEntityItem item = new EntityItem(world, xCoord, yCoord, zCoord, stack);\n\t\tworld.spawnEntity(item);\n\t\treturn item;\n\t}\n\n\tpublic static boolean checkPipesConnections(TileEntity from, TileEntity to, EnumFacing way) {\n\t\treturn MainProxy.checkPipesConnections(from, to, way, false);\n\t}\n\n\tpublic static boolean checkPipesConnections(TileEntity from, TileEntity to, EnumFacing way, boolean ignoreSystemDisconnection) {\n\t\tif (from == null || to == null) {\n\t\t\treturn false;\n\t\t}\n\t\tIPipeInformationProvider fromInfo = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(from);\n\t\tIPipeInformationProvider toInfo = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(to);\n\t\tif (fromInfo == null && toInfo == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (fromInfo != null) {\n\t\t\tif (!fromInfo.canConnect(to, way, ignoreSystemDisconnection)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif (toInfo != null) {\n\t\t\treturn toInfo.canConnect(from, way.getOpposite(), ignoreSystemDisconnection);\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic static boolean isPipeControllerEquipped(EntityPlayer entityplayer) {\n\t\treturn entityplayer != null &&\n\t\t\t\t!entityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).isEmpty() &&\n\t\t\t\tentityplayer.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND).getItem() == LPItems.pipeController;\n\t}\n\n\t@SubscribeEvent\n\tpublic static void onWorldUnload(WorldEvent.Unload event) {\n\t\tfakePlayers.entrySet().removeIf(entry -> entry.getValue().world == event.getWorld());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/PowerProxy.java",
    "content": "package logisticspipes.proxy;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.energy.CapabilityEnergy;\nimport net.minecraftforge.energy.EnergyStorage;\nimport net.minecraftforge.energy.IEnergyStorage;\n\nimport logisticspipes.proxy.cofh.subproxies.ICoFHEnergyReceiver;\nimport logisticspipes.proxy.cofh.subproxies.ICoFHEnergyStorage;\nimport logisticspipes.proxy.interfaces.IPowerProxy;\n\npublic class PowerProxy implements IPowerProxy {\n\n\tprivate static class MEnergyStorage extends EnergyStorage {\n\n\t\tpublic MEnergyStorage(int capacity) {\n\t\t\tsuper(capacity);\n\t\t}\n\n\t\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\t\tthis.energy = nbt.getInteger(\"Energy\");\n\n\t\t\tif (energy > capacity) {\n\t\t\t\tenergy = capacity;\n\t\t\t}\n\t\t}\n\n\t\tpublic NBTTagCompound writeToNBT(NBTTagCompound nbt) {\n\t\t\tif (energy < 0) {\n\t\t\t\tenergy = 0;\n\t\t\t}\n\t\t\tnbt.setInteger(\"Energy\", energy);\n\t\t\treturn nbt;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isEnergyReceiver(TileEntity tile, EnumFacing face) {\n\t\tif (tile != null && tile.hasCapability(CapabilityEnergy.ENERGY, face)) {\n\t\t\treturn tile.getCapability(CapabilityEnergy.ENERGY, face).canReceive();\n\t\t}\n\t\treturn tile instanceof IEnergyStorage;\n\t}\n\n\t@Override\n\tpublic ICoFHEnergyReceiver getEnergyReceiver(TileEntity tile, EnumFacing face) {\n\t\tIEnergyStorage bHandler = null;\n\t\tif (tile != null && tile.hasCapability(CapabilityEnergy.ENERGY, face)) {\n\t\t\tbHandler = tile.getCapability(CapabilityEnergy.ENERGY, face);\n\t\t} else if (tile instanceof IEnergyStorage) {\n\t\t\tbHandler = (IEnergyStorage) tile;\n\t\t}\n\t\tfinal IEnergyStorage handler = bHandler;\n\t\treturn new ICoFHEnergyReceiver() {\n\n\t\t\t@Override\n\t\t\tpublic int getMaxEnergyStored() {\n\t\t\t\treturn handler.getMaxEnergyStored();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getEnergyStored() {\n\t\t\t\treturn handler.getEnergyStored();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int receiveEnergy(EnumFacing opposite, int amount, boolean simulate) {\n\t\t\t\treturn handler.receiveEnergy(amount, simulate);\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tpublic ICoFHEnergyStorage getEnergyStorage(int i) {\n\t\tfinal MEnergyStorage energy = new MEnergyStorage(i);\n\t\treturn new ICoFHEnergyStorage() {\n\n\t\t\t@Override\n\t\t\tpublic int extractEnergy(int space, boolean b) {\n\t\t\t\treturn energy.extractEnergy(space, b);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int receiveEnergy(int maxReceive, boolean simulate) {\n\t\t\t\treturn energy.receiveEnergy(maxReceive, simulate);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getEnergyStored() {\n\t\t\t\treturn energy.getEnergyStored();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int getMaxEnergyStored() {\n\t\t\t\treturn energy.getMaxEnergyStored();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\t\t\tenergy.readFromNBT(nbt);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void writeToNBT(NBTTagCompound nbt) {\n\t\t\t\tenergy.writeToNBT(nbt);\n\t\t\t}\n\n\t\t};\n\t}\n\n\t@Override\n\tpublic boolean isAvailable() {\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ProxyManager.java",
    "content": "package logisticspipes.proxy;\n\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.BlockStateContainer;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.util.text.TextFormatting;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.model.IModelState;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport com.google.common.collect.Lists;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.wrapper.LogisticsWrapperHandler;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.buildcraft.BuildCraftProxy;\nimport logisticspipes.proxy.buildcraft.subproxies.IBCPipeCapabilityProvider;\nimport logisticspipes.proxy.cc.CCProxy;\nimport logisticspipes.proxy.ccl.CCLProxy;\nimport logisticspipes.proxy.enderchest.EnderStorageProxy;\nimport logisticspipes.proxy.ic.IronChestProxy;\nimport logisticspipes.proxy.ic2.IC2Proxy;\nimport logisticspipes.proxy.interfaces.IBCProxy;\nimport logisticspipes.proxy.interfaces.ICCLProxy;\nimport logisticspipes.proxy.interfaces.ICCProxy;\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.proxy.interfaces.IEnderStorageProxy;\nimport logisticspipes.proxy.interfaces.IIC2Proxy;\nimport logisticspipes.proxy.interfaces.IIronChestProxy;\nimport logisticspipes.proxy.interfaces.INEIProxy;\nimport logisticspipes.proxy.interfaces.IOpenComputersProxy;\nimport logisticspipes.proxy.interfaces.ITDProxy;\nimport logisticspipes.proxy.interfaces.IThermalExpansionProxy;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IBounds;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.IRenderState;\nimport logisticspipes.proxy.object3d.interfaces.ITranslation;\nimport logisticspipes.proxy.object3d.interfaces.IVec3;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.opencomputers.IOCTile;\nimport logisticspipes.proxy.opencomputers.OpenComputersProxy;\nimport logisticspipes.proxy.td.ThermalDynamicsProxy;\nimport logisticspipes.proxy.td.subproxies.ITDPart;\nimport logisticspipes.proxy.te.ThermalExpansionProxy;\nimport logisticspipes.recipes.CraftingParts;\nimport logisticspipes.renderer.newpipe.RenderEntry;\nimport network.rs485.logisticspipes.proxy.mcmp.IMCMPProxy;\nimport network.rs485.logisticspipes.proxy.mcmp.MCMPProxy;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPBlockAccess;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPLTGPCompanion;\n\npublic class ProxyManager {\n\n\tpublic static <T> T getWrappedProxy(String modId, Class<T> interfaze, Class<? extends T> proxyClazz, T dummyProxy, Class<?>... wrapperInterfaces) {\n\t\ttry {\n\t\t\treturn LogisticsWrapperHandler.getWrappedProxy(modId, interfaze, proxyClazz, dummyProxy, wrapperInterfaces);\n\t\t} catch (Exception e) {\n\t\t\tif (e instanceof RuntimeException) {\n\t\t\t\tthrow (RuntimeException) e;\n\t\t\t}\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tpublic static void load() {\n\t\t//@formatter:off\n\t\t//CHECKSTYLE:OFF\n\n\t\tSimpleServiceLocator.setBuildCraftProxy(ProxyManager.getWrappedProxy(LPConstants.bcTransportModID + \"+\" + LPConstants.bcSiliconModID, IBCProxy.class, BuildCraftProxy.class, new IBCProxy() {\n\t\t\t@Override public void registerPipeInformationProvider() {}\n\t\t\t@Override public void initProxy() {}\n\t\t\t@Override public boolean isActive() {return false;}\n\t\t\t@Override public boolean isInstalled() {return false;}\n\t\t\t@Override public CraftingParts getRecipeParts() {return null;}\n\t\t\t@Override public void addCraftingRecipes(CraftingParts parts) {}\n\t\t\t@Override public Class<? extends ICraftingRecipeProvider> getAssemblyTableProviderClass() {return null;}\n\t\t\t@Override public void registerInventoryHandler() {}\n\t\t\t@Override public IBCPipeCapabilityProvider getIBCPipeCapabilityProvider(LogisticsTileGenericPipe pipe) {\n\t\t\t\treturn new IBCPipeCapabilityProvider() {\n\t\t\t\t\t@Override public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {return false;}\n\t\t\t\t\t@Nullable@Override public<T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {return null;}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public Object createMjReceiver(@Nonnull LogisticsPowerJunctionTileEntity te) {return null;}\n\t\t\t@Override public boolean isBuildCraftPipe(TileEntity tile) {return false;}\n\t\t}, IBCPipeCapabilityProvider.class));\n\n\t\tSimpleServiceLocator.setElectricItemProxy(ProxyManager.getWrappedProxy(LPConstants.ic2ModID, IIC2Proxy.class, IC2Proxy.class, new IIC2Proxy() {\n\t\t\t@Override public void addCraftingRecipes(CraftingParts parts) {}\n\t\t\t@Override public boolean hasIC2() {return false;}\n\t\t\t@Override public void registerToEneryNet(TileEntity tile) {}\n\t\t\t@Override public void unregisterToEneryNet(TileEntity tile) {}\n\t\t\t@Override public boolean acceptsEnergyFrom(TileEntity tile1, TileEntity tile2, EnumFacing opposite) {return false;}\n\t\t\t@Override public boolean isEnergySink(TileEntity tile) {return false;}\n\t\t\t@Override public double demandedEnergyUnits(TileEntity tile) {return 0;}\n\t\t\t@Override public double injectEnergyUnits(TileEntity tile, EnumFacing opposite, double d) {return d;}\n\t\t}));\n\n\t\tSimpleServiceLocator.setCCProxy(ProxyManager.getWrappedProxy(LPConstants.computerCraftModID, ICCProxy.class, CCProxy.class, new ICCProxy() {\n\t\t\t@Override public boolean isTurtle(TileEntity tile) {return false;}\n\t\t\t@Override public boolean isComputer(TileEntity tile) {return false;}\n\t\t\t@Override public boolean isCC() {return false;}\n\t\t\t@Override public boolean isLuaThread(Thread thread) {return false;}\n\t\t\t@Override public void queueEvent(String event, Object[] arguments, LogisticsTileGenericPipe logisticsTileGenericPipe) {}\n\t\t\t@Override public void setTurtleConnect(boolean flag, LogisticsTileGenericPipe logisticsTileGenericPipe) {}\n\t\t\t@Override public boolean getTurtleConnect(LogisticsTileGenericPipe logisticsTileGenericPipe) {return false;}\n\t\t\t@Override public int getLastCCID(LogisticsTileGenericPipe logisticsTileGenericPipe) {return 0;}\n\t\t\t@Override public void handleMesssage(int computerId, Object message, LogisticsTileGenericPipe tile, int sourceId) {}\n\t\t\t@Override public void addCraftingRecipes(CraftingParts parts) {}\n\t\t\t@Override public Object getAnswer(Object object) {return object;}\n\t\t}));\n\n\t\tSimpleServiceLocator.setThermalExpansionProxy(ProxyManager.getWrappedProxy(LPConstants.thermalExpansionModID, IThermalExpansionProxy.class, ThermalExpansionProxy.class, new IThermalExpansionProxy() {\n\t\t\t@Override public boolean isTE() {return false;}\n\t\t\t@Override public CraftingParts getRecipeParts() {return null;}\n\t\t\t@Override public boolean isToolHammer(Item stack) {return false;}\n\t\t\t@Override public boolean canHammer(@Nonnull ItemStack stack, EntityPlayer entityplayer, BlockPos pos) {return false;}\n\t\t\t@Override public void toolUsed(@Nonnull ItemStack stack, EntityPlayer entityplayer, BlockPos pos) {}\n\t\t}));\n\n\t\tSimpleServiceLocator.setNEIProxy(ProxyManager.getWrappedProxy(LPConstants.neiModID, INEIProxy.class, null /*NEIProxy.class*/, new INEIProxy() {\n\t\t\t@Override public List<String> getInfoForPosition(World world, EntityPlayer player, RayTraceResult objectMouseOver) {return new ArrayList<>(0);}\n\t\t\t@Override @SideOnly(Side.CLIENT) public boolean renderItemToolTip(int posX, int posY, List<String> msg, TextFormatting rarityColor, @Nonnull ItemStack stack) {return false;}\n\t\t\t@Override @SideOnly(Side.CLIENT) public List<String> getItemToolTip(@Nonnull ItemStack stack, EntityPlayer thePlayer, ITooltipFlag advancedItemTooltips, GuiContainer screen) {return stack.getTooltip(thePlayer, advancedItemTooltips);}\n\t\t\t@Override public@Nonnull  ItemStack getItemForPosition(World world, EntityPlayer player, RayTraceResult objectMouseOver) {return null;}\n\t\t}));\n\n\t\tSimpleServiceLocator.setIronChestProxy(ProxyManager.getWrappedProxy(LPConstants.ironChestModID, IIronChestProxy.class, IronChestProxy.class, new IIronChestProxy() {\n\t\t\t@Override public boolean isIronChest(TileEntity tile) {return false;}\n\t\t\t@Override public @SideOnly(Side.CLIENT) boolean isChestGui(GuiScreen gui) {return false;}\n\t\t}));\n\n\t\tSimpleServiceLocator.setEnderStorageProxy(ProxyManager.getWrappedProxy(\"enderstorage\", IEnderStorageProxy.class, EnderStorageProxy.class, new IEnderStorageProxy() {\n\t\t\t@Override public boolean isEnderChestBlock(Block block) {return false;}\n\t\t\t@Override public void openEnderChest(World world, int x, int y, int z, EntityPlayer player) {}\n\t\t}));\n\n\t\tSimpleServiceLocator.setOpenComputersProxy(ProxyManager.getWrappedProxy(LPConstants.openComputersModID, IOpenComputersProxy.class, OpenComputersProxy.class, new IOpenComputersProxy() {\n\t\t\t@Override public void initLogisticsTileGenericPipe(LogisticsTileGenericPipe tile) {}\n\t\t\t@Override public void initLogisticsSolidTileEntity(LogisticsSolidTileEntity tile) {}\n\t\t\t@Override public void handleWriteToNBT(IOCTile tile, NBTTagCompound nbt) {}\n\t\t\t@Override public void handleReadFromNBT(IOCTile tile, NBTTagCompound nbt) {}\n\t\t\t@Override public void handleInvalidate(IOCTile tile) {}\n\t\t\t@Override public void handleChunkUnload(IOCTile tile) {}\n\t\t\t@Override public void addToNetwork(TileEntity tile) {}\n\t\t}));\n\n/*\t\tSimpleServiceLocator.setToolWrenchProxy(ProxyManager.getWrappedProxy(\"!IToolWrench\", IToolWrenchProxy.class, ToolWrenchProxy.class, new IToolWrenchProxy() {\n\t\t\t@Override public void wrenchUsed(EntityPlayer entityplayer, int x, int y, int z) {}\n\t\t\t@Override public boolean isWrenchEquipped(EntityPlayer entityplayer) {return false;}\n\t\t\t@Override public boolean canWrench(EntityPlayer entityplayer, int x, int y, int z) {return false;}\n\t\t\t@Override public boolean isWrench(Item item) {return false;}\n\t\t}));*/\n\n\t\tSimpleServiceLocator.setThermalDynamicsProxy(ProxyManager.getWrappedProxy(LPConstants.thermalDynamicsModID, ITDProxy.class, ThermalDynamicsProxy.class, new ITDProxy() {\n\t\t\t@Override public ITDPart getTDPart(final LogisticsTileGenericPipe pipe) {\n\t\t\t\treturn new ITDPart() {\n\t\t\t\t\t@Override public TileEntity getInternalDuct() {return pipe;}\n\t\t\t\t\t@Override public void setWorld_LP(World world) {}\n\t\t\t\t\t@Override public void invalidate() {}\n\t\t\t\t\t@Override public void onChunkUnload() {}\n\t\t\t\t\t@Override public void scheduleNeighborChange() {}\n\t\t\t\t\t@Override public void connectionsChanged() {}\n\t\t\t\t\t@Override public boolean isLPSideBlocked(int i) {return false;}\n\t\t\t\t\t@Override public void setPos(BlockPos pos) {}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public boolean isActive() {return false;}\n\t\t\t@Override public void registerPipeInformationProvider() {}\n\t\t\t@Override public boolean isItemDuct(TileEntity tile) {return false;}\n\t\t\t@Override @SideOnly(Side.CLIENT) public void renderPipeConnections(LogisticsTileGenericPipe pipeTile, List<RenderEntry> list) {}\n\t\t\t@Override public void registerTextures(TextureMap iconRegister) {}\n\t\t\t@Override public boolean isBlockedSide(TileEntity with, EnumFacing opposite) {return false;}\n\t\t}, ITDPart.class));\n\n\t\tSimpleServiceLocator.setMCMPProxy(ProxyManager.getWrappedProxy(LPConstants.mcmpModID, IMCMPProxy.class, MCMPProxy.class, new IMCMPProxy() {\n\t\t\t@Override public IMCMPLTGPCompanion createMCMPCompanionFor(LogisticsTileGenericPipe pipe) {\n\t\t\t\treturn new IMCMPLTGPCompanion() {\n\t\t\t\t\t@Override public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {return false;}\n\t\t\t\t\t@Nullable @Override public<T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {return null;}\n\t\t\t\t\t@Override public NBTTagCompound getUpdateTag() {return new NBTTagCompound();}\n\t\t\t\t\t@Override public void handleUpdateTag(NBTTagCompound tag) {}\n\t\t\t\t\t@Override public TileEntity getMCMPTileEntity() {return null;}\n\t\t\t\t\t@Override public void update() {}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public IMCMPBlockAccess createMCMPBlockAccess() {return new IMCMPBlockAccess() {\n\t\t\t\t\t@Override public void addBlockState(BlockStateContainer.Builder builder) {}\n\t\t\t\t\t@Override public IBlockState getExtendedState(IBlockState state, IBlockAccess worldIn, BlockPos pos) {return state;}\n\t\t\t\t\t@Override public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entity, boolean isActualState) {}\n\t\t\t\t\t@Override public RayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end) {return null;}\n\t\t\t\t\t@Override public Block getBlock() {return null;}\n\t\t\t\t\t@Override public void addDrops(NonNullList<ItemStack> list, IBlockAccess world, BlockPos pos, IBlockState state, int fortune) {}\n\t\t\t\t};\n\t\t\t}\n\t\t    @Override public void addQuads(@Nonnull List<BakedQuad> list, IBlockState state, EnumFacing side, long rand) {}\n\t\t    @Override public void registerTileEntities() {}\n\t\t    @Override public boolean checkIntersectionWith(LogisticsTileGenericPipe logisticsTileGenericPipe, AxisAlignedBB aabb) {return false;}\n\t\t    @Override public boolean hasParts(LogisticsTileGenericPipe pipeTile) {return false;}\n\t\t    @Override @SideOnly(Side.CLIENT) public void renderTileEntitySpecialRenderer(LogisticsTileGenericPipe tileentity, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {}\n\t\t}, IMCMPLTGPCompanion.class));\n\n\t\tfinal IBounds dummyBounds = new IBounds() {\n\t\t\t@Override public IVec3 min() {\n\t\t\t\treturn new IVec3() {\n\t\t\t\t\t@Override public double x() {return 0;}\n\t\t\t\t\t@Override public double y() {return 0;}\n\t\t\t\t\t@Override public double z() {return 0;}\n\t\t\t\t\t@Override public Object getOriginal() {return null;}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public IVec3 max() {\n\t\t\t\treturn new IVec3() {\n\t\t\t\t\t@Override public double x() {return 0;}\n\t\t\t\t\t@Override public double y() {return 0;}\n\t\t\t\t\t@Override public double z() {return 0;}\n\t\t\t\t\t@Override public Object getOriginal() {return null;}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public AxisAlignedBB toAABB() {return null;}\n\t\t};\n\t\tfinal IModel3D dummy3DModel = new IModel3D() {\n\t\t\t@Override public IModel3D backfacedCopy() {return this;}\n\t\t\t@Override public void render(I3DOperation... i3dOperations) {}\n\t\t\t@Override public List<BakedQuad> renderToQuads(VertexFormat format, I3DOperation... i3dOperations) {return Lists.newArrayList();}\n\t\t\t@Override public void computeNormals() {}\n\t\t\t@Override public void computeStandardLighting() {}\n\t\t\t@Override public IBounds bounds() {\n\t\t\t\treturn dummyBounds;\n\t\t\t}\n\t\t\t@Override public IModel3D apply(I3DOperation translation) {return this;}\n\t\t\t@Override public IModel3D copy() {return this;}\n\t\t\t@Override public IModel3D twoFacedCopy() {return this;}\n\t\t\t@Override public Object getOriginal() {return this;}\n\t\t\t@Override public IBounds getBoundsInside(AxisAlignedBB boundingBox) {return dummyBounds;}\n\t\t};\n\t\tICCLProxy dummyCCLProxy = new ICCLProxy() {\n\t\t\t@SideOnly(Side.CLIENT) @Override public TextureTransformation createIconTransformer(TextureAtlasSprite registerIcon) {\n\t\t\t\treturn new TextureTransformation() {\n\t\t\t\t\t@Override public Object getOriginal() {return null;}\n\t\t\t\t\t@Override public void update(TextureAtlasSprite registerIcon) {}\n\t\t\t\t\t@Override public TextureAtlasSprite getTexture() {return null;}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public IRenderState getRenderState() {\n\t\t\t\treturn new IRenderState() {\n\t\t\t\t\t@Override public void reset() {}\n\t\t\t\t\t@Override public void setAlphaOverride(int i) {}\n\t\t\t\t\t@Override public void draw() {}\n\t\t\t\t\t@Override public void setBrightness(IBlockAccess world, BlockPos pos) {}\n\t\t\t\t\t@Override public void startDrawing(int mode, VertexFormat format) {}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public Map<String, IModel3D> parseObjModels(InputStream resourceAsStream, int i, LPScale scale) {return new HashMap<>();}\n\t\t\t@Override public Object getRotation(int i, int j) {return null;}\n\t\t\t@Override public Object getScale(double d, double e, double f) {return null;}\n\t\t\t@Override public Object getScale(double d) {return null;}\n\t\t\t@Override public ITranslation getTranslation(double d, double e, double f) {\n\t\t\t\treturn new ITranslation() {\n\t\t\t\t\t@Override public ITranslation inverse() {return this;}\n\t\t\t\t\t@Override public Object getOriginal() {return null;}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public ITranslation getTranslation(IVec3 min) {\n\t\t\t\treturn new ITranslation() {\n\t\t\t\t\t@Override public ITranslation inverse() {return this;}\n\t\t\t\t\t@Override public Object getOriginal() {return null;}\n\t\t\t\t};\n\t\t\t}\n\t\t\t@Override public Object getUVScale(double i, double d) {return null;}\n\t\t\t@Override public Object getUVTranslation(float i, float f) {return null;}\n\t\t\t@Override public Object getUVTransformationList(I3DOperation[] uvTranslation) {return null;}\n\t\t\t@Override public IModel3D wrapModel(Object model) {\n\t\t\t\treturn dummy3DModel;\n\t\t\t}\n\t\t\t@Override public boolean isActivated() {return false;}\n\t\t\t@Override public Object getRotation(double d, int i, int j, int k) {return null;}\n\t\t\t@Override public IModel3D combine(Collection<IModel3D> list) {\n\t\t\t\treturn dummy3DModel;\n\t\t\t}\n\t\t\t@Override public Object getColourMultiplier(int i) {return null;}\n\t\t\t@Override public IModelState getDefaultBlockState() {return null;}\n\t\t};\n\n\t\t//@formatter:on\n\t\t//CHECKSTYLE:ON\n\n\t\tClass<?>[] cclSubWrapper = new Class<?>[] { TextureTransformation.class, IRenderState.class, IModel3D.class, ITranslation.class, IVec3.class, IBounds.class };\n\t\tSimpleServiceLocator.setCCLProxy(ProxyManager.getWrappedProxy(\"!\" + LPConstants.cclrenderModID, ICCLProxy.class, CCLProxy.class, dummyCCLProxy, cclSubWrapper));\n\n\t\tSimpleServiceLocator.setConfigToolHandler(new ConfigToolHandler());\n\t\tSimpleServiceLocator.configToolHandler.registerWrapper();\n\n\t\tSimpleServiceLocator.setPowerProxy(new PowerProxy());\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/SimpleServiceLocator.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.proxy;\n\nimport java.util.LinkedList;\n\nimport logisticspipes.interfaces.ISecurityStationManager;\nimport logisticspipes.interfaces.routing.IChannelConnectionManager;\nimport logisticspipes.interfaces.routing.IChannelManagerProvider;\nimport logisticspipes.logistics.ILogisticsFluidManager;\nimport logisticspipes.logistics.ILogisticsManager;\nimport logisticspipes.proxy.interfaces.IBCProxy;\nimport logisticspipes.proxy.interfaces.ICCLProxy;\nimport logisticspipes.proxy.interfaces.ICCProxy;\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.proxy.interfaces.IEnderStorageProxy;\nimport logisticspipes.proxy.interfaces.IIC2Proxy;\nimport logisticspipes.proxy.interfaces.IIronChestProxy;\nimport logisticspipes.proxy.interfaces.INEIProxy;\nimport logisticspipes.proxy.interfaces.IOpenComputersProxy;\nimport logisticspipes.proxy.interfaces.IPowerProxy;\nimport logisticspipes.proxy.interfaces.ITDProxy;\nimport logisticspipes.proxy.interfaces.IThermalExpansionProxy;\nimport logisticspipes.proxy.progressprovider.MachineProgressProvider;\nimport logisticspipes.proxy.specialconnection.SpecialPipeConnection;\nimport logisticspipes.proxy.specialconnection.SpecialTileConnection;\nimport logisticspipes.proxy.specialtankhandler.SpecialTankHandler;\nimport logisticspipes.renderer.newpipe.GLRenderListHandler;\nimport logisticspipes.routing.RouterManager;\nimport logisticspipes.routing.pathfinder.PipeInformationManager;\nimport logisticspipes.ticks.ClientPacketBufferHandlerThread;\nimport logisticspipes.ticks.ServerPacketBufferHandlerThread;\nimport logisticspipes.utils.InventoryUtilFactory;\nimport logisticspipes.utils.RoutedItemHelper;\nimport network.rs485.logisticspipes.proxy.mcmp.IMCMPProxy;\n\npublic final class SimpleServiceLocator {\n\n\tprivate SimpleServiceLocator() {}\n\n\tpublic static IBCProxy buildCraftProxy = null;\n\n\tpublic static void setBuildCraftProxy(final IBCProxy bcProxy) {\n\t\tSimpleServiceLocator.buildCraftProxy = bcProxy;\n\t}\n\n\tpublic static IIC2Proxy IC2Proxy;\n\n\tpublic static void setElectricItemProxy(final IIC2Proxy ic2Proxy) {\n\t\tSimpleServiceLocator.IC2Proxy = ic2Proxy;\n\t}\n\n\tpublic static ICCProxy ccProxy;\n\n\tpublic static void setCCProxy(final ICCProxy cProxy) {\n\t\tSimpleServiceLocator.ccProxy = cProxy;\n\t}\n\n\tpublic static IChannelConnectionManager connectionManager;\n\n\tpublic static void setChannelConnectionManager(final IChannelConnectionManager conMngr) {\n\t\tSimpleServiceLocator.connectionManager = conMngr;\n\t}\n\n\tpublic static ISecurityStationManager securityStationManager;\n\n\tpublic static void setSecurityStationManager(final ISecurityStationManager secStationMngr) {\n\t\tSimpleServiceLocator.securityStationManager = secStationMngr;\n\t}\n\n\tpublic static RouterManager routerManager;\n\n\tpublic static void setRouterManager(final RouterManager routerMngr) {\n\t\tSimpleServiceLocator.routerManager = routerMngr;\n\t}\n\n\tpublic static ILogisticsManager logisticsManager;\n\n\tpublic static void setLogisticsManager(final ILogisticsManager logisticsMngr) {\n\t\tSimpleServiceLocator.logisticsManager = logisticsMngr;\n\t}\n\n\tpublic static ILogisticsFluidManager logisticsFluidManager;\n\n\tpublic static void setLogisticsFluidManager(final ILogisticsFluidManager logisticsMngr) {\n\t\tSimpleServiceLocator.logisticsFluidManager = logisticsMngr;\n\t}\n\n\tpublic static InventoryUtilFactory inventoryUtilFactory;\n\n\tpublic static void setInventoryUtilFactory(final InventoryUtilFactory invUtilFactory) {\n\t\tSimpleServiceLocator.inventoryUtilFactory = invUtilFactory;\n\t}\n\n\tpublic static LinkedList<ICraftingRecipeProvider> craftingRecipeProviders = new LinkedList<>();\n\n\tpublic static void addCraftingRecipeProvider(ICraftingRecipeProvider provider) {\n\t\tSimpleServiceLocator.craftingRecipeProviders.add(provider);\n\t}\n\n\tpublic static SpecialPipeConnection specialpipeconnection;\n\n\tpublic static void setSpecialConnectionHandler(final SpecialPipeConnection special) {\n\t\tSimpleServiceLocator.specialpipeconnection = special;\n\t}\n\n\tpublic static SpecialTileConnection specialtileconnection;\n\n\tpublic static void setSpecialConnectionHandler(final SpecialTileConnection special) {\n\t\tSimpleServiceLocator.specialtileconnection = special;\n\t}\n\n\tpublic static IThermalExpansionProxy thermalExpansionProxy;\n\n\tpublic static void setThermalExpansionProxy(IThermalExpansionProxy proxy) {\n\t\tSimpleServiceLocator.thermalExpansionProxy = proxy;\n\t}\n\n\tpublic static SpecialTankHandler specialTankHandler;\n\n\tpublic static void setSpecialTankHandler(SpecialTankHandler proxy) {\n\t\tSimpleServiceLocator.specialTankHandler = proxy;\n\t}\n\n\tpublic static ClientPacketBufferHandlerThread clientBufferHandler;\n\n\tpublic static void setClientPacketBufferHandlerThread(ClientPacketBufferHandlerThread proxy) {\n\t\tSimpleServiceLocator.clientBufferHandler = proxy;\n\t}\n\n\tpublic static ServerPacketBufferHandlerThread serverBufferHandler;\n\n\tpublic static void setServerPacketBufferHandlerThread(ServerPacketBufferHandlerThread proxy) {\n\t\tSimpleServiceLocator.serverBufferHandler = proxy;\n\t}\n\n\tpublic static INEIProxy neiProxy;\n\n\tpublic static void setNEIProxy(INEIProxy proxy) {\n\t\tSimpleServiceLocator.neiProxy = proxy;\n\t}\n\n\tpublic static PipeInformationManager pipeInformationManager;\n\n\tpublic static void setPipeInformationManager(PipeInformationManager manager) {\n\t\tSimpleServiceLocator.pipeInformationManager = manager;\n\t}\n\n\tpublic static IIronChestProxy ironChestProxy;\n\n\tpublic static void setIronChestProxy(IIronChestProxy proxy) {\n\t\tSimpleServiceLocator.ironChestProxy = proxy;\n\t}\n\n\tpublic static IEnderStorageProxy enderStorageProxy;\n\n\tpublic static void setEnderStorageProxy(IEnderStorageProxy proxy) {\n\t\tSimpleServiceLocator.enderStorageProxy = proxy;\n\t}\n\n\tpublic static MachineProgressProvider machineProgressProvider;\n\n\tpublic static void setMachineProgressProvider(MachineProgressProvider provider) {\n\t\tSimpleServiceLocator.machineProgressProvider = provider;\n\t}\n\n\tpublic static RoutedItemHelper routedItemHelper;\n\n\tpublic static void setRoutedItemHelper(RoutedItemHelper helper) {\n\t\tSimpleServiceLocator.routedItemHelper = helper;\n\t}\n\n\tpublic static IOpenComputersProxy openComputersProxy;\n\n\tpublic static void setOpenComputersProxy(IOpenComputersProxy proxy) {\n\t\tSimpleServiceLocator.openComputersProxy = proxy;\n\t}\n\n\tpublic static GLRenderListHandler renderListHandler;\n\n\tpublic static void setRenderListHandler(GLRenderListHandler handler) {\n\t\tSimpleServiceLocator.renderListHandler = handler;\n\t}\n\n\tpublic static IPowerProxy powerProxy;\n\n\tpublic static void setPowerProxy(IPowerProxy proxy) {\n\t\tSimpleServiceLocator.powerProxy = proxy;\n\t}\n\n\tpublic static ITDProxy thermalDynamicsProxy;\n\n\tpublic static void setThermalDynamicsProxy(ITDProxy proxy) {\n\t\tSimpleServiceLocator.thermalDynamicsProxy = proxy;\n\t}\n\n\tpublic static ICCLProxy cclProxy;\n\n\tpublic static void setCCLProxy(ICCLProxy proxy) {\n\t\tSimpleServiceLocator.cclProxy = proxy;\n\t}\n\n\tpublic static ConfigToolHandler configToolHandler;\n\n\tpublic static void setConfigToolHandler(ConfigToolHandler configToolHandler) {\n\t\tSimpleServiceLocator.configToolHandler = configToolHandler;\n\t}\n\n\tpublic static IMCMPProxy mcmpProxy;\n\n\tpublic static void setMCMPProxy(IMCMPProxy proxy) {\n\t\tSimpleServiceLocator.mcmpProxy = proxy;\n\t}\n\n\tpublic static IChannelManagerProvider channelManagerProvider;\n\n\tpublic static void setChannelManagerProvider(IChannelManagerProvider managerProvider) {\n\t\tSimpleServiceLocator.channelManagerProvider = managerProvider;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/SpecialInventoryHandlerManager.java",
    "content": "package logisticspipes.proxy;\n\nimport net.minecraftforge.fml.common.Loader;\n\nimport static logisticspipes.LPConstants.appliedenergisticsModID;\n\nimport logisticspipes.proxy.specialinventoryhandler.AEInterfaceInventoryHandler;\nimport network.rs485.logisticspipes.compat.CharsetImplementationFactory;\nimport network.rs485.logisticspipes.proxy.StorageDrawersProxy;\n\npublic class SpecialInventoryHandlerManager {\n\n\tpublic static void load() {\n\n\t\tif (Loader.isModLoaded(appliedenergisticsModID)) {\n\t\t\tSimpleServiceLocator.inventoryUtilFactory.registerHandler(new AEInterfaceInventoryHandler());\n\t\t}\n\n\t\tSimpleServiceLocator.buildCraftProxy.registerInventoryHandler();\n\n\t\tStorageDrawersProxy.INSTANCE.registerInventoryHandler();\n\n\t\tSimpleServiceLocator.inventoryUtilFactory.registerHandler(new CharsetImplementationFactory());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/SpecialTankHandlerManager.java",
    "content": "package logisticspipes.proxy;\n\npublic class SpecialTankHandlerManager {\n\n\tpublic static void load() {\n\t\t/*if (Loader.isModLoaded(\"BuildCraft|Factory\")) {\n\t\t\tSimpleServiceLocator.specialTankHandler.registerHandler(new BuildCraftTankHandler());\n\t\t}\n\t\tif (Loader.isModLoaded(\"AppliedEnergistics2-Core\") || Loader.isModLoaded(\"appliedenergistics2-core\")) {\n\t\t\tSimpleServiceLocator.specialTankHandler.registerHandler(new AETankHandler());\n\t\t}*/\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/VersionNotSupportedException.java",
    "content": "package logisticspipes.proxy;\n\npublic class VersionNotSupportedException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 3229611374730119210L;\n\n\tpublic VersionNotSupportedException(String modName, String haveVersion, String targetVersion, String condition) {\n\t\tsuper(\"The \" + modName + \" Version '\" + haveVersion + \"' is not supported by this LP version\" + condition + \". Please use '\" + targetVersion + \"'\");\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/buildcraft/BCPipeInformationProvider.java",
    "content": "package logisticspipes.proxy.buildcraft;\n\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Stream;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport buildcraft.api.transport.pipe.IFlowItems;\nimport buildcraft.api.transport.pipe.PipeApi;\nimport buildcraft.transport.pipe.behaviour.PipeBehaviourDiamondItem;\nimport buildcraft.transport.pipe.behaviour.PipeBehaviourDirectional;\nimport buildcraft.transport.pipe.behaviour.PipeBehaviourIron;\nimport buildcraft.transport.pipe.behaviour.PipeBehaviourObsidian;\nimport buildcraft.transport.tile.TilePipeHolder;\n\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.utils.ReflectionHelper;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.connection.ConnectionType;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class BCPipeInformationProvider implements IPipeInformationProvider {\n\n\tprivate final TilePipeHolder pipe;\n\n\tpublic BCPipeInformationProvider(TilePipeHolder pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\t@Override\n\tpublic boolean isCorrect(ConnectionType type) {\n\t\tif (pipe == null || pipe.getPipe() == null || !SimpleServiceLocator.buildCraftProxy.isActive()) {\n\t\t\treturn false;\n\t\t}\n\n\t\tboolean precheck = false;\n\t\tif (type == ConnectionType.UNDEFINED) {\n\t\t\tprecheck = pipe.getPipe().getDefinition().flowType == PipeApi.flowItems || pipe.getPipe().getDefinition().flowType == PipeApi.flowFluids;\n\t\t} else if (type == ConnectionType.ITEM) {\n\t\t\tprecheck = pipe.getPipe().getDefinition().flowType == PipeApi.flowItems;\n\t\t} else if (type == ConnectionType.FLUID) {\n\t\t\tprecheck = pipe.getPipe().getDefinition().flowType == PipeApi.flowFluids;\n\t\t}\n\t\treturn precheck;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn pipe.getPipePos().getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn pipe.getPipePos().getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn pipe.getPipePos().getZ();\n\t}\n\n\t@Override\n\tpublic World getWorld() {\n\t\treturn pipe.getWorld();\n\t}\n\n\t@Override\n\tpublic boolean isRouterInitialized() {\n\t\treturn pipe.getPipe() != null;\n\t}\n\n\t@Override\n\tpublic boolean isRoutingPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getRoutingPipe() {\n\t\tthrow new RuntimeException(\"This is no routing pipe\");\n\t}\n\n\t@Override\n\tpublic TileEntity getNextConnectedTile(EnumFacing direction) {\n\t\treturn pipe.getNeighbourTile(direction);\n\t}\n\n\t@Override\n\tpublic boolean isFirewallPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IFilter getFirewallFilter() {\n\t\tthrow new RuntimeException(\"This is not a firewall pipe\");\n\t}\n\n\t@Override\n\tpublic TileEntity getTile() {\n\t\treturn pipe;\n\t}\n\n\t@Override\n\tpublic boolean divideNetwork() {\n\t\t//Obsidian seperates networks\n\t\treturn (pipe.getPipe().getDefinition().flowType == PipeApi.flowItems && pipe.getPipe().getBehaviour() instanceof PipeBehaviourObsidian) || pipe.getPipe().getDefinition().flowType == PipeApi.flowStructure;\n\t}\n\n\t@Override\n\tpublic boolean powerOnly() {\n\t\treturn (pipe.getPipe().getDefinition().flowType == PipeApi.flowItems && pipe.getPipe().getBehaviour() instanceof PipeBehaviourDiamondItem);\n\t}\n\n\t@Override\n\tpublic boolean isOnewayPipe() {\n\t\treturn (pipe.getPipe().getDefinition().flowType == PipeApi.flowItems && pipe.getPipe().getBehaviour() instanceof PipeBehaviourIron);\n\t}\n\n\t@Override\n\tpublic boolean isOutputClosed(EnumFacing direction) {\n\t\tEnumFacing point = ReflectionHelper.invokePrivateMethod(PipeBehaviourDirectional.class, pipe.getPipe().getBehaviour(), \"getCurrentDir\", \"getCurrentDir\", new Class[0], new Object[0]);\n\t\treturn point != direction;\n\t}\n\n\t@Override\n\tpublic boolean canConnect(TileEntity to, EnumFacing direction, boolean targeted) {\n\t\treturn pipe.getPipe().isConnected(direction);\n\t}\n\n\t@Override\n\tpublic double getDistance() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic double getDistanceWeight() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic boolean isItemPipe() {\n\t\treturn pipe != null && pipe.getPipe() != null && pipe.getPipe().getDefinition().flowType == PipeApi.flowItems && SimpleServiceLocator.buildCraftProxy.isActive();\n\t}\n\n\t@Override\n\tpublic boolean isFluidPipe() {\n\t\treturn pipe != null && pipe.getPipe() != null && pipe.getPipe().getDefinition().flowType == PipeApi.flowFluids && SimpleServiceLocator.buildCraftProxy.isActive();\n\t}\n\n\t@Override\n\tpublic boolean isPowerPipe() {\n\t\treturn pipe != null && pipe.getPipe() != null && pipe.getPipe().getDefinition().flowType == PipeApi.flowPower && SimpleServiceLocator.buildCraftProxy.isActive();\n\t}\n\n\t@Override\n\tpublic double getDistanceTo(int destinationint, EnumFacing ignore, ItemIdentifier ident, boolean isActive, double traveled, double max, List<DoubleCoordinates> visited) {\n\t\tif (traveled >= max) {\n\t\t\treturn Integer.MAX_VALUE;\n\t\t}\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (ignore == dir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tIPipeInformationProvider information = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(getNextConnectedTile(dir));\n\t\t\tif (information != null) {\n\t\t\t\tDoubleCoordinates pos = new DoubleCoordinates(information);\n\t\t\t\tif (visited.contains(pos)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tvisited.add(pos);\n\t\t\t\tdouble result = information.getDistanceTo(destinationint, dir.getOpposite(), ident, isActive, traveled + getDistance(), max, visited);\n\t\t\t\tvisited.remove(pos);\n\t\t\t\tif (result == Integer.MAX_VALUE) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t\treturn result + (int) getDistance();\n\t\t\t}\n\t\t}\n\t\treturn Integer.MAX_VALUE;\n\t}\n\n\t@Override\n\tpublic boolean acceptItem(LPTravelingItem item, TileEntity from) {\n\t\tif (pipe != null && pipe.getPipe() != null && pipe.getPipe().getDefinition().flowType == PipeApi.flowItems) {\n\t\t\tif (!(item instanceof LPTravelingItemServer)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tItemRoutingInformation routingInformation = ((LPTravelingItemServer) item).getInfo();\n\t\t\tNBTTagCompound routingData = new NBTTagCompound();\n\t\t\troutingInformation.storeToNBT(routingData);\n\n\t\t\tItemStack transportStack = item.getItemIdentifierStack().makeNormalStack();\n\t\t\tif (!transportStack.hasTagCompound()) {\n\t\t\t\ttransportStack.setTagCompound(new NBTTagCompound());\n\t\t\t}\n\t\t\tfinal NBTTagCompound tag = Objects.requireNonNull(transportStack.getTagCompound());\n\t\t\ttag.setTag(\"logisticspipes:routingdata_buildcraft\", routingData);\n\n\t\t\tIFlowItems itemPipe = (IFlowItems) pipe.getPipe().getFlow();\n\t\t\titemPipe.insertItemsForce(transportStack, item.output.getOpposite(), null, item.getSpeed());\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void refreshTileCacheOnSide(EnumFacing side) {\n\n\t}\n\n\t@Override\n\tpublic boolean isMultiBlock() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic Stream<TileEntity> getPartsOfPipe() {\n\t\treturn Stream.empty();\n\t}\n}"
  },
  {
    "path": "common/logisticspipes/proxy/buildcraft/BuildCraftProxy.java",
    "content": "package logisticspipes.proxy.buildcraft;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\n\nimport buildcraft.api.mj.IMjConnector;\nimport buildcraft.api.mj.IMjReceiver;\nimport buildcraft.api.mj.MjAPI;\nimport buildcraft.lib.tile.TileBC_Neptune;\nimport buildcraft.transport.tile.TilePipeHolder;\n\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.pipes.basic.ItemInsertionHandler;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.buildcraft.recipeprovider.AssemblyTable;\nimport logisticspipes.proxy.buildcraft.subproxies.BCPipeCapabilityProvider;\nimport logisticspipes.proxy.buildcraft.subproxies.IBCPipeCapabilityProvider;\nimport logisticspipes.proxy.interfaces.IBCProxy;\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.proxy.specialinventoryhandler.BuildCraftTransactorHandler;\nimport logisticspipes.recipes.CraftingParts;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.transport.LPTravelingItem;\n\npublic class BuildCraftProxy implements IBCProxy {\n\n\tpublic BuildCraftProxy() {\n\n\t}\n\n\t@Override\n\tpublic void registerPipeInformationProvider() {\n\t\tSimpleServiceLocator.pipeInformationManager.registerProvider(TilePipeHolder.class, BCPipeInformationProvider.class);\n\t}\n\n\t@Override\n\tpublic void initProxy() {\n\t\tLogisticsTileGenericPipe.pipeInventoryConnectionChecker.addSupportedClassType(TileBC_Neptune.class);\n\n\t\tItemInsertionHandler.ACCEPTORS.add((pipe, from, stack) -> {\n\t\t\tif (!stack.isEmpty() && stack.hasTagCompound() && stack.getTagCompound().hasKey(\"logisticspipes:routingdata_buildcraft\")) {\n\t\t\t\tNBTTagCompound routingData = stack.getTagCompound().getCompoundTag(\"logisticspipes:routingdata_buildcraft\");\n\t\t\t\tItemRoutingInformation info = ItemRoutingInformation.restoreFromNBT(routingData);\n\t\t\t\tLPTravelingItem item = new LPTravelingItem.LPTravelingItemServer(info);\n\t\t\t\titem.output = from.getOpposite();\n\t\t\t\treturn pipe.acceptItem(item, null);\n\t\t\t}\n\t\t\treturn false;\n\t\t});\n\t}\n\n\t@Override\n\tpublic boolean isActive() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isInstalled() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic CraftingParts getRecipeParts() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void addCraftingRecipes(CraftingParts parts) {}\n\n\t@Override\n\tpublic Class<? extends ICraftingRecipeProvider> getAssemblyTableProviderClass() {\n\t\treturn AssemblyTable.class;\n\t}\n\n\t@Override\n\tpublic void registerInventoryHandler() {\n\t\tSimpleServiceLocator.inventoryUtilFactory.registerHandler(new BuildCraftTransactorHandler());\n\t}\n\n\t@Override\n\tpublic IBCPipeCapabilityProvider getIBCPipeCapabilityProvider(LogisticsTileGenericPipe pipe) {\n\t\treturn new BCPipeCapabilityProvider(pipe);\n\t}\n\n\t@Override\n\tpublic Object createMjReceiver(@Nonnull LogisticsPowerJunctionTileEntity te) {\n\t\treturn new IMjReceiver() {\n\n\t\t\t@Override\n\t\t\tpublic long getPowerRequested() {\n\t\t\t\treturn te.freeSpace() / LogisticsPowerJunctionTileEntity.MJMultiplier * MjAPI.MJ;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic long receivePower(long l, boolean b) {\n\t\t\t\tlong freeMj = te.freeSpace() / LogisticsPowerJunctionTileEntity.MJMultiplier * MjAPI.MJ;\n\t\t\t\tlong needs = Math.min(freeMj, l);\n\t\t\t\tif (!b) {\n\t\t\t\t\tte.addEnergy(((float) needs) * LogisticsPowerJunctionTileEntity.MJMultiplier / MjAPI.MJ);\n\t\t\t\t}\n\t\t\t\treturn l - needs;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean canConnect(@Nonnull IMjConnector iMjConnector) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tpublic boolean isBuildCraftPipe(TileEntity tile) {\n\t\treturn tile instanceof TilePipeHolder;\n\t}\n}"
  },
  {
    "path": "common/logisticspipes/proxy/buildcraft/BuildCraftToolWrench.java",
    "content": "package logisticspipes.proxy.buildcraft;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumHand;\n\nimport buildcraft.api.tools.IToolWrench;\n\nimport logisticspipes.api.ILPPipeConfigTool;\nimport logisticspipes.api.ILPPipeTile;\nimport logisticspipes.proxy.interfaces.ILPPipeConfigToolWrapper;\n\npublic class BuildCraftToolWrench implements ILPPipeConfigToolWrapper {\n\n\t@Override\n\tpublic ILPPipeConfigTool getWrappedTool(@Nonnull ItemStack stack) {\n\t\tif (!stack.isEmpty() && stack.getItem() instanceof IToolWrench) {\n\t\t\treturn new ILPPipeConfigTool() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean canWrench(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\t\t\t\tif (wrench.isEmpty() || !(wrench.getItem() instanceof IToolWrench)) return false;\n\t\t\t\t\treturn ((IToolWrench) wrench.getItem()).canWrench(player, EnumHand.MAIN_HAND, wrench, null);\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void wrenchUsed(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\t\t\t\tif (wrench.isEmpty() || !(wrench.getItem() instanceof IToolWrench)) return;\n\t\t\t\t\t((IToolWrench) wrench.getItem()).wrenchUsed(player, EnumHand.MAIN_HAND, wrench, null);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/buildcraft/recipeprovider/AssemblyTable.java",
    "content": "package logisticspipes.proxy.buildcraft.recipeprovider;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.NonNullList;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport buildcraft.api.recipes.AssemblyRecipe;\nimport buildcraft.api.recipes.AssemblyRecipeBasic;\nimport buildcraft.lib.recipe.AssemblyRecipeRegistry;\nimport buildcraft.silicon.EnumAssemblyRecipeState;\nimport buildcraft.silicon.tile.TileAssemblyTable;\n\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\npublic class AssemblyTable implements ICraftingRecipeProvider {\n\n\t@Override\n\tpublic boolean canOpenGui(TileEntity tile) {\n\t\treturn (tile instanceof TileAssemblyTable);\n\t}\n\n\t@Override\n\tpublic boolean importRecipe(TileEntity tile, IItemIdentifierInventory inventory) {\n\t\tif (!(tile instanceof TileAssemblyTable)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tTileAssemblyTable table = (TileAssemblyTable) tile;\n\n\t\t//current pipe inputs/outputs\n\t\tfinal ItemIdentifierInventory inputs = new ItemIdentifierInventory(inventory.getSizeInventory() - 2, \"AssemblyTableDummyInv\", 64, false);\n\t\tfor (int i = 0; i < inventory.getSizeInventory() - 2; i++) {\n\t\t\tinputs.setInventorySlotContents(i, inventory.getIDStackInSlot(i));\n\t\t}\n\t\tfinal ItemStack output = inventory.getStackInSlot(inventory.getSizeInventory() - 2);\n\n\t\t//see if there's a recipe planned in the table that matches the current pipe settings, if yes take the next, otherwise take the first\n\t\tAssemblyRecipeBasic firstRecipe = null;\n\t\tAssemblyRecipeBasic nextRecipe = null;\n\t\tboolean takeNext = false;\n\t\tfor (AssemblyRecipe r : AssemblyRecipeRegistry.REGISTRY.values()) {\n\t\t\tif (!(r instanceof AssemblyRecipeBasic)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (table.recipesStates.entrySet().stream().filter(it -> it.getKey().recipe == r)\n\t\t\t\t\t.anyMatch(it -> it.getValue() != EnumAssemblyRecipeState.POSSIBLE)) {\n\t\t\t\tif (firstRecipe == null) {\n\t\t\t\t\tfirstRecipe = (AssemblyRecipeBasic) r;\n\t\t\t\t}\n\t\t\t\tif (takeNext) {\n\t\t\t\t\tnextRecipe = (AssemblyRecipeBasic) r;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!output.isEmpty() && r.getOutputPreviews().stream().anyMatch(it -> ItemStack.areItemStacksEqual(output, it))) {\n\t\t\t\t\tif (!r.getOutputs(inputs.toNonNullList()).isEmpty()) {\n\t\t\t\t\t\ttakeNext = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (nextRecipe == null) {\n\t\t\tnextRecipe = firstRecipe;\n\t\t}\n\t\tif (nextRecipe == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Import\n\t\tinventory.setInventorySlotContents(inventory.getSizeInventory() - 2, nextRecipe.getOutputPreviews().stream().findFirst().orElse(ItemStack.EMPTY));\n\t\ttry {\n\t\t\tfor (int i = 0; i < inventory.getSizeInventory() - 2; i++) {\n\t\t\t\tinventory.clearInventorySlotContents(i);\n\t\t\t}\n\t\t\tint i = 0;\n\t\t\tfor (Object input : nextRecipe.getInputsFor(inventory.getStackInSlot(inventory.getSizeInventory() - 2))) {\n\t\t\t\tItemStack processed = ItemStack.EMPTY;\n\t\t\t\tif (input instanceof String) {\n\t\t\t\t\tNonNullList<ItemStack> ores = OreDictionary.getOres((String) input);\n\t\t\t\t\tif (ores != null && ores.size() > 0) {\n\t\t\t\t\t\tprocessed = ores.get(0);\n\t\t\t\t\t}\n\t\t\t\t} else if (input instanceof ItemStack) {\n\t\t\t\t\tprocessed = (ItemStack) input;\n\t\t\t\t} else if (input instanceof Item) {\n\t\t\t\t\tprocessed = new ItemStack((Item) input);\n\t\t\t\t} else if (input instanceof Block) {\n\t\t\t\t\tprocessed = new ItemStack((Block) input, 1, 0);\n\t\t\t\t} else if (input instanceof Integer) {\n\t\t\t\t\t// was null\n\t\t\t\t} else {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Unknown Object passed to recipe!\");\n\t\t\t\t}\n\t\t\t\tif (!processed.isEmpty()) {\n\t\t\t\t\tinventory.setInventorySlotContents(i, processed);\n\t\t\t\t\t++i;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (ClassCastException e) {\n\t\t\t// TODO: make it show a nice error or\n\t\t\t// remove this hack altogether.\n\t\t}\n\n\t\tinventory.getSlotAccess().compactFirst(9);\n\n\t\treturn true;\n\t}\n}"
  },
  {
    "path": "common/logisticspipes/proxy/buildcraft/subproxies/BCPipeCapabilityProvider.java",
    "content": "package logisticspipes.proxy.buildcraft.subproxies;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.EnumDyeColor;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.capabilities.Capability;\n\nimport buildcraft.api.transport.IInjectable;\nimport buildcraft.api.transport.pipe.PipeApi;\n\nimport logisticspipes.pipes.basic.ItemInsertionHandler;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\npublic class BCPipeCapabilityProvider implements IBCPipeCapabilityProvider, IInjectable {\n\n\tprivate final LogisticsTileGenericPipe logisticsPipe;\n\n\tpublic BCPipeCapabilityProvider(LogisticsTileGenericPipe logisticsPipe) {\n\t\tthis.logisticsPipe = logisticsPipe;\n\t}\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\treturn capability == PipeApi.CAP_INJECTABLE;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == PipeApi.CAP_INJECTABLE) {\n\t\t\treturn (T) this;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean canInjectItems(EnumFacing from) {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack injectItem(@Nonnull ItemStack stack, boolean doAdd, EnumFacing from, EnumDyeColor color, double speed) {\n\t\tif (doAdd) {\n\t\t\treturn ItemInsertionHandler.handleItemInsetion(logisticsPipe, from, stack);\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/buildcraft/subproxies/IBCPipeCapabilityProvider.java",
    "content": "package logisticspipes.proxy.buildcraft.subproxies;\n\nimport net.minecraftforge.common.capabilities.ICapabilityProvider;\n\npublic interface IBCPipeCapabilityProvider extends ICapabilityProvider {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/CCConstants.java",
    "content": "package logisticspipes.proxy.cc;\n\npublic class CCConstants {\n\n\tpublic static final String LP_CC_BROADCAST_EVENT = \"LP_BROADCAST\";\n\tpublic static final String LP_CC_MESSAGE_EVENT = \"LP_MESSAGE\";\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/CCProxy.java",
    "content": "package logisticspipes.proxy.cc;\n\nimport java.lang.reflect.Field;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport dan200.computercraft.api.ComputerCraftAPI;\nimport dan200.computercraft.api.peripheral.IComputerAccess;\nimport dan200.computercraft.shared.computer.blocks.TileComputer;\nimport dan200.computercraft.shared.turtle.blocks.TileTurtle;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.cc.wrapper.CCCommandWrapper;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\nimport logisticspipes.proxy.interfaces.ICCProxy;\nimport logisticspipes.recipes.CraftingParts;\n\npublic class CCProxy implements ICCProxy {\n\n\tprivate Field target;\n\n\tpublic CCProxy() throws NoSuchFieldException, SecurityException {\n\t\tComputerCraftAPI.registerPeripheralProvider(new LPPeripheralProvider());\n\t\ttarget = Thread.class.getDeclaredField(\"target\");\n\t\ttarget.setAccessible(true);\n\t}\n\n\t@Override\n\tpublic boolean isTurtle(TileEntity tile) {\n\t\treturn tile instanceof TileTurtle;\n\t}\n\n\t@Override\n\tpublic boolean isComputer(TileEntity tile) {\n\t\treturn tile instanceof TileComputer;\n\t}\n\n\t@Override\n\tpublic boolean isCC() {\n\t\treturn true;\n\t}\n\n\tprivate Runnable getTaget(Thread thread) {\n\t\ttry {\n\t\t\treturn (Runnable) target.get(thread);\n\t\t} catch (SecurityException | IllegalAccessException | IllegalArgumentException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isLuaThread(Thread thread) {\n\t\tRunnable tar = getTaget(thread);\n\t\tif (tar == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn tar.getClass().getName().contains(\"org.luaj.vm2.LuaThread\");\n\t}\n\n\t@Override\n\tpublic void queueEvent(String event, Object[] arguments, LogisticsTileGenericPipe tile) {\n\t\tfor (IComputerAccess computer : tile.connections.keySet()) {\n\t\t\tcomputer.queueEvent(event, arguments);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setTurtleConnect(boolean flag, LogisticsTileGenericPipe tile) {\n\t\ttile.turtleConnect[tile.connections.get(tile.currentPC).ordinal()] = flag;\n\t\ttile.scheduleNeighborChange();\n\t}\n\n\t@Override\n\tpublic boolean getTurtleConnect(LogisticsTileGenericPipe tile) {\n\t\treturn tile.turtleConnect[tile.connections.get(tile.currentPC).ordinal()];\n\t}\n\n\t@Override\n\tpublic int getLastCCID(LogisticsTileGenericPipe tile) {\n\t\tif (tile.currentPC == null) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn tile.currentPC.getID();\n\t}\n\n\t@Override\n\tpublic void handleMesssage(int computerId, Object message, LogisticsTileGenericPipe tile, int sourceId) {\n\t\ttile.connections.keySet().stream().filter(computer -> computer.getID() == computerId).forEach(computer -> computer.queueEvent(CCConstants.LP_CC_MESSAGE_EVENT, new Object[] { sourceId, message }));\n\t}\n\n\t@Override\n\tpublic void addCraftingRecipes(CraftingParts parts) {\n\t\t/*\n\t\tLocalCraftingManager craftingManager = RecipeManager.craftingManager;\n\t\tcraftingManager.addRecipe(new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.CC_REMOTE_CONTROL), CraftingDependency.Upgrades, new Object[] { false, \"rTr\", \"WCM\", \"rKr\", Character.valueOf('C'), parts.getChipTear3(), Character.valueOf('r'), Items.redstone, Character.valueOf('T'), Blocks.redstone_torch,\n\t\t\t\tCharacter.valueOf('W'), new ItemStack(ComputerCraft.Blocks.peripheral, 1, 1), Character.valueOf('M'), new ItemStack(ComputerCraft.Blocks.cable, 1, 1), Character.valueOf('K'), new ItemStack(ComputerCraft.Blocks.cable, 1, 0) });\n\t\tcraftingManager.addRecipe(new ItemStack(LogisticsPipes.ModuleItem, 1, ItemModule.CC_BASED_ITEMSINK), CraftingDependency.Upgrades, new Object[] { false, \"rTr\", \"WCM\", \"rKr\", Character.valueOf('C'), new ItemStack(LogisticsPipes.ModuleItem, 1, ItemModule.ITEMSINK), Character.valueOf('r'), Items.redstone,\n\t\t\t\tCharacter.valueOf('T'), Blocks.redstone_torch, Character.valueOf('W'), new ItemStack(ComputerCraft.Blocks.peripheral, 1, 1), Character.valueOf('M'), new ItemStack(ComputerCraft.Blocks.cable, 1, 1), Character.valueOf('K'), new ItemStack(ComputerCraft.Blocks.cable, 1, 0) });\n\t\tcraftingManager.addRecipe(new ItemStack(LogisticsPipes.ModuleItem, 1, ItemModule.CC_BASED_QUICKSORT), CraftingDependency.Upgrades, new Object[] { false, \"rTr\", \"WCM\", \"rKr\", Character.valueOf('C'), new ItemStack(LogisticsPipes.ModuleItem, 1, ItemModule.QUICKSORT), Character.valueOf('r'), Items.redstone,\n\t\t\t\tCharacter.valueOf('T'), Blocks.redstone_torch, Character.valueOf('W'), new ItemStack(ComputerCraft.Blocks.peripheral, 1, 1), Character.valueOf('M'), new ItemStack(ComputerCraft.Blocks.cable, 1, 1), Character.valueOf('K'), new ItemStack(ComputerCraft.Blocks.cable, 1, 0) });\n\t\t\t\t*/\n\t}\n\n\t@Override\n\tpublic Object getAnswer(Object object) {\n\t\treturn CCObjectWrapper.getWrappedObject(object, CCCommandWrapper.WRAPPER);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/LPASMHookCC.java",
    "content": "package logisticspipes.proxy.cc;\n\nimport dan200.computercraft.api.lua.ILuaObject;\nimport org.luaj.vm2.LuaTable;\nimport org.luaj.vm2.LuaValue;\nimport org.luaj.vm2.Varargs;\n\nimport logisticspipes.proxy.cc.wrapper.CCCommandWrapper;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\n\npublic class LPASMHookCC {\n\n\tpublic static boolean handleCCWrappedILuaObject(ILuaObject object) {\n\t\tif (object instanceof CCCommandWrapper) {\n\t\t\treturn ((CCCommandWrapper) object).table != null;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic static LuaTable returnCCWrappedILuaObject(ILuaObject object) {\n\t\treturn ((CCCommandWrapper) object).table;\n\t}\n\n\tpublic static LuaTable onCCWrappedILuaObject(final LuaTable table, final ILuaObject object) {\n\t\tif (object instanceof CCCommandWrapper) {\n\t\t\tLuaTable lpTable = new LPLuaTable((CCCommandWrapper) object);\n\t\t\tLuaValue k = LuaValue.NIL;\n\t\t\twhile (true) {\n\t\t\t\tVarargs n = table.next(k);\n\t\t\t\tif ((k = n.arg1()).isnil()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tLuaValue v = n.arg(2);\n\t\t\t\tlpTable.set(k, v);\n\t\t\t}\n\t\t\t((CCCommandWrapper) object).table = lpTable;\n\t\t\treturn lpTable;\n\t\t}\n\t\treturn table;\n\t}\n\n\tpublic static boolean handleCCToObject(LuaValue value) {\n\t\tif (value.type() != LuaValue.TTABLE) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!(value instanceof LPLuaTable)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tLPLuaTable table = (LPLuaTable) value;\n\t\treturn table.wrapper.getObject() != null;\n\t}\n\n\tpublic static Object returnCCToObject(LuaValue value) {\n\t\tObject object = ((LPLuaTable) value).wrapper.getObject();\n\t\tif (object instanceof ICCTypeWrapped) {\n\t\t\tobject = ((ICCTypeWrapped) object).getObject();\n\t\t}\n\t\treturn object;\n\t}\n\n\tprivate static class LPLuaTable extends LuaTable {\n\n\t\tfinal CCCommandWrapper wrapper;\n\n\t\tpublic LPLuaTable(CCCommandWrapper wrapper) {\n\t\t\tthis.wrapper = wrapper;\n\t\t}\n\n\t\t@Override\n\t\tpublic String tojstring() {\n\t\t\treturn wrapper.getType() + \" [\" + super.tojstring() + \"]\";\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/LPPeripheralProvider.java",
    "content": "package logisticspipes.proxy.cc;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport dan200.computercraft.api.peripheral.IPeripheral;\nimport dan200.computercraft.api.peripheral.IPeripheralProvider;\n\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.cc.wrapper.LPPeripheralTilePipeWrapper;\nimport logisticspipes.proxy.cc.wrapper.LPPeripheralTileSolidWrapper;\n\npublic class LPPeripheralProvider implements IPeripheralProvider {\n\n\t@Override\n\tpublic IPeripheral getPeripheral(World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side) {\n\t\tTileEntity tile = world.getTileEntity(pos);\n\t\tif (tile instanceof IPeripheral) {\n\t\t\tif (tile.getClass().getPackage().getName().startsWith(\"logisticspipes\")) {\n\t\t\t\treturn (IPeripheral) tile;\n\t\t\t}\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tif (((LogisticsTileGenericPipe) tile).pipe == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn new LPPeripheralTilePipeWrapper((LogisticsTileGenericPipe) tile, side);\n\t\t}\n\t\tif (tile instanceof LogisticsSolidTileEntity) {\n\t\t\treturn new LPPeripheralTileSolidWrapper((LogisticsSolidTileEntity) tile, side);\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/wrapper/CCCommandWrapper.java",
    "content": "package logisticspipes.proxy.cc.wrapper;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.LinkedList;\nimport javax.annotation.Nonnull;\n\nimport dan200.computercraft.api.lua.ILuaContext;\nimport dan200.computercraft.api.lua.ILuaObject;\nimport org.luaj.vm2.LuaTable;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCDirectCall;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\nimport logisticspipes.proxy.computers.wrapper.CCWrapperInformation;\nimport logisticspipes.proxy.computers.wrapper.ICommandWrapper;\nimport logisticspipes.security.PermissionException;\nimport logisticspipes.ticks.QueuedTasks;\n\npublic class CCCommandWrapper implements ILuaObject {\n\n\tpublic static final ICommandWrapper WRAPPER = CCCommandWrapper::new;\n\n\tprivate CCWrapperInformation info;\n\tprivate Object object;\n\tpublic boolean isDirectCall;\n\n\tpublic LuaTable table;\n\n\tpublic CCCommandWrapper(CCWrapperInformation info2, Object object2) {\n\t\tinfo = info2;\n\t\tobject = object2;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String[] getMethodNames() {\n\t\tLinkedList<String> list = new LinkedList<>();\n\t\tlist.add(\"help\");\n\t\tlist.add(\"commandHelp\");\n\t\tlist.add(\"getType\");\n\t\tfor (int i = 0; i < info.commandMap.size(); i++) {\n\t\t\tlist.add(info.commandMap.get(i));\n\t\t}\n\t\treturn list.toArray(new String[0]);\n\t}\n\n\t@Override\n\tpublic Object[] callMethod(@Nonnull ILuaContext context, int methodId, @Nonnull Object[] arguments) {\n\t\tif (methodId == 0) {\n\t\t\treturn help(arguments);\n\t\t}\n\t\tmethodId--;\n\t\tif (methodId == 0) {\n\t\t\treturn helpCommand(arguments);\n\t\t}\n\n\t\tmethodId--;\n\t\tif (methodId == 0) {\n\t\t\treturn CCObjectWrapper.createArray(info.type);\n\t\t}\n\t\tmethodId--;\n\n\t\tString name = info.commandMap.get(methodId);\n\t\tMethod match = null;\n\t\tfor (Method method : info.commands.values()) {\n\t\t\tif (!method.getName().equalsIgnoreCase(name)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!argumentsMatch(method, arguments)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmatch = method;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (match == null) {\n\t\t\tStringBuilder error = new StringBuilder();\n\t\t\terror.append(\"No such method.\");\n\t\t\tboolean handled = false;\n\t\t\tfor (Method method : info.commands.values()) {\n\t\t\t\tif (!method.getName().equalsIgnoreCase(name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (handled) {\n\t\t\t\t\terror.append(\"\\n\");\n\t\t\t\t}\n\t\t\t\thandled = true;\n\t\t\t\terror.append(method.getName());\n\t\t\t\terror.append(\"(\");\n\t\t\t\tboolean a = false;\n\t\t\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\t\t\tif (a) {\n\t\t\t\t\t\terror.append(\", \");\n\t\t\t\t\t}\n\t\t\t\t\terror.append(clazz.getName());\n\t\t\t\t\ta = true;\n\t\t\t\t}\n\t\t\t\terror.append(\")\");\n\t\t\t}\n\t\t\tif (!handled) {\n\t\t\t\terror = new StringBuilder();\n\t\t\t\terror.append(\"Internal Excption (Code: 1, \");\n\t\t\t\terror.append(name);\n\t\t\t\terror.append(\")\");\n\t\t\t}\n\t\t\tthrow new UnsupportedOperationException(error.toString());\n\t\t}\n\n\t\tif (match.getAnnotation(CCDirectCall.class) != null) {\n\t\t\tif (!isDirectCall) {\n\t\t\t\tthrow new PermissionException();\n\t\t\t}\n\t\t}\n\n\t\tif (match.getAnnotation(CCCommand.class).needPermission()) {\n\t\t\tif (info.securityMethod != null) {\n\t\t\t\ttry {\n\t\t\t\t\tinfo.securityMethod.invoke(object);\n\t\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\t\tif (e.getTargetException() instanceof Exception) {\n\t\t\t\t\t\tthrow new RuntimeException(e.getTargetException());\n\t\t\t\t\t}\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t} catch (IllegalAccessException | IllegalArgumentException e) {\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (match.getAnnotation(CCQueued.class) != null) {\n\t\t\tfinal Method m = match;\n\t\t\tfinal Object[] a = arguments;\n\t\t\tfinal Object[] resultArray = new Object[1];\n\t\t\tfinal Boolean[] booleans = new Boolean[2];\n\t\t\tbooleans[0] = false;\n\t\t\tbooleans[1] = false;\n\t\t\tQueuedTasks.queueTask(() -> {\n\t\t\t\ttry {\n\t\t\t\t\tObject result = m.invoke(object, a);\n\t\t\t\t\tif (result != null) {\n\t\t\t\t\t\tresultArray[0] = result;\n\t\t\t\t\t}\n\t\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\t\tif (e.getTargetException() instanceof PermissionException) {\n\t\t\t\t\t\tbooleans[1] = true;\n\t\t\t\t\t\tresultArray[0] = e.getTargetException();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbooleans[0] = true;\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbooleans[0] = true;\n\t\t\t\treturn null;\n\t\t\t});\n\t\t\tint count = 0;\n\t\t\twhile (!booleans[0] && count < 200) {\n\t\t\t\ttry {\n\t\t\t\t\tThread.sleep(10);\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t}\n\t\t\t\tcount++;\n\t\t\t}\n\t\t\tif (count >= 199) {\n\t\t\t\tLogisticsPipes.log.warn(\"CC call \" + m.getName() + \" on \" + object.getClass().getName() + \", (\" + object.toString() + \") took too long.\");\n\t\t\t\tthrow new RuntimeException(\"Took too long\");\n\t\t\t}\n\t\t\tif (m.getReturnType().equals(Void.class)) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (booleans[1]) {\n\t\t\t\t//PermissionException\n\t\t\t\tthrow ((RuntimeException) resultArray[0]);\n\t\t\t}\n\t\t\treturn CCObjectWrapper.createArray(CCObjectWrapper.getWrappedObject(resultArray[0], CCCommandWrapper.WRAPPER));\n\t\t}\n\t\tObject result;\n\t\ttry {\n\t\t\tresult = match.invoke(object, arguments);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tif (e.getTargetException() instanceof Exception) {\n\t\t\t\tthrow new RuntimeException(e.getTargetException());\n\t\t\t}\n\t\t\tthrow new RuntimeException(e);\n\t\t} catch (IllegalAccessException | IllegalArgumentException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\treturn CCObjectWrapper.createArray(CCObjectWrapper.getWrappedObject(result, CCCommandWrapper.WRAPPER));\n\t}\n\n\tprivate Object[] help(Object[] arguments) {\n\t\tStringBuilder help = new StringBuilder();\n\t\tStringBuilder head = new StringBuilder();\n\t\tStringBuilder head2 = new StringBuilder();\n\t\thead.append(\"Type: \");\n\t\thead.append(info.type);\n\t\thead.append(\"\\n\");\n\t\thead2.append(\"Commands: \\n\");\n\t\tfor (Integer num : info.commands.keySet()) {\n\t\t\tMethod method = info.commands.get(num);\n\t\t\tStringBuilder command = new StringBuilder();\n\t\t\tif (help.length() != 0) {\n\t\t\t\tcommand.append(\"\\n\");\n\t\t\t}\n\t\t\tint number = num.intValue();\n\t\t\tif (number < 10) {\n\t\t\t\tcommand.append(\" \");\n\t\t\t}\n\t\t\tcommand.append(number);\n\t\t\tcommand.append(\" \");\n\t\t\tif (method.isAnnotationPresent(CCDirectCall.class)) {\n\t\t\t\tcommand.append(\"D\");\n\t\t\t} else {\n\t\t\t\tcommand.append(\" \");\n\t\t\t}\n\t\t\tif (method.isAnnotationPresent(CCQueued.class)) {\n\t\t\t\tcommand.append(\"Q\");\n\t\t\t} else {\n\t\t\t\tcommand.append(\" \");\n\t\t\t}\n\t\t\tcommand.append(\": \");\n\t\t\tcommand.append(method.getName());\n\t\t\tStringBuilder param = new StringBuilder();\n\t\t\tparam.append(\"(\");\n\t\t\tboolean a = false;\n\t\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\t\tif (a) {\n\t\t\t\t\tparam.append(\", \");\n\t\t\t\t}\n\t\t\t\tparam.append(clazz.getSimpleName());\n\t\t\t\ta = true;\n\t\t\t}\n\t\t\tparam.append(\")\");\n\t\t\tif (param.toString().length() + command.length() > 36) {\n\t\t\t\tcommand.append(\"\\n      ---\");\n\t\t\t}\n\t\t\tcommand.append(param.toString());\n\t\t\thelp.append(command.toString());\n\t\t}\n\t\tString commands = help.toString();\n\t\tString[] lines = commands.split(\"\\n\");\n\t\tif (lines.length > 16) {\n\t\t\tint pageNumber = 1;\n\t\t\tif (arguments.length > 0) {\n\t\t\t\tif (arguments[0] instanceof Double) {\n\t\t\t\t\tpageNumber = (int) Math.floor((Double) arguments[0]);\n\t\t\t\t\tif (pageNumber < 1) {\n\t\t\t\t\t\tpageNumber = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tStringBuilder page = new StringBuilder();\n\t\t\tpage.append(head.toString());\n\t\t\tpage.append(\"Page \");\n\t\t\tpage.append(pageNumber);\n\t\t\tpage.append(\" of \");\n\t\t\tpage.append((int) (Math.floor(lines.length / 10) + (lines.length % 10 == 0 ? 0 : 1)));\n\t\t\tpage.append(\"\\n\");\n\t\t\tpage.append(head2.toString());\n\t\t\tpageNumber--;\n\t\t\tint from = pageNumber * 11;\n\t\t\tint to = pageNumber * 11 + 11;\n\t\t\tfor (int i = from; i < to; i++) {\n\t\t\t\tif (i < lines.length) {\n\t\t\t\t\tpage.append(lines[i]);\n\t\t\t\t}\n\t\t\t\tif (i < to - 1) {\n\t\t\t\t\tpage.append(\"\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn new Object[] { page.toString() };\n\t\t} else {\n\t\t\tfor (int i = 0; i < 16 - lines.length; i++) {\n\t\t\t\tString buffer = head.toString();\n\t\t\t\thead = new StringBuilder();\n\t\t\t\thead.append(\"\\n\").append(buffer);\n\t\t\t}\n\t\t}\n\t\treturn new Object[] { String.format(\"%s%s%s\", head, head2, help) };\n\t}\n\n\tprivate Object[] helpCommand(Object[] arguments) {\n\t\tif (arguments.length != 1) {\n\t\t\treturn new Object[] { \"Wrong Argument Count\" };\n\t\t}\n\t\tif (!(arguments[0] instanceof Double)) {\n\t\t\treturn new Object[] { \"Wrong Argument Type\" };\n\t\t}\n\t\tInteger number = (int) Math.floor(((Double) arguments[0]));\n\t\tif (!info.commands.containsKey(number)) {\n\t\t\treturn new Object[] { \"No command with that index\" };\n\t\t}\n\t\tMethod method = info.commands.get(number);\n\t\tStringBuilder help = new StringBuilder();\n\t\thelp.append(\"---------------------------------\\n\");\n\t\thelp.append(\"Command: \");\n\t\thelp.append(method.getName());\n\t\thelp.append(\"\\n\");\n\t\thelp.append(\"Parameter: \");\n\t\tif (method.getParameterTypes().length > 0) {\n\t\t\thelp.append(\"\\n\");\n\t\t\tboolean a = false;\n\t\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\t\tif (a) {\n\t\t\t\t\thelp.append(\", \");\n\t\t\t\t}\n\t\t\t\thelp.append(clazz.getSimpleName());\n\t\t\t\ta = true;\n\t\t\t}\n\t\t\thelp.append(\"\\n\");\n\t\t} else {\n\t\t\thelp.append(\"NONE\\n\");\n\t\t}\n\t\thelp.append(\"Return Type: \");\n\t\thelp.append(method.getReturnType().getName());\n\t\thelp.append(\"\\n\");\n\t\thelp.append(\"Description: \\n\");\n\t\thelp.append(method.getAnnotation(CCCommand.class).description());\n\t\treturn new Object[] { help.toString() };\n\t}\n\n\tprivate boolean argumentsMatch(Method method, Object[] arguments) {\n\t\tint i = 0;\n\t\tfor (Class<?> args : method.getParameterTypes()) {\n\t\t\tif (arguments.length <= i) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!args.isAssignableFrom(arguments[i].getClass())) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t//if(!arguments[i].getClass().equals(args)) return false;\n\t\t\ti++;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic String getType() {\n\t\treturn info.type;\n\t}\n\n\tpublic Object getObject() {\n\t\treturn object;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/wrapper/LPPeripheralTilePipeWrapper.java",
    "content": "package logisticspipes.proxy.cc.wrapper;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.EnumFacing;\n\nimport dan200.computercraft.api.lua.ILuaContext;\nimport dan200.computercraft.api.peripheral.IComputerAccess;\nimport dan200.computercraft.api.peripheral.IPeripheral;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\n\npublic class LPPeripheralTilePipeWrapper implements IPeripheral {\n\n\tprivate final EnumFacing dir;\n\tprivate CCCommandWrapper wrapped;\n\tprivate LogisticsTileGenericPipe pipe;\n\n\tpublic LPPeripheralTilePipeWrapper(LogisticsTileGenericPipe pipe, EnumFacing dir) {\n\t\tthis.pipe = pipe;\n\t\twrapped = (CCCommandWrapper) CCObjectWrapper.checkForAnnotations(pipe.pipe, CCCommandWrapper.WRAPPER);\n\t\tthis.dir = dir;\n\t}\n\n\t@Override\n\tpublic Object[] callMethod(@Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments) {\n\t\tpipe.currentPC = computer;\n\t\twrapped.isDirectCall = true;\n\t\tObject[] result = wrapped.callMethod(context, method, arguments);\n\t\tpipe.currentPC = null;\n\t\twrapped.isDirectCall = false;\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void attach(@Nonnull IComputerAccess computer) {\n\t\tpipe.connections.put(computer, dir);\n\t\tpipe.scheduleNeighborChange();\n\t}\n\n\t@Override\n\tpublic void detach(@Nonnull IComputerAccess computer) {\n\t\tpipe.connections.remove(computer);\n\t}\n\n\t@Override\n\tpublic boolean equals(IPeripheral other) {\n\t\tif (other instanceof LPPeripheralTilePipeWrapper) {\n\t\t\treturn ((LPPeripheralTilePipeWrapper) other).pipe.equals(pipe);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getType() {\n\t\treturn wrapped.getType();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String[] getMethodNames() {\n\t\treturn wrapped.getMethodNames();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cc/wrapper/LPPeripheralTileSolidWrapper.java",
    "content": "package logisticspipes.proxy.cc.wrapper;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.EnumFacing;\n\nimport dan200.computercraft.api.lua.ILuaContext;\nimport dan200.computercraft.api.peripheral.IComputerAccess;\nimport dan200.computercraft.api.peripheral.IPeripheral;\n\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\n\npublic class LPPeripheralTileSolidWrapper implements IPeripheral {\n\n\tprivate CCCommandWrapper wrapped;\n\tprivate LogisticsSolidTileEntity tile;\n\n\tpublic LPPeripheralTileSolidWrapper(LogisticsSolidTileEntity tile, EnumFacing dir) {\n\t\tthis.tile = tile;\n\t\twrapped = (CCCommandWrapper) CCObjectWrapper.checkForAnnotations(tile, CCCommandWrapper.WRAPPER);\n\t}\n\n\t@Override\n\tpublic Object[] callMethod(@Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments) {\n\t\twrapped.isDirectCall = true;\n\t\tObject[] result = wrapped.callMethod(context, method, arguments);\n\t\twrapped.isDirectCall = false;\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void attach(@Nonnull IComputerAccess computer) {}\n\n\t@Override\n\tpublic void detach(@Nonnull IComputerAccess computer) {}\n\n\t@Override\n\tpublic boolean equals(IPeripheral other) {\n\t\tif (other instanceof LPPeripheralTileSolidWrapper) {\n\t\t\treturn ((LPPeripheralTileSolidWrapper) other).tile.equals(tile);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getType() {\n\t\treturn wrapped.getType();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String[] getMethodNames() {\n\t\treturn wrapped.getMethodNames();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ccl/CCLProxy.java",
    "content": "package logisticspipes.proxy.ccl;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\n\nimport net.minecraftforge.common.model.IModelState;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport codechicken.lib.render.CCModel;\nimport codechicken.lib.render.CCRenderState;\nimport codechicken.lib.render.OBJParser;\nimport codechicken.lib.render.pipeline.ColourMultiplier;\nimport codechicken.lib.util.TransformUtils;\nimport codechicken.lib.vec.Rotation;\nimport codechicken.lib.vec.Scale;\nimport codechicken.lib.vec.Transformation;\nimport codechicken.lib.vec.Translation;\nimport codechicken.lib.vec.Vector3;\nimport codechicken.lib.vec.uv.IconTransformation;\nimport codechicken.lib.vec.uv.UVScale;\nimport codechicken.lib.vec.uv.UVTransformation;\nimport codechicken.lib.vec.uv.UVTransformationList;\nimport codechicken.lib.vec.uv.UVTranslation;\n\nimport logisticspipes.proxy.DontLoadProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.interfaces.ICCLProxy;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.IRenderState;\nimport logisticspipes.proxy.object3d.interfaces.ITranslation;\nimport logisticspipes.proxy.object3d.interfaces.IVec3;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\n\npublic class CCLProxy implements ICCLProxy {\n\n\tpublic CCLProxy() {\n\t\ttry {\n\t\t\tCCModel.class.getName();\n\t\t} catch (Throwable e) {\n\t\t\tthrow new DontLoadProxy();\n\t\t}\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic TextureTransformation createIconTransformer(TextureAtlasSprite registerIcon) {\n\t\tfinal IconTransformation icon = new IconTransformation(registerIcon);\n\t\treturn new TextureTransformation() {\n\n\t\t\t@Override\n\t\t\tpublic Object getOriginal() {\n\t\t\t\treturn icon;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void update(TextureAtlasSprite registerIcon) {\n\t\t\t\ticon.icon = registerIcon;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic TextureAtlasSprite getTexture() {\n\t\t\t\treturn icon.icon;\n\t\t\t}\n\n\t\t};\n\t}\n\n\t@Override\n\tpublic IRenderState getRenderState() {\n\t\treturn new IRenderState() {\n\n\t\t\t@Override\n\t\t\tpublic void reset() {\n\t\t\t\tCCRenderState.instance().reset();\n\t\t\t\tCCRenderState.instance().computeLighting = false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void setAlphaOverride(int i) {\n\t\t\t\tCCRenderState.instance().alphaOverride = i;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void draw() {\n\t\t\t\tCCRenderState.instance().draw();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void setBrightness(IBlockAccess world, BlockPos pos) {\n\t\t\t\tCCRenderState.instance().setBrightness(world, pos);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@SideOnly(Side.CLIENT)\n\t\t\tpublic void startDrawing(int mode, VertexFormat format) {\n\t\t\t\tCCRenderState.instance().startDrawing(mode, format);\n\t\t\t}\n\n\t\t};\n\t}\n\n\t@Override\n\tpublic Map<String, IModel3D> parseObjModels(InputStream resourceAsStream, int i, LPScale scale) throws IOException {\n\t\tMap<String, IModel3D> target = new HashMap<>();\n\t\tMap<String, CCModel> source = OBJParser.parseModels(resourceAsStream, i, (Transformation) scale.getOriginal());\n\t\tfor (Entry<String, CCModel> entry : source.entrySet()) {\n\t\t\ttarget.put(entry.getKey(), SimpleServiceLocator.cclProxy.wrapModel(entry.getValue()));\n\t\t}\n\t\treturn target;\n\t}\n\n\t@Override\n\tpublic Object getRotation(int i, int j) {\n\t\treturn Rotation.sideOrientation(i, j);\n\t}\n\n\t@Override\n\tpublic Object getScale(double d, double e, double f) {\n\t\treturn new Scale(d, e, f);\n\t}\n\n\t@Override\n\tpublic Object getScale(double d) {\n\t\treturn new Scale(d);\n\t}\n\n\t@Override\n\tpublic ITranslation getTranslation(double d, double e, double f) {\n\t\treturn new TransformationProxy(new Translation(d, e, f));\n\t}\n\n\t@Override\n\tpublic ITranslation getTranslation(IVec3 vec) {\n\t\tfinal Translation translation;\n\t\tif (vec.getOriginal() instanceof Vector3) {\n\t\t\ttranslation = new Translation((Vector3) vec.getOriginal());\n\t\t} else {\n\t\t\ttranslation = new Translation(vec.x(), vec.y(), vec.z());\n\t\t}\n\t\treturn new TransformationProxy(translation);\n\t}\n\n\t@Override\n\tpublic Object getUVScale(double i, double d) {\n\t\treturn new UVScale(i, d);\n\t}\n\n\t@Override\n\tpublic Object getUVTranslation(float i, float f) {\n\t\treturn new UVTranslation(i, f);\n\t}\n\n\t@Override\n\tpublic Object getUVTransformationList(I3DOperation[] uvTranslation) {\n\t\tList<UVTransformation> transforms = new ArrayList<>();\n\t\tfor (I3DOperation op : uvTranslation) {\n\t\t\ttransforms.add((UVTransformation) op.getOriginal());\n\t\t}\n\t\treturn new UVTransformationList(transforms.toArray(new UVTransformation[0]));\n\t}\n\n\t@Override\n\tpublic IModel3D wrapModel(Object oModel) {\n\t\tfinal CCModel model = (CCModel) oModel;\n\t\treturn new Model3D(model);\n\t}\n\n\t@Override\n\tpublic boolean isActivated() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic Object getRotation(double d, int i, int j, int k) {\n\t\treturn new Rotation(d, i, j, k);\n\t}\n\n\t@Override\n\tpublic IModel3D combine(Collection<IModel3D> list) {\n\t\tList<CCModel> collection = new ArrayList<>(list.size());\n\t\tcollection.addAll(list.stream().map(model -> (CCModel) model.getOriginal()).collect(Collectors.toList()));\n\t\treturn SimpleServiceLocator.cclProxy.wrapModel(CCModel.combine(collection));\n\t}\n\n\t@Override\n\tpublic Object getColourMultiplier(int i) {\n\t\treturn ColourMultiplier.instance(i);\n\t}\n\n\t@Override\n\tpublic IModelState getDefaultBlockState() {\n\t\treturn TransformUtils.DEFAULT_BLOCK;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ccl/Model3D.java",
    "content": "package logisticspipes.proxy.ccl;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.Vec3d;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport codechicken.lib.lighting.LightModel;\nimport codechicken.lib.render.CCModel;\nimport codechicken.lib.render.CCRenderState;\nimport codechicken.lib.render.buffer.BakingVertexBuffer;\nimport codechicken.lib.render.pipeline.IVertexOperation;\nimport codechicken.lib.vec.Cuboid6;\nimport codechicken.lib.vec.Rotation;\nimport codechicken.lib.vec.Scale;\nimport codechicken.lib.vec.Transformation;\nimport codechicken.lib.vec.Translation;\nimport codechicken.lib.vec.Vertex5;\nimport codechicken.lib.vec.uv.IconTransformation;\nimport codechicken.lib.vec.uv.UVTransformation;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport lombok.SneakyThrows;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IBounds;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.IVec3;\n\npublic class Model3D implements IModel3D {\n\n\tprivate static final Field spiteMap;\n\tprivate static final HashMap<Integer, TextureAtlasSprite> emptyHashMap = new HashMap<>();\n\n\tstatic {\n\t\tif (FMLCommonHandler.instance().getSide() == Side.CLIENT) {\n\t\t\ttry {\n\t\t\t\tspiteMap = BakingVertexBuffer.class.getDeclaredField(\"spriteMap\");\n\t\t\t\tspiteMap.setAccessible(true);\n\t\t\t} catch (NoSuchFieldException e) {\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t} else {\n\t\t\tspiteMap = null;\n\t\t}\n\t}\n\n\tprivate final CCModel model;\n\tpublic Cache<Integer, List<BakedQuad>> renderCache = CacheBuilder.newBuilder().build();\n\n\tpublic Model3D(CCModel model) {\n\t\tif (model == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\tthis.model = model;\n\t}\n\n\t@Override\n\tpublic void render(I3DOperation... i3dOperations) {\n\t\tList<IVertexOperation> list = new ArrayList<>();\n\t\tfor (I3DOperation op : i3dOperations) {\n\t\t\tlist.add((IVertexOperation) op.getOriginal());\n\t\t}\n\t\tmodel.render(CCRenderState.instance(), list.toArray(new IVertexOperation[0]));\n\t}\n\n\tprivate String atlasString(TextureAtlasSprite sprite) {\n\t\treturn \"name='\" + sprite.getIconName() + \"', x=\" + sprite.getOriginX() + \", y=\" + sprite.getOriginY() + \", height=\" + sprite.getIconHeight() + \", width=\" + sprite.getIconWidth() + \", u0=\" + sprite.getMinU() + \", u1=\" + sprite.getMaxU() + \", v0=\" + sprite.getMinV() + \", v1=\" + sprite.getMaxV() + \"}\";\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@SneakyThrows({ IllegalAccessException.class })\n\tpublic List<BakedQuad> renderToQuads(VertexFormat format, I3DOperation... i3dOperations) {\n\t\tList<IVertexOperation> list = new ArrayList<>();\n\t\tSet<String> hash = new HashSet<>();\n\t\thash.add(String.valueOf(format.hashCode()));\n\t\tboolean cachable = true;\n\n\t\tfor (I3DOperation op : i3dOperations) {\n\t\t\tIVertexOperation iVertexOperation = (IVertexOperation) op.getOriginal();\n\t\t\tlist.add(iVertexOperation);\n\t\t\tif (iVertexOperation instanceof IconTransformation) {\n\t\t\t\thash.add(atlasString(((IconTransformation) iVertexOperation).icon));\n\t\t\t} else if (iVertexOperation instanceof Rotation) {\n\t\t\t\thash.add(iVertexOperation.toString());\n\t\t\t} else if (iVertexOperation instanceof Scale) {\n\t\t\t\thash.add(iVertexOperation.toString());\n\t\t\t} else if (iVertexOperation instanceof Translation) {\n\t\t\t\thash.add(iVertexOperation.toString());\n\t\t\t} else {\n\t\t\t\tcachable = false;\n\t\t\t}\n\t\t}\n\n\t\tif (cachable) {\n\t\t\tList<BakedQuad> content = renderCache.getIfPresent(hash.hashCode());\n\t\t\tif (content != null) {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}\n\n\t\tBakingVertexBuffer buffer = BakingVertexBuffer.create();\n\t\tCCRenderState ccrs = CCRenderState.instance();\n\t\tccrs.reset();\n\t\tccrs.startDrawing(0x7, format, buffer);\n\t\tmodel.render(ccrs, list.toArray(new IVertexOperation[0]));\n\t\tbuffer.finishDrawing();\n\n\t\temptyHashMap.clear();\n\t\tif (spiteMap != null) {\n\t\t\tspiteMap.set(buffer, emptyHashMap);\n\t\t}\n\n\t\tList<BakedQuad> quads = buffer.bake();\n\t\tif (cachable) {\n\t\t\trenderCache.put(hash.hashCode(), quads);\n\t\t}\n\t\treturn quads;\n\t}\n\n\t@Override\n\tpublic IModel3D copy() {\n\t\treturn SimpleServiceLocator.cclProxy.wrapModel(model.copy());\n\t}\n\n\t@Override\n\tpublic void computeStandardLighting() {\n\t\tmodel.computeLighting(LightModel.standardLightModel);\n\t}\n\n\t@Override\n\tpublic void computeNormals() {\n\t\tmodel.computeNormals();\n\t}\n\n\t@Override\n\tpublic IBounds bounds() {\n\t\treturn wrap(model.bounds());\n\t}\n\n\tprivate IBounds wrap(final Cuboid6 bounds) {\n\t\treturn new IBounds() {\n\n\t\t\t@Override\n\t\t\tpublic IVec3 min() {\n\t\t\t\treturn new IVec3() {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic double z() {\n\t\t\t\t\t\treturn bounds.min.z;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic double y() {\n\t\t\t\t\t\treturn bounds.min.y;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic double x() {\n\t\t\t\t\t\treturn bounds.min.x;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Object getOriginal() {\n\t\t\t\t\t\treturn bounds.min;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic IVec3 max() {\n\t\t\t\treturn new IVec3() {\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic double z() {\n\t\t\t\t\t\treturn bounds.max.z;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic double y() {\n\t\t\t\t\t\treturn bounds.max.y;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic double x() {\n\t\t\t\t\t\treturn bounds.max.x;\n\t\t\t\t\t}\n\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic Object getOriginal() {\n\t\t\t\t\t\treturn bounds.max;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic AxisAlignedBB toAABB() {\n\t\t\t\treturn bounds.aabb();\n\t\t\t}\n\t\t};\n\t}\n\n\t@Override\n\tpublic IModel3D backfacedCopy() {\n\t\treturn SimpleServiceLocator.cclProxy.wrapModel(model.backfacedCopy());\n\t}\n\n\t@Override\n\tpublic IModel3D apply(I3DOperation translation) {\n\t\tif (translation.getOriginal() instanceof UVTransformation) {\n\t\t\treturn SimpleServiceLocator.cclProxy.wrapModel(model.apply((UVTransformation) translation.getOriginal()));\n\t\t} else if (translation.getOriginal() instanceof Transformation) {\n\t\t\treturn SimpleServiceLocator.cclProxy.wrapModel(model.apply((Transformation) translation.getOriginal()));\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(translation.getOriginal().getClass().toString());\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (obj instanceof Model3D) {\n\t\t\treturn ((Model3D) obj).model.equals(model);\n\t\t}\n\t\treturn super.equals(obj);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn model.hashCode();\n\t}\n\n\t@Override\n\tpublic IModel3D twoFacedCopy() {\n\t\treturn SimpleServiceLocator.cclProxy.wrapModel(model.twoFacedCopy());\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn model;\n\t}\n\n\t@Override\n\tpublic IBounds getBoundsInside(AxisAlignedBB boundingBox) {\n\t\tCuboid6 c = null;\n\t\tfor (Vertex5 v : model.verts) {\n\t\t\tif (boundingBox.contains(new Vec3d(v.vec.x, v.vec.y, v.vec.z))) {\n\t\t\t\tif (c == null) {\n\t\t\t\t\tc = new Cuboid6(v.vec.copy(), v.vec.copy());\n\t\t\t\t} else {\n\t\t\t\t\tc.enclose(v.vec);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (c == null) return null;\n\t\treturn wrap(c);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ccl/TransformationProxy.java",
    "content": "package logisticspipes.proxy.ccl;\n\nimport codechicken.lib.vec.Transformation;\n\nimport logisticspipes.proxy.object3d.interfaces.ITranslation;\n\npublic class TransformationProxy implements ITranslation {\n\n\tprivate final Transformation transformation;\n\n\tpublic TransformationProxy(Transformation transformation) {\n\t\tthis.transformation = transformation;\n\t}\n\n\t@Override\n\tpublic ITranslation inverse() {\n\t\treturn new TransformationProxy(transformation.inverse());\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn transformation;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cofh/CoFHToolHammer.java",
    "content": "package logisticspipes.proxy.cofh;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\n\nimport cofh.api.item.IToolHammer;\n\nimport logisticspipes.api.ILPPipeConfigTool;\nimport logisticspipes.api.ILPPipeTile;\nimport logisticspipes.proxy.interfaces.ILPPipeConfigToolWrapper;\n\npublic class CoFHToolHammer implements ILPPipeConfigToolWrapper {\n\n\t@Override\n\tpublic ILPPipeConfigTool getWrappedTool(@Nonnull ItemStack stack) {\n\t\tif (stack.getItem() instanceof IToolHammer) {\n\t\t\treturn new ILPPipeConfigTool() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean canWrench(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\t\t\t\tif (wrench.isEmpty() || !(wrench.getItem() instanceof IToolHammer)) return false;\n\t\t\t\t\treturn ((IToolHammer) wrench.getItem()).isUsable(wrench, player, pipe.getBlockPos());\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void wrenchUsed(EntityPlayer player, @Nonnull ItemStack wrench, ILPPipeTile pipe) {\n\t\t\t\t\tif (wrench.isEmpty() || !(wrench.getItem() instanceof IToolHammer)) return;\n\t\t\t\t\t((IToolHammer) wrench.getItem()).toolUsed(wrench, player, pipe.getBlockPos());\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cofh/subproxies/ICoFHEnergyReceiver.java",
    "content": "package logisticspipes.proxy.cofh.subproxies;\n\nimport net.minecraft.util.EnumFacing;\n\npublic interface ICoFHEnergyReceiver {\n\n\tint getMaxEnergyStored();\n\n\tint getEnergyStored();\n\n\tint receiveEnergy(EnumFacing opposite, int i, boolean b);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/cofh/subproxies/ICoFHEnergyStorage.java",
    "content": "package logisticspipes.proxy.cofh.subproxies;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\npublic interface ICoFHEnergyStorage {\n\n\tint extractEnergy(int space, boolean b);\n\n\tint receiveEnergy(int maxReceive, boolean simulate);\n\n\tint getEnergyStored();\n\n\tint getMaxEnergyStored();\n\n\tvoid readFromNBT(NBTTagCompound nbt);\n\n\tvoid writeToNBT(NBTTagCompound nbt);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/CCCommand.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface CCCommand {\n\n\tString description() default \"\";\n\n\tboolean needPermission() default true;\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/CCDirectCall.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface CCDirectCall {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/CCQueued.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface CCQueued {}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/CCSecurtiyCheck.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.METHOD)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface CCSecurtiyCheck {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/CCType.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface CCType {\n\n\tString name();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/ICCTypeWrapped.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\npublic interface ICCTypeWrapped {\n\n\tObject getObject();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/ILPCCTypeDefinition.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\npublic interface ILPCCTypeDefinition {\n\n\tICCTypeWrapped getTypeFor(Object input);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/interfaces/ILPCCTypeHolder.java",
    "content": "package logisticspipes.proxy.computers.interfaces;\n\npublic interface ILPCCTypeHolder {\n\n\t/**\n\t * Returns the type holder for the CC/OC interoperability.\n\t *\n\t * @return an object array with at least one element.\n\t */\n\tObject[] getTypeHolder();\n\n\tdefault void setCCType(Object type) {\n\t\tgetTypeHolder()[0] = type;\n\t}\n\n\tdefault Object getCCType() {\n\t\treturn getTypeHolder()[0];\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCFilterInventory.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\n@CCType(name = \"FilterInventory\")\npublic class CCFilterInventory {\n\n\tprivate final IItemIdentifierInventory inv;\n\n\tpublic CCFilterInventory(IItemIdentifierInventory inv) {\n\t\tthis.inv = inv;\n\t}\n\n\t@CCCommand(description = \"Returns the size of this FilterInventory\")\n\tpublic int getSizeInventory() {\n\t\treturn inv.getSizeInventory();\n\t}\n\n\t@CCCommand(description = \"Returns the ItemIdentifier in the given slot\")\n\t@CCQueued\n\tpublic ItemIdentifier getItemIdentifier(Double slot) {\n\t\tint s = slot.intValue();\n\t\tif (s <= 0 || s > getSizeInventory()) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot out of Inventory\");\n\t\t}\n\t\tif (s != slot) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot not an Integer\");\n\t\t}\n\t\ts--;\n\t\tif (inv.getIDStackInSlot(s) == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn inv.getIDStackInSlot(s).getItem();\n\t}\n\n\t@CCCommand(description = \"Sets the ItemIdentifier at the given slot\")\n\t@CCQueued\n\tpublic void setItemIdentifier(Double slot, ItemIdentifier ident) {\n\t\tint s = slot.intValue();\n\t\tif (s <= 0 || s > getSizeInventory()) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot out of Inventory\");\n\t\t}\n\t\tif (s != slot) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot not an Integer\");\n\t\t}\n\t\ts--;\n\t\tinv.setInventorySlotContents(s, ident.makeStack(1));\n\t}\n\n\t@CCCommand(description = \"Sets the ItemIdentifierStack at the given slot\")\n\t@CCQueued\n\tpublic void clearSlot(Double slot) {\n\t\tint s = slot.intValue();\n\t\tif (s <= 0 || s > getSizeInventory()) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot out of Inventory\");\n\t\t}\n\t\tif (s != slot) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot not an Integer\");\n\t\t}\n\t\ts--;\n\t\tinv.setInventorySlotContents(s, (ItemIdentifierStack) null);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCFluidIdentifier.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class CCFluidIdentifier implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object ident) {\n\t\treturn new CCFluidIdentifierImplementation((FluidIdentifier) ident);\n\t}\n\n\t@CCType(name = \"FluidIdentifier\")\n\tpublic static class CCFluidIdentifierImplementation implements ICCTypeWrapped {\n\n\t\tfinal FluidIdentifier ident;\n\n\t\tpublic CCFluidIdentifierImplementation(FluidIdentifier ident2) {\n\t\t\tident = ident2;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the fluidIdentifier of this FluidIdentifier\")\n\t\tpublic String getId() {\n\t\t\treturn ident.fluidID;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns true if this FluidIdentifier has an tag\")\n\t\tpublic boolean hasTagCompound() {\n\t\t\treturn ident.tag != null;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the tag of this FluidIdentifier\")\n\t\tpublic NBTTagCompound getTagCompound() {\n\t\t\treturn ident.tag;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the Name of this FluidIdentifier\")\n\t\tpublic String getName() {\n\t\t\treturn ident.getName();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns an ItemIdentifier if one exists for this FluidIdentifier\")\n\t\tpublic ItemIdentifier getItemIdentifier() {\n\t\t\treturn ident.getItemIdentifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic FluidIdentifier getObject() {\n\t\t\treturn ident;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCItemIdentifier.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class CCItemIdentifier implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object ident) {\n\t\treturn new CCItemIdentifierImplementation((ItemIdentifier) ident);\n\t}\n\n\t@CCType(name = \"ItemIdentifier\")\n\tpublic static class CCItemIdentifierImplementation implements ICCTypeWrapped {\n\n\t\tfinal ItemIdentifier ident;\n\n\t\tpublic CCItemIdentifierImplementation(ItemIdentifier ident2) {\n\t\t\tident = ident2;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the itemID (int) of this ItemIdentifier\")\n\t\tpublic int getId() {\n\t\t\treturn Item.getIdFromItem(ident.item);\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the itemID (String) of this ItemIdentifier\")\n\t\tpublic String getIdName() {\n\t\t\treturn Item.REGISTRY.getNameForObject(ident.item).toString();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the data/damage of this ItemIdentifier\")\n\t\tpublic int getData() {\n\t\t\treturn ident.itemDamage;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns true if this ItemIdentifier is damagable\")\n\t\tpublic boolean isDamageable() {\n\t\t\treturn ident.isDamageable();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns true if this ItemIdentifier has an tag\")\n\t\tpublic boolean hasTagCompound() {\n\t\t\treturn ident.tag != null;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the tag of this ItemIdentifier\")\n\t\tpublic NBTTagCompound getTagCompound() {\n\t\t\treturn ident.tag;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns this ItemIdentifier in it's undamaged version\")\n\t\tpublic ItemIdentifier getUndamaged() {\n\t\t\treturn ident.getUndamaged();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns this ItemIdentifier without NBT tag information\")\n\t\tpublic ItemIdentifier getIgnoringNBT() {\n\t\t\treturn ident.getIgnoringNBT();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the Name of this ItemIdentifier\")\n\t\tpublic String getName() {\n\t\t\treturn ident.getFriendlyNameCC();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the name of the mod this ItemIdentifier belongs to\")\n\t\tpublic String getModName() {\n\t\t\treturn ident.getModName();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns a new ItemIdentifierStack\")\n\t\tpublic ItemIdentifierStack makeStack(Double stackSize) {\n\t\t\treturn ident.makeStack(stackSize.intValue());\n\t\t}\n\n\t\t@CCCommand(description = \"Returns true if this ItemIdentifier represents an FluidIdentifier\")\n\t\tpublic boolean isFluidContainer() {\n\t\t\treturn ident.isFluidContainer();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns an FluidIdentifier if one exists for this ItemIdentifier\")\n\t\tpublic FluidIdentifier getFluidContainer() {\n\t\t\treturn FluidIdentifier.get(ident);\n\t\t}\n\n\t\t@Override\n\t\tpublic ItemIdentifier getObject() {\n\t\t\treturn ident;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCItemIdentifierBuilder.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport java.util.List;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.utils.item.ItemIdentifier;\n\n@CCType(name = \"ItemIdentifierBuilder\")\npublic class CCItemIdentifierBuilder implements ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate int itemID = 0;\n\tprivate String itemIDName = null;\n\tprivate int itemData = 0;\n\n\t@CCCommand(description = \"Set the itemID for this ItemIdentifierBuilder\")\n\tpublic void setItemID(Double id) {\n\t\titemID = id.intValue();\n\t\titemIDName = null;\n\t}\n\n\t@CCCommand(description = \"Set the itemID for this ItemIdentifierBuilder\")\n\tpublic void setItemID(String id) {\n\t\titemID = 0;\n\t\titemIDName = id;\n\t}\n\n\t@CCCommand(description = \"Returns the itemID (String or Int) for this ItemIdentifierBuilder\")\n\tpublic Object getItemID() {\n\t\tif (itemIDName != null) {\n\t\t\treturn itemIDName;\n\t\t}\n\t\treturn itemID;\n\t}\n\n\t@CCCommand(description = \"Set the item data/damage for this ItemIdentifierBuilder\")\n\tpublic void setItemData(Double data) {\n\t\titemData = data.intValue();\n\t}\n\n\t@CCCommand(description = \"Returns the item data/damage for this ItemIdentifierBuilder\")\n\tpublic int getItemData() {\n\t\treturn itemData;\n\t}\n\n\t@CCCommand(description = \"Returns the ItemIdentifier for this ItemIdentifierBuilder\")\n\tpublic ItemIdentifier build() {\n\t\tItem item;\n\t\tif (itemIDName != null) {\n\t\t\titem = Item.REGISTRY.getObject(new ResourceLocation(itemIDName));\n\t\t} else {\n\t\t\titem = Item.getItemById(itemID);\n\t\t}\n\t\tif (item == null) {\n\t\t\tthrow new UnsupportedOperationException(\"Not a valid ItemIdentifier\");\n\t\t}\n\t\treturn ItemIdentifier.get(item, itemData, null);\n\t}\n\n\t@CCCommand(description = \"Returns a list of all ItemIdentifier with an NBT tag matching the given Item ID and data\")\n\tpublic List<ItemIdentifier> matchingNBTIdentifier() {\n\t\tItem item = Item.REGISTRY.getObjectById(itemID);\n\t\tif (item == null) {\n\t\t\tthrow new UnsupportedOperationException(\"Not a valid ItemIdentifier\");\n\t\t}\n\t\treturn ItemIdentifier.getMatchingNBTIdentifier(item, itemData);\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCItemIdentifierInventory.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\n@CCType(name = \"FilterInventory\")\npublic class CCItemIdentifierInventory {\n\n\tprivate final IItemIdentifierInventory inv;\n\n\tpublic CCItemIdentifierInventory(IItemIdentifierInventory inv) {\n\t\tthis.inv = inv;\n\t}\n\n\t@CCCommand(description = \"Returns the size of this FilterInventory\")\n\tpublic int getSizeInventory() {\n\t\treturn inv.getSizeInventory();\n\t}\n\n\t@CCCommand(description = \"Returns the ItemIdentifierStack in the given slot\")\n\t@CCQueued\n\tpublic ItemIdentifierStack getItemIdentifierStack(Double slot) {\n\t\tint s = slot.intValue();\n\t\tif (s <= 0 || s > getSizeInventory()) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot out of Inventory\");\n\t\t}\n\t\tif (s != slot) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot not an Integer\");\n\t\t}\n\t\ts--;\n\t\treturn inv.getIDStackInSlot(s);\n\t}\n\n\t@CCCommand(description = \"Sets the ItemIdentifierStack at the given slot\")\n\t@CCQueued\n\tpublic void setItemIdentifierStack(Double slot, ItemIdentifierStack stack) {\n\t\tint s = slot.intValue();\n\t\tif (s <= 0 || s > getSizeInventory()) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot out of Inventory\");\n\t\t}\n\t\tif (s != slot) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot not an Integer\");\n\t\t}\n\t\ts--;\n\t\tinv.setInventorySlotContents(s, stack);\n\t}\n\n\t@CCCommand(description = \"Sets the ItemIdentifierStack at the given slot\")\n\t@CCQueued\n\tpublic void clearSlot(Double slot) {\n\t\tint s = slot.intValue();\n\t\tif (s <= 0 || s > getSizeInventory()) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot out of Inventory\");\n\t\t}\n\t\tif (s != slot) {\n\t\t\tthrow new UnsupportedOperationException(\"Slot not an Integer\");\n\t\t}\n\t\ts--;\n\t\tinv.setInventorySlotContents(s, (ItemIdentifierStack) null);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCItemIdentifierStack.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class CCItemIdentifierStack implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object stack) {\n\t\treturn new CCItemIdentifierStackImplementation((ItemIdentifierStack) stack);\n\t}\n\n\t@CCType(name = \"ItemIdentifierStack\")\n\tpublic static class CCItemIdentifierStackImplementation implements ICCTypeWrapped {\n\n\t\tfinal ItemIdentifierStack stack;\n\n\t\tpublic CCItemIdentifierStackImplementation(ItemIdentifierStack stack2) {\n\t\t\tstack = stack2;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the ItemIdentifier from this ItemIdentifierStack\")\n\t\tpublic ItemIdentifier getItem() {\n\t\t\treturn stack.getItem();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the size of this ItemIdentifierStack\")\n\t\tpublic int getStackSize() {\n\t\t\treturn stack.getStackSize();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the name of this ItemIdentifierStack\")\n\t\tpublic String getName() {\n\t\t\treturn stack.getFriendlyName();\n\t\t}\n\n\t\t@CCCommand(description = \"Compares this ItemIdentifierStack to another one\")\n\t\tpublic boolean equals(ItemIdentifierStack stack) {\n\t\t\treturn this.stack.equals(stack);\n\t\t}\n\n\t\t@Override\n\t\tpublic ItemIdentifierStack getObject() {\n\t\t\treturn stack;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCPair.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class CCPair implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object input) {\n\t\treturn new CCPairImplementation((Pair<?, ?>) input);\n\t}\n\n\t@CCType(name = \"Pair\")\n\tpublic static class CCPairImplementation implements ICCTypeWrapped {\n\n\t\tprivate final Pair<?, ?> pair;\n\n\t\tprotected CCPairImplementation(Pair<?, ?> pair) {\n\t\t\tthis.pair = pair;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the first value\")\n\t\tpublic Object getValue1() {\n\t\t\treturn pair.getValue1();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of the first value\")\n\t\tpublic String getType1() {\n\t\t\tif (pair.getValue1() != null) {\n\t\t\t\treturn pair.getValue1().getClass().toString();\n\t\t\t} else {\n\t\t\t\treturn \"null\";\n\t\t\t}\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the second value\")\n\t\tpublic Object getValue2() {\n\t\t\treturn pair.getValue2();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of the second value\")\n\t\tpublic String getType2() {\n\t\t\tif (pair.getValue2() != null) {\n\t\t\t\treturn pair.getValue2().getClass().toString();\n\t\t\t} else {\n\t\t\t\treturn \"null\";\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic Object getObject() {\n\t\t\treturn pair;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCQuartet.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.proxy.computers.objects.CCTriplet.CCTripletImplementation;\nimport logisticspipes.utils.tuples.Quartet;\n\npublic class CCQuartet implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object input) {\n\t\treturn new CCQuartetImplementation((Quartet<?, ?, ?, ?>) input);\n\t}\n\n\t@CCType(name = \"Quartet\")\n\tpublic static class CCQuartetImplementation extends CCTripletImplementation {\n\n\t\tprivate final Quartet<?, ?, ?, ?> quartet;\n\n\t\tprotected CCQuartetImplementation(Quartet<?, ?, ?, ?> quartet) {\n\t\t\tsuper(quartet);\n\t\t\tthis.quartet = quartet;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the forth value\")\n\t\tpublic Object getValue4() {\n\t\t\treturn quartet.getValue4();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of the forth value\")\n\t\tpublic String getType4() {\n\t\t\tif (quartet.getValue4() != null) {\n\t\t\t\treturn quartet.getValue4().getClass().toString();\n\t\t\t} else {\n\t\t\t\treturn \"null\";\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCResource.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.FluidResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class CCResource implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object input) {\n\t\tif (input instanceof ItemResource) {\n\t\t\treturn new CCItemResourceImplementation((ItemResource) input);\n\t\t}\n\t\tif (input instanceof DictResource) {\n\t\t\treturn new CCDictResourceImplementation((DictResource) input);\n\t\t}\n\t\tif (input instanceof FluidResource) {\n\t\t\treturn new CCFluidResourceImplementation((FluidResource) input);\n\t\t}\n\t\treturn new CCResourceImplementation((IResource) input);\n\t}\n\n\t@CCType(name = \"ItemResource\")\n\tpublic static class CCItemResourceImplementation extends CCResourceImplementation {\n\n\t\tprivate ItemResource resource;\n\n\t\tprotected CCItemResourceImplementation(ItemResource resource) {\n\t\t\tsuper(resource);\n\t\t\tthis.resource = resource;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the resource's item\")\n\t\tpublic ItemIdentifier getItemIdentifier() {\n\t\t\treturn resource.getItem();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the resource's item\")\n\t\tpublic ItemIdentifierStack getItemIdentifierStack() {\n\t\t\treturn resource.getItemStack();\n\t\t}\n\t}\n\n\t@CCType(name = \"DictResource\")\n\tpublic static class CCDictResourceImplementation extends CCResourceImplementation {\n\n\t\tprivate DictResource resource;\n\n\t\tprotected CCDictResourceImplementation(DictResource resource) {\n\t\t\tsuper(resource);\n\t\t\tthis.resource = resource;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the resource's item\")\n\t\tpublic ItemIdentifier getItemIdentifier() {\n\t\t\treturn resource.getItem();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the resource's item\")\n\t\tpublic ItemIdentifierStack getItemIdentifierStack() {\n\t\t\treturn resource.getItemStack();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns whether the OreDictionary should be used to compare this resource\")\n\t\tpublic Boolean isUseOreDictionarySet() {\n\t\t\treturn resource.useOreDict();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns whether the OreDictionary's entry category should be used to compare this resource\")\n\t\tpublic Boolean isUseOreDictionaryCategorySet() {\n\t\t\treturn resource.useOreCategory();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns whether the damage should be ignored to compare this resource\")\n\t\tpublic Boolean isIgnoreDamageSet() {\n\t\t\treturn resource.ignoreDamage();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns whether the NBT data should be ignored to compare this resource\")\n\t\tpublic Boolean isIgnoreNBTSet() {\n\t\t\treturn resource.ignoreNBT();\n\t\t}\n\t}\n\n\t@CCType(name = \"FluidResource\")\n\tpublic static class CCFluidResourceImplementation extends CCResourceImplementation {\n\n\t\tprivate FluidResource resource;\n\n\t\tprotected CCFluidResourceImplementation(FluidResource resource) {\n\t\t\tsuper(resource);\n\t\t\tthis.resource = resource;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the resource's fluid\")\n\t\tpublic FluidIdentifier getFluidIdentifier() {\n\t\t\treturn resource.getFluid();\n\t\t}\n\t}\n\n\t@CCType(name = \"Resource\")\n\tpublic static class CCResourceImplementation implements ICCTypeWrapped {\n\n\t\tprivate IResource resource;\n\n\t\tprotected CCResourceImplementation(IResource resource) {\n\t\t\tthis.resource = resource;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of resource\")\n\t\tpublic String getResourceType() {\n\t\t\tif (resource instanceof ItemResource) {\n\t\t\t\treturn \"ItemResource\";\n\t\t\t}\n\t\t\tif (resource instanceof DictResource) {\n\t\t\t\treturn \"DictResource\";\n\t\t\t}\n\t\t\tif (resource instanceof FluidResource) {\n\t\t\t\treturn \"FluidResource\";\n\t\t\t}\n\t\t\treturn \"UNKNOWN\";\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the amount of the resource\")\n\t\tpublic int getResourceAmount() {\n\t\t\treturn resource.getRequestedAmount();\n\t\t}\n\n\t\t/* Lagacy Support for old scripts */\n\n\t\t@CCCommand(description = \"Returns the first value\")\n\t\tpublic Object getValue1() {\n\t\t\tif (resource instanceof ItemResource) {\n\t\t\t\treturn ((ItemResource) resource).getItem();\n\t\t\t}\n\t\t\tif (resource instanceof DictResource) {\n\t\t\t\treturn ((DictResource) resource).getItem();\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of the first value\")\n\t\tpublic String getType1() {\n\t\t\tif (getValue1() != null) {\n\t\t\t\treturn getValue1().getClass().toString();\n\t\t\t} else {\n\t\t\t\treturn \"null\";\n\t\t\t}\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the second value\")\n\t\tpublic Object getValue2() {\n\t\t\treturn resource.getRequestedAmount();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of the second value\")\n\t\tpublic String getType2() {\n\t\t\treturn Integer.class.toString();\n\t\t}\n\n\t\t@Override\n\t\tpublic Object getObject() {\n\t\t\treturn resource;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCSinkResponder.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.IQueueCCEvent;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\n@CCType(name = \"CCItemSinkRequest\")\npublic class CCSinkResponder implements ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\n\t@Getter\n\tprivate final ItemIdentifierStack stack;\n\t@Getter\n\tprivate final int routerId;\n\t@Getter\n\tprivate boolean done = false;\n\t@Getter\n\tprivate final IQueueCCEvent queuer;\n\n\t@Getter\n\tprivate int canSink;\n\t@Getter\n\tprivate int priority;\n\n\tpublic CCSinkResponder(ItemIdentifierStack stack, int id, IQueueCCEvent queuer) {\n\t\tthis.stack = stack;\n\t\trouterId = id;\n\t\tthis.queuer = queuer;\n\t}\n\n\t@CCCommand(description = \"Returns the ItemIdentifier for the item that should be sinked\")\n\tpublic ItemIdentifier getItemIdentifier() {\n\t\treturn stack.getItem();\n\t}\n\n\t@CCCommand(description = \"Returns the amount of items that should be sinked\")\n\tpublic int getAmount() {\n\t\treturn stack.getStackSize();\n\t}\n\n\t@CCCommand(description = \"Sends the response to the CC QuickSort module to deny the sink\")\n\tpublic void denySink() {\n\t\tdone = true;\n\t\tcanSink = -1;\n\t}\n\n\t@CCCommand(description = \"Sends the response to the CC QuickSort module to accept the sink for the given amount with the given priority\")\n\tpublic void acceptSink(Double amount, Double priority) {\n\t\tcanSink = ((Double) (amount > 0 ? amount : 0D)).intValue();\n\t\tthis.priority = priority.intValue();\n\t\tdone = true;\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/CCTriplet.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.proxy.computers.objects.CCPair.CCPairImplementation;\nimport logisticspipes.utils.tuples.Triplet;\n\npublic class CCTriplet implements ILPCCTypeDefinition {\n\n\t@Override\n\tpublic ICCTypeWrapped getTypeFor(Object input) {\n\t\treturn new CCTripletImplementation((Triplet<?, ?, ?>) input);\n\t}\n\n\t@CCType(name = \"Triplet\")\n\tpublic static class CCTripletImplementation extends CCPairImplementation {\n\n\t\tprivate final Triplet<?, ?, ?> triplet;\n\n\t\tprotected CCTripletImplementation(Triplet<?, ?, ?> triplet) {\n\t\t\tsuper(triplet);\n\t\t\tthis.triplet = triplet;\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the third value\")\n\t\tpublic Object getValue3() {\n\t\t\treturn triplet.getValue3();\n\t\t}\n\n\t\t@CCCommand(description = \"Returns the type of the third value\")\n\t\tpublic String getType3() {\n\t\t\tif (triplet.getValue3() != null) {\n\t\t\t\treturn triplet.getValue3().getClass().toString();\n\t\t\t} else {\n\t\t\t\treturn \"null\";\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/objects/LPGlobalCCAccess.java",
    "content": "package logisticspipes.proxy.computers.objects;\n\nimport java.util.Map;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\n\n@CCType(name = \"LP Global Access\")\npublic class LPGlobalCCAccess implements ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\n\t@CCCommand(description = \"Returns more information about the object\")\n\tpublic String identify(Object object) {\n\t\tif (object instanceof Map<?, ?>) {\n\t\t\tStringBuilder builder = new StringBuilder(\"Map: \");\n\t\t\tif (((Map<?, ?>) object).isEmpty()) {\n\t\t\t\treturn builder.append(\"empty\").toString();\n\t\t\t}\n\t\t\tbuilder.append(\"key [\");\n\t\t\tif (((Map<?, ?>) object).keySet().toArray()[0] != null) {\n\t\t\t\tbuilder.append(((Map<?, ?>) object).keySet().toArray()[0].getClass());\n\t\t\t} else {\n\t\t\t\tbuilder.append(\"null\");\n\t\t\t}\n\t\t\tbuilder.append(\"], [\");\n\t\t\tif (((Map<?, ?>) object).values().toArray()[0] != null) {\n\t\t\t\tbuilder.append(((Map<?, ?>) object).values().toArray()[0].getClass());\n\t\t\t} else {\n\t\t\t\tbuilder.append(\"null\");\n\t\t\t}\n\t\t\tbuilder.append(\"]\");\n\t\t\treturn builder.toString();\n\t\t}\n\t\tif (object == null) {\n\t\t\treturn \"null\";\n\t\t}\n\t\treturn object.toString() + \" [\" + object.getClass() + \"]\";\n\t}\n\n\t@CCCommand(description = \"Creates a new ItemIdentifier Builder\")\n\tpublic CCItemIdentifierBuilder getItemIdentifierBuilder() {\n\t\treturn new CCItemIdentifierBuilder();\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/wrapper/CCObjectWrapper.java",
    "content": "package logisticspipes.proxy.computers.wrapper;\n\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.WeakHashMap;\n\nimport net.minecraft.nbt.NBTBase;\n\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.interfaces.CCSecurtiyCheck;\nimport logisticspipes.proxy.computers.interfaces.CCType;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeDefinition;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.proxy.computers.objects.CCFilterInventory;\nimport logisticspipes.proxy.computers.objects.CCFluidIdentifier;\nimport logisticspipes.proxy.computers.objects.CCItemIdentifier;\nimport logisticspipes.proxy.computers.objects.CCItemIdentifierInventory;\nimport logisticspipes.proxy.computers.objects.CCItemIdentifierStack;\nimport logisticspipes.proxy.computers.objects.CCPair;\nimport logisticspipes.proxy.computers.objects.CCQuartet;\nimport logisticspipes.proxy.computers.objects.CCResource;\nimport logisticspipes.proxy.computers.objects.CCTriplet;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Quartet;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\npublic class CCObjectWrapper {\n\n\tprivate static Map<Class<?>, CCWrapperInformation> ccMapings = new HashMap<>();\n\tprivate static Map<Object, Object> wrappedObjects = new WeakHashMap<>();\n\tprivate static Map<Class<? extends ILPCCTypeHolder>, ILPCCTypeDefinition> specialMappings = new HashMap<>();\n\n\tstatic {\n\t\tCCObjectWrapper.specialMappings.put(ItemIdentifier.class, new CCItemIdentifier());\n\t\tCCObjectWrapper.specialMappings.put(ItemIdentifierStack.class, new CCItemIdentifierStack());\n\t\tCCObjectWrapper.specialMappings.put(Pair.class, new CCPair());\n\t\tCCObjectWrapper.specialMappings.put(Triplet.class, new CCTriplet());\n\t\tCCObjectWrapper.specialMappings.put(Quartet.class, new CCQuartet());\n\t\tCCObjectWrapper.specialMappings.put(IResource.class, new CCResource());\n\t\tCCObjectWrapper.specialMappings.put(FluidIdentifier.class, new CCFluidIdentifier());\n\t}\n\n\tprivate static String checkForTypeAnotation(Class<?> clazz) {\n\t\tif (clazz.getAnnotation(CCType.class) != null) {\n\t\t\treturn clazz.getAnnotation(CCType.class).name();\n\t\t}\n\t\tString result;\n\t\tif (!clazz.getSuperclass().equals(Object.class)) {\n\t\t\tif (!(result = CCObjectWrapper.checkForTypeAnotation(clazz.getSuperclass())).equals(\"\")) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\treturn \"\";\n\t}\n\n\tpublic static Object checkForAnnotations(final Object input, final ICommandWrapper wrapper) {\n\t\tif (input == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (input instanceof ILPCCTypeHolder && ((ILPCCTypeHolder) input).getCCType() != null) {\n\t\t\treturn ((ILPCCTypeHolder) input).getCCType();\n\t\t}\n\t\tObject wrapped = input;\n\t\tif (CCObjectWrapper.specialMappings.containsKey(input.getClass())) {\n\t\t\twrapped = CCObjectWrapper.specialMappings.get(input.getClass()).getTypeFor(input);\n\t\t} else if (input instanceof IItemIdentifierInventory) {\n\t\t\tif (((IItemIdentifierInventory) input).getInventoryStackLimit() == 1) {\n\t\t\t\twrapped = new CCFilterInventory((IItemIdentifierInventory) input);\n\t\t\t} else {\n\t\t\t\twrapped = new CCItemIdentifierInventory((IItemIdentifierInventory) input);\n\t\t\t}\n\t\t}\n\t\tCCWrapperInformation info = CCObjectWrapper.getWrapperInformation(wrapped.getClass());\n\t\tif (!info.isCCType) {\n\t\t\treturn wrapped;\n\t\t}\n\t\tif (input instanceof ILPCCTypeHolder) {\n\t\t\tObject finalWrapped = wrapper.getWrappedObject(info, wrapped);\n\t\t\t((ILPCCTypeHolder) input).setCCType(finalWrapped);\n\t\t\treturn finalWrapped;\n\t\t} else if (CCObjectWrapper.wrappedObjects.containsKey(input)) {\n\t\t\treturn CCObjectWrapper.wrappedObjects.get(input);\n\t\t} else {\n\t\t\tObject finalWrapped = wrapper.getWrappedObject(info, wrapped);\n\t\t\tCCObjectWrapper.wrappedObjects.put(input, finalWrapped);\n\t\t\treturn finalWrapped;\n\t\t}\n\t}\n\n\t@SuppressWarnings({ \"rawtypes\", \"unchecked\" })\n\tpublic static Object getWrappedObject(Object input, final ICommandWrapper wrapper) {\n\t\tif (input instanceof Object[]) {\n\t\t\tObject[] array = (Object[]) input;\n\t\t\tfor (int i = 0; i < array.length; i++) {\n\t\t\t\tarray[i] = CCObjectWrapper.getWrappedObject(array[i], wrapper);\n\t\t\t}\n\t\t\treturn array;\n\t\t} else if (input instanceof List) {\n\t\t\tList list = (List) input;\n\t\t\tMap map = new HashMap();\n\t\t\tfor (int i = 0; i < list.size(); i++) {\n\t\t\t\tmap.put((i + 1), CCObjectWrapper.getWrappedObject(list.get(i), wrapper));\n\t\t\t}\n\t\t\treturn map;\n\t\t} else if (input instanceof Map) {\n\t\t\tMap oldMap = (Map) input;\n\t\t\tMap map = new HashMap();\n\t\t\tfor (Object key : oldMap.keySet()) {\n\t\t\t\tmap.put(CCObjectWrapper.getWrappedObject(key, wrapper), CCObjectWrapper.getWrappedObject(oldMap.get(key), wrapper));\n\t\t\t}\n\t\t\treturn map;\n\t\t} else if (input instanceof NBTBase) {\n\t\t\ttry {\n\t\t\t\treturn ItemIdentifier.getNBTBaseAsMap((NBTBase) input);\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\treturn CCObjectWrapper.checkForAnnotations(input, wrapper);\n\t}\n\n\tpublic static CCWrapperInformation getWrapperInformation(Class<?> wrappedClass) {\n\t\tCCWrapperInformation info = CCObjectWrapper.ccMapings.get(wrappedClass);\n\t\tif (info == null) {\n\t\t\tinfo = new CCWrapperInformation();\n\t\t\tString type = CCObjectWrapper.checkForTypeAnotation(wrappedClass);\n\t\t\tif (!type.equals(\"\")) {\n\t\t\t\tinfo.isCCType = true;\n\t\t\t\tinfo.type = type;\n\t\t\t\tClass<?> clazz = wrappedClass;\n\t\t\t\tint i = 0;\n\t\t\t\twhile (clazz != Object.class) {\n\t\t\t\t\tfor (Method method : clazz.getDeclaredMethods()) {\n\t\t\t\t\t\tif (method.isAnnotationPresent(CCSecurtiyCheck.class)) {\n\t\t\t\t\t\t\tif (method.getParameterTypes().length > 0) {\n\t\t\t\t\t\t\t\tthrow new InternalError(\"Internal Excption (Code: 4)\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinfo.securityMethod = method;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!method.isAnnotationPresent(CCCommand.class)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (Class<?> param : method.getParameterTypes()) {\n\t\t\t\t\t\t\tif (param.isPrimitive()) {\n\t\t\t\t\t\t\t\tthrow new InternalError(\"Internal Excption (Code: 2)\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinfo.commandMap.put(i, method.getName());\n\t\t\t\t\t\tinfo.commands.put(i, method);\n\t\t\t\t\t\tif (info.commandTypes.containsKey(method.getName())) {\n\t\t\t\t\t\t\tPair<Boolean, String> pair = info.commandTypes.get(method.getName());\n\t\t\t\t\t\t\tif (pair.getValue1().booleanValue() ^ method.isAnnotationPresent(CCQueued.class)) {\n\t\t\t\t\t\t\t\tthrow new InternalError(\"Internal Excption (Code: 5, \" + method + \")\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!pair.getValue2().equals(method.getAnnotation(CCCommand.class).description())) {\n\t\t\t\t\t\t\t\tpair.setValue2(\"Multipurpose method. Use help() for more information\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinfo.commandTypes.put(method.getName(), new Pair<>(method\n\t\t\t\t\t\t\t\t\t.isAnnotationPresent(CCQueued.class), method.getAnnotation(CCCommand.class)\n\t\t\t\t\t\t\t\t\t.description()));\n\t\t\t\t\t\t}\n\t\t\t\t\t\ti++;\n\t\t\t\t\t}\n\t\t\t\t\tclazz = clazz.getSuperclass();\n\t\t\t\t}\n\t\t\t}\n\t\t\tCCObjectWrapper.ccMapings.put(wrappedClass, info);\n\t\t}\n\t\treturn info;\n\t}\n\n\tpublic static Object[] createArray(Object input) {\n\t\tif (input instanceof Object[]) {\n\t\t\treturn (Object[]) input;\n\t\t}\n\t\tif (input == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new Object[] { input };\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/wrapper/CCWrapperInformation.java",
    "content": "package logisticspipes.proxy.computers.wrapper;\n\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport logisticspipes.utils.tuples.Pair;\n\npublic class CCWrapperInformation {\n\n\tpublic boolean isCCType = false;\n\tpublic String type = \"\";\n\tpublic HashMap<Integer, String> commandMap = new HashMap<>();\n\tpublic Map<Integer, Method> commands = new LinkedHashMap<>();\n\tpublic Map<String, Pair<Boolean, String>> commandTypes = new LinkedHashMap<>();\n\tpublic Method securityMethod = null;\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/computers/wrapper/ICommandWrapper.java",
    "content": "package logisticspipes.proxy.computers.wrapper;\n\npublic interface ICommandWrapper {\n\n\tObject getWrappedObject(CCWrapperInformation info, Object object);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/enderchest/EnderStorageProxy.java",
    "content": "package logisticspipes.proxy.enderchest;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport codechicken.enderstorage.block.BlockEnderStorage;\nimport codechicken.enderstorage.tile.TileFrequencyOwner;\n\nimport logisticspipes.proxy.interfaces.IEnderStorageProxy;\n\npublic class EnderStorageProxy implements IEnderStorageProxy {\n\n\t@Override\n\tpublic boolean isEnderChestBlock(Block block) {\n\t\treturn block instanceof BlockEnderStorage;\n\t}\n\n\t@Override\n\tpublic void openEnderChest(World world, int x, int y, int z, EntityPlayer player) {\n\t\tTileFrequencyOwner tile = (TileFrequencyOwner) world.getTileEntity(new BlockPos(x, y, z));\n\t\ttile.activate(player, 0, null);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/endercore/EnderCoreProgressProvider.java",
    "content": "package logisticspipes.proxy.endercore;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport com.enderio.core.api.common.util.IProgressTile;\n\nimport logisticspipes.proxy.interfaces.IGenericProgressProvider;\n\npublic class EnderCoreProgressProvider implements IGenericProgressProvider {\n\n\t@Override\n\tpublic boolean isType(TileEntity tile) {\n\t\treturn tile instanceof IProgressTile;\n\t}\n\n\t@Override\n\tpublic byte getProgress(TileEntity tile) {\n\t\treturn (byte) Math.max(0, Math.min(((IProgressTile) tile).getProgress() * 100, 100));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ic/IronChestProxy.java",
    "content": "package logisticspipes.proxy.ic;\n\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport cpw.mods.ironchest.client.gui.chest.GUIChest;\nimport cpw.mods.ironchest.common.tileentity.chest.TileEntityIronChest;\n\nimport logisticspipes.proxy.interfaces.IIronChestProxy;\n\npublic class IronChestProxy implements IIronChestProxy {\n\n\t@Override\n\tpublic boolean isIronChest(TileEntity tile) {\n\t\treturn tile instanceof TileEntityIronChest;\n\t}\n\n\t@Override\n\tpublic @SideOnly(Side.CLIENT)\n\tboolean isChestGui(GuiScreen gui) {\n\t\treturn gui instanceof GUIChest;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ic2/IC2ProgressProvider.java",
    "content": "package logisticspipes.proxy.ic2;\n\nimport java.util.function.Function;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport ic2.api.classic.tile.machine.IProgressMachine;\nimport ic2.core.block.machine.tileentity.TileEntityStandardMachine;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.interfaces.IGenericProgressProvider;\n\npublic class IC2ProgressProvider implements IGenericProgressProvider {\n\n\t@Nullable\n\tprivate Class<?> progressProviderClass = null;\n\t@Nullable\n\tprivate Function<TileEntity, Byte> getProgressFunction = null;\n\n\tpublic IC2ProgressProvider() {\n\t\ttry {\n\t\t\t// support for IC2C progress\n\t\t\tprogressProviderClass = IProgressMachine.class;\n\t\t\tgetProgressFunction = this::getIC2CProgress;\n\t\t\treturn;\n\t\t} catch (LinkageError error) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\terror.printStackTrace();\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tprogressProviderClass = TileEntityStandardMachine.class;\n\t\t\tgetProgressFunction = this::getIC2Progress;\n\t\t} catch (LinkageError error) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\terror.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isType(TileEntity tile) {\n\t\tif (progressProviderClass == null) return false;\n\t\treturn progressProviderClass.isInstance(tile);\n\t}\n\n\tprivate byte getIC2CProgress(TileEntity tile) {\n\t\tIProgressMachine progressMachine = (IProgressMachine) tile;\n\t\tfloat normalizedProgress = progressMachine.getProgress() / progressMachine.getMaxProgress();\n\t\treturn (byte) Math.max(0, Math.min(normalizedProgress * 100, 100));\n\t}\n\n\tprivate byte getIC2Progress(TileEntity tile) {\n\t\tTileEntityStandardMachine standardMachine = (TileEntityStandardMachine) tile;\n\t\treturn (byte) Math.max(0, Math.min(standardMachine.getProgress() * 100, 100));\n\t}\n\n\t@Override\n\tpublic byte getProgress(TileEntity tile) {\n\t\tif (getProgressFunction == null) return 0;\n\t\treturn getProgressFunction.apply(tile);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/ic2/IC2Proxy.java",
    "content": "package logisticspipes.proxy.ic2;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.MinecraftForge;\n\nimport ic2.api.energy.event.EnergyTileLoadEvent;\nimport ic2.api.energy.event.EnergyTileUnloadEvent;\nimport ic2.api.energy.tile.IEnergyEmitter;\nimport ic2.api.energy.tile.IEnergySink;\nimport ic2.api.energy.tile.IEnergyTile;\n\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.interfaces.IIC2Proxy;\nimport logisticspipes.recipes.CraftingParts;\n\npublic class IC2Proxy implements IIC2Proxy {\n\n\t/**\n\t * Adds crafting recipes to \"IC2 Crafting\"\n\t */\n\t@Override\n\tpublic void addCraftingRecipes(CraftingParts parts) {\n\t\t/*\n\t\tCraftingRecipes.advRecipes.addRecipe(new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_LV_SUPPLIER),\n\t\t\t\tnew Object[] { \"PSP\", \"OBO\", \"PTP\", Character.valueOf('B'), new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_TRANSPORTATION), Character.valueOf('S'), IC2Items.getItem(\"energyStorageUpgrade\"), Character.valueOf('O'), IC2Items.getItem(\"overclockerUpgrade\"), Character.valueOf('T'),\n\t\t\t\t\t\tIC2Items.getItem(\"transformerUpgrade\"), Character.valueOf('P'), Items.paper });\n\n\t\tCraftingRecipes.advRecipes.addRecipe(new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_MV_SUPPLIER),\n\t\t\t\tnew Object[] { \"PSP\", \"OBO\", \"PTP\", Character.valueOf('B'), new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_LV_SUPPLIER), Character.valueOf('S'), IC2Items.getItem(\"energyStorageUpgrade\"), Character.valueOf('O'), IC2Items.getItem(\"overclockerUpgrade\"), Character.valueOf('T'),\n\t\t\t\t\t\tIC2Items.getItem(\"transformerUpgrade\"), Character.valueOf('P'), Items.paper });\n\n\t\tCraftingRecipes.advRecipes.addRecipe(new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_HV_SUPPLIER),\n\t\t\t\tnew Object[] { \"PSP\", \"OBO\", \"PTP\", Character.valueOf('B'), new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_MV_SUPPLIER), Character.valueOf('S'), IC2Items.getItem(\"energyStorageUpgrade\"), Character.valueOf('O'), IC2Items.getItem(\"overclockerUpgrade\"), Character.valueOf('T'),\n\t\t\t\t\t\tIC2Items.getItem(\"transformerUpgrade\"), Character.valueOf('P'), Items.paper });\n\n\t\tCraftingRecipes.advRecipes.addRecipe(new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_EV_SUPPLIER),\n\t\t\t\tnew Object[] { \"PSP\", \"OBO\", \"PTP\", Character.valueOf('B'), new ItemStack(LogisticsPipes.UpgradeItem, 1, ItemUpgrade.POWER_IC2_HV_SUPPLIER), Character.valueOf('S'), IC2Items.getItem(\"energyStorageUpgrade\"), Character.valueOf('O'), IC2Items.getItem(\"overclockerUpgrade\"), Character.valueOf('T'),\n\t\t\t\t\t\tIC2Items.getItem(\"transformerUpgrade\"), Character.valueOf('P'), Items.paper });\n\n\t\tCraftingRecipes.advRecipes.addRecipe(new ItemStack(LogisticsPipes.LogisticsSolidBlock, 1, LogisticsSolidBlock.LOGISTICS_IC2_POWERPROVIDER), new Object[] { \"PSP\", \"OBO\", \"PTP\", Character.valueOf('B'), Blocks.redstone_block, Character.valueOf('S'), IC2Items.getItem(\"energyStorageUpgrade\"), Character.valueOf('O'),\n\t\t\t\tIC2Items.getItem(\"overclockerUpgrade\"), Character.valueOf('T'), IC2Items.getItem(\"transformerUpgrade\"), Character.valueOf('P'), Items.paper });\n\t\t*/\n\t}\n\n\t/**\n\t * Registers an TileEntity to the IC2 EnergyNet\n\t *\n\t * @param tile to be an instance of IEnergyTile\n\t */\n\t@Override\n\tpublic void registerToEneryNet(TileEntity tile) {\n\t\tif (MainProxy.isServer(tile.getWorld())) {\n\t\t\tMinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent((IEnergyTile) tile));\n\t\t}\n\t}\n\n\t/**\n\t * Removes an TileEntity from the IC2 EnergyNet\n\t *\n\t * @param tile to be an instance of IEnergyTile\n\t */\n\t@Override\n\tpublic void unregisterToEneryNet(TileEntity tile) {\n\t\tif (MainProxy.isServer(tile.getWorld())) {\n\t\t\tMinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent((IEnergyTile) tile));\n\t\t}\n\t}\n\n\t/**\n\t * @return If IC2 is loaded, returns true.\n\t */\n\t@Override\n\tpublic boolean hasIC2() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean acceptsEnergyFrom(TileEntity energy, TileEntity tile, EnumFacing opposite) {\n\t\treturn tile instanceof IEnergyEmitter && energy instanceof IEnergySink && ((IEnergySink) energy).acceptsEnergyFrom((IEnergyEmitter) tile, opposite);\n\t}\n\n\t@Override\n\tpublic boolean isEnergySink(TileEntity tile) {\n\t\treturn tile instanceof IEnergySink;\n\t}\n\n\t@Override\n\tpublic double demandedEnergyUnits(TileEntity tile) {\n\t\treturn ((IEnergySink) tile).getDemandedEnergy();\n\t}\n\n\t@Override\n\tpublic double injectEnergyUnits(TileEntity tile, EnumFacing opposite, double d) {\n\t\treturn ((IEnergySink) tile).injectEnergy(opposite, d, 1); //TODO check the voltage\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IBCProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.asm.IgnoreDisabledProxy;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.buildcraft.subproxies.IBCPipeCapabilityProvider;\nimport logisticspipes.recipes.CraftingParts;\n\npublic interface IBCProxy {\n\n\tvoid registerPipeInformationProvider();\n\n\tvoid initProxy();\n\n\tboolean isActive();\n\n\t@IgnoreDisabledProxy\n\tboolean isInstalled();\n\n\tCraftingParts getRecipeParts();\n\n\tvoid addCraftingRecipes(CraftingParts parts);\n\n\tClass<? extends ICraftingRecipeProvider> getAssemblyTableProviderClass();\n\n\tvoid registerInventoryHandler();\n\n\tIBCPipeCapabilityProvider getIBCPipeCapabilityProvider(LogisticsTileGenericPipe pipe);\n\n\tObject createMjReceiver(@Nonnull LogisticsPowerJunctionTileEntity te);\n\n\tboolean isBuildCraftPipe(TileEntity tile);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/ICCLProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Collection;\nimport java.util.Map;\n\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\nimport net.minecraftforge.common.model.IModelState;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.IRenderState;\nimport logisticspipes.proxy.object3d.interfaces.ITranslation;\nimport logisticspipes.proxy.object3d.interfaces.IVec3;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\n\npublic interface ICCLProxy {\n\n\t@SideOnly(Side.CLIENT)\n\tTextureTransformation createIconTransformer(TextureAtlasSprite registerIcon);\n\n\tIRenderState getRenderState();\n\n\tMap<String, IModel3D> parseObjModels(InputStream resourceAsStream, int i, LPScale scale) throws IOException;\n\n\tObject getRotation(int i, int j);\n\n\tObject getScale(double d, double e, double f);\n\n\tObject getScale(double d);\n\n\tITranslation getTranslation(double d, double e, double f);\n\n\tITranslation getTranslation(IVec3 min);\n\n\tObject getUVScale(double i, double d);\n\n\tObject getUVTranslation(float i, float f);\n\n\tObject getUVTransformationList(I3DOperation[] uvTranslation);\n\n\tIModel3D wrapModel(Object model);\n\n\tboolean isActivated();\n\n\tObject getRotation(double d, int i, int j, int k);\n\n\tIModel3D combine(Collection<IModel3D> list);\n\n\tObject getColourMultiplier(int i);\n\n\tIModelState getDefaultBlockState();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/ICCProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.recipes.CraftingParts;\n\npublic interface ICCProxy {\n\n\tboolean isTurtle(TileEntity tile);\n\n\tboolean isComputer(TileEntity tile);\n\n\tboolean isCC();\n\n\tboolean isLuaThread(Thread thread);\n\n\tvoid queueEvent(String event, Object[] arguments, LogisticsTileGenericPipe logisticsTileGenericPipe);\n\n\tvoid setTurtleConnect(boolean flag, LogisticsTileGenericPipe logisticsTileGenericPipe);\n\n\tboolean getTurtleConnect(LogisticsTileGenericPipe logisticsTileGenericPipe);\n\n\tint getLastCCID(LogisticsTileGenericPipe logisticsTileGenericPipe);\n\n\tvoid handleMesssage(int computerId, Object message, LogisticsTileGenericPipe tile, int sourceId);\n\n\tvoid addCraftingRecipes(CraftingParts parts);\n\n\tObject getAnswer(Object object);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/ICraftingRecipeProvider.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\n\npublic interface ICraftingRecipeProvider {\n\n\tboolean canOpenGui(TileEntity tile);\n\n\tboolean importRecipe(TileEntity tile, IItemIdentifierInventory inventory);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IEnderStorageProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.world.World;\n\npublic interface IEnderStorageProxy {\n\n\tboolean isEnderChestBlock(Block block);\n\n\tvoid openEnderChest(World world, int x, int y, int z, EntityPlayer player);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IFuzzyRecipeProvider.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport network.rs485.logisticspipes.inventory.SlotAccess;\nimport network.rs485.logisticspipes.property.BitSetProperty;\n\npublic interface IFuzzyRecipeProvider extends ICraftingRecipeProvider {\n\n\tvoid importFuzzyFlags(TileEntity tile, SlotAccess slotAccess, BitSetProperty fuzzyFlags);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IGenericProgressProvider.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\n\npublic interface IGenericProgressProvider {\n\n\tboolean isType(TileEntity tile);\n\n\tbyte getProgress(TileEntity tile);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IIC2Proxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.recipes.CraftingParts;\n\npublic interface IIC2Proxy {\n\n\tvoid addCraftingRecipes(CraftingParts parts);\n\n\tboolean hasIC2();\n\n\tvoid registerToEneryNet(TileEntity tile);\n\n\tvoid unregisterToEneryNet(TileEntity tile);\n\n\tboolean acceptsEnergyFrom(TileEntity energy, TileEntity tile, EnumFacing opposite);\n\n\tboolean isEnergySink(TileEntity tile);\n\n\tdouble demandedEnergyUnits(TileEntity tile);\n\n\tdouble injectEnergyUnits(TileEntity tile, EnumFacing opposite, double d);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IIronChestProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic interface IIronChestProxy {\n\n\tboolean isIronChest(TileEntity tile);\n\n\t@SideOnly(Side.CLIENT)\n\tboolean isChestGui(GuiScreen gui);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/ILPPipeConfigToolWrapper.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.api.ILPPipeConfigTool;\n\npublic interface ILPPipeConfigToolWrapper {\n\n\tILPPipeConfigTool getWrappedTool(@Nonnull ItemStack stack);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/INEIProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.text.TextFormatting;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic interface INEIProxy {\n\n\t@Nonnull\n\tItemStack getItemForPosition(World world, EntityPlayer player, RayTraceResult objectMouseOver);\n\n\tList<String> getInfoForPosition(World world, EntityPlayer player, RayTraceResult objectMouseOver);\n\n\t@SideOnly(Side.CLIENT)\n\tboolean renderItemToolTip(int posX, int posY, List<String> msg, TextFormatting rarityColor, @Nonnull ItemStack stack);\n\n\t@SideOnly(Side.CLIENT)\n\tList<String> getItemToolTip(@Nonnull ItemStack var22, EntityPlayer thePlayer, ITooltipFlag advancedItemTooltips, GuiContainer screen);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IOpenComputersProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.opencomputers.IOCTile;\n\npublic interface IOpenComputersProxy {\n\n\tvoid initLogisticsTileGenericPipe(LogisticsTileGenericPipe tile);\n\n\tvoid initLogisticsSolidTileEntity(LogisticsSolidTileEntity tile);\n\n\tvoid addToNetwork(TileEntity tile);\n\n\tvoid handleInvalidate(IOCTile tile);\n\n\tvoid handleChunkUnload(IOCTile tile);\n\n\tvoid handleWriteToNBT(IOCTile tile, NBTTagCompound nbt);\n\n\tvoid handleReadFromNBT(IOCTile tile, NBTTagCompound nbt);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IPowerProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.proxy.cofh.subproxies.ICoFHEnergyReceiver;\nimport logisticspipes.proxy.cofh.subproxies.ICoFHEnergyStorage;\n\npublic interface IPowerProxy {\n\n\tboolean isEnergyReceiver(TileEntity tile, EnumFacing face);\n\n\tICoFHEnergyReceiver getEnergyReceiver(TileEntity tile, EnumFacing face);\n\n\tICoFHEnergyStorage getEnergyStorage(int i);\n\n\tboolean isAvailable();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.network.INetHandler;\nimport net.minecraft.world.World;\n\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface IProxy {\n\n\tString getSide();\n\n\tWorld getWorld();\n\n\tvoid registerTileEntities();\n\n\tEntityPlayer getClientPlayer();\n\n\tvoid addLogisticsPipesOverride(Object par1IIconRegister, int index, String override1, String override2, boolean flag);\n\n\tvoid registerParticles();\n\n\tString getName(ItemIdentifier item);\n\n\tvoid updateNames(ItemIdentifier item, String name);\n\n\tvoid tick();\n\n\tvoid sendNameUpdateRequest(EntityPlayer player);\n\n\tLogisticsTileGenericPipe getPipeInDimensionAt(int dimension, int x, int y, int z, EntityPlayer player);\n\n\tvoid sendBroadCast(String message);\n\n\tvoid tickServer();\n\n\tvoid tickClient();\n\n\tEntityPlayer getEntityPlayerFromNetHandler(INetHandler handler);\n\n\tvoid setIconProviderFromPipe(ItemLogisticsPipe item, CoreUnroutedPipe dummyPipe);\n\n\tLogisticsModule getModuleFromGui();\n\n\tboolean checkSinglePlayerOwner(String commandSenderName);\n\n\tvoid openFluidSelectGui(int slotId);\n\n\tdefault void registerModels() {}\n\n\tvoid registerTextures();\n\n\tvoid initModelLoader();\n\n\tint getRenderIndex();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/ITDProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport java.util.List;\n\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.td.subproxies.ITDPart;\nimport logisticspipes.renderer.newpipe.RenderEntry;\n\npublic interface ITDProxy {\n\n\tITDPart getTDPart(LogisticsTileGenericPipe pipe);\n\n\tboolean isActive();\n\n\tvoid registerPipeInformationProvider();\n\n\tboolean isItemDuct(TileEntity tile);\n\n\t@SideOnly(Side.CLIENT)\n\tvoid renderPipeConnections(LogisticsTileGenericPipe pipeTile, List<RenderEntry> renderList);\n\n\t@SideOnly(Side.CLIENT)\n\tvoid registerTextures(TextureMap iconRegister);\n\n\tboolean isBlockedSide(TileEntity with, EnumFacing opposite);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/interfaces/IThermalExpansionProxy.java",
    "content": "package logisticspipes.proxy.interfaces;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.math.BlockPos;\n\nimport logisticspipes.recipes.CraftingParts;\n\npublic interface IThermalExpansionProxy {\n\n\tboolean isTE();\n\n\tCraftingParts getRecipeParts();\n\n\tboolean isToolHammer(Item stack);\n\n\tboolean canHammer(@Nonnull ItemStack stack, EntityPlayer entityplayer, BlockPos pos);\n\n\tvoid toolUsed(@Nonnull ItemStack stack, EntityPlayer entityplayer, BlockPos pos);\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/nei/NEIProxy.java",
    "content": "/*\npackage logisticspipes.proxy.nei;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.text.TextFormatting;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport codechicken.lib.gui.GuiDraw;\nimport codechicken.nei.api.ItemInfo;\nimport codechicken.nei.guihook.GuiContainerManager;\nimport codechicken.nei.guihook.IContainerTooltipHandler;\nimport lombok.SneakyThrows;\n\nimport logisticspipes.proxy.interfaces.INEIProxy;\nimport logisticspipes.utils.ReflectionHelper;\npublic class NEIProxy implements INEIProxy {\n\n\t@Override\n\tpublic List<String> getInfoForPosition(World world, EntityPlayer player, RayTraceResult objectMouseOver) {\n\t\tList<ItemStack> items = ItemInfo.getIdentifierItems(world, player, objectMouseOver);\n\t\tif (items.isEmpty()) {\n\t\t\treturn new ArrayList<>(0);\n\t\t}\n\t\tCollections.sort(items, (stack0, stack1) -> stack1.getItemDamage() - stack0.getItemDamage());\n\t\treturn ItemInfo.getText(items.get(0), world, player, objectMouseOver);\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@SneakyThrows({NoSuchFieldException.class, IllegalAccessException.class})\n\tpublic boolean renderItemToolTip(int mousex, int mousey, List<String> msg, TextFormatting rarityColor, ItemStack stack) {\n\t\tif (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) {\n\t\t\treturn false;\n\t\t}\n\t\tGuiContainer window = (GuiContainer) Minecraft.getMinecraft().currentScreen;\n\t\tList<String> tooltip = new LinkedList<String>();\n\t\tFontRenderer font = GuiDraw.fontRenderer;\n\n\t\tif (GuiContainerManager.shouldShowTooltip(window)) {\n\t\t\tfont = GuiContainerManager.getFontRenderer(stack);\n\t\t\tif (stack != null) {\n\t\t\t\ttooltip = msg;\n\t\t\t}\n\t\t\tfor (IContainerTooltipHandler handler : (List<IContainerTooltipHandler>) ReflectionHelper.getPrivateField(List.class, GuiContainerManager.class, \"instanceTooltipHandlers\", GuiContainerManager.getManager())) {\n\t\t\t\ttooltip = handler.handleItemTooltip(window, stack, mousex, mousey, tooltip);\n\t\t\t}\n\t\t}\n\t\tif (tooltip.size() > 0) {\n\t\t\ttooltip.set(0, tooltip.get(0) + \"§h\");\n\t\t}\n\t\tGuiDraw.drawMultilineTip(mousex + 12, mousey - 12, tooltip);\n\t\treturn true;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic List<String> getItemToolTip(ItemStack stack, EntityPlayer thePlayer, ITooltipFlag advancedItemTooltips, GuiContainer screen) {\n\t\treturn GuiContainerManager.itemDisplayNameMultiline(stack, screen, true);\n\t}\n\n\t@Override\n\tpublic ItemStack getItemForPosition(World world, EntityPlayer player, RayTraceResult objectMouseOver) {\n\t\tList<ItemStack> items = ItemInfo.getIdentifierItems(world, player, objectMouseOver);\n\t\tif (items.isEmpty()) {\n\t\t\treturn null;\n\t\t}\n\t\tCollections.sort(items, (stack0, stack1) -> stack1.getItemDamage() - stack0.getItemDamage());\n\t\treturn items.get(0);\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/I3DOperation.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\npublic interface I3DOperation {\n\n\tObject getOriginal();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/IBounds.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\nimport net.minecraft.util.math.AxisAlignedBB;\n\npublic interface IBounds {\n\n\tIVec3 max();\n\n\tIVec3 min();\n\n\tAxisAlignedBB toAABB();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/IModel3D.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\nimport java.util.List;\n\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic interface IModel3D {\n\n\tIModel3D backfacedCopy();\n\n\tvoid render(I3DOperation... i3dOperations);\n\n\t@SideOnly(Side.CLIENT)\n\tList<BakedQuad> renderToQuads(VertexFormat format, I3DOperation... i3dOperations);\n\n\tvoid computeNormals();\n\n\tvoid computeStandardLighting();\n\n\tIBounds bounds();\n\n\tIModel3D apply(I3DOperation translation);\n\n\tIModel3D copy();\n\n\tIModel3D twoFacedCopy();\n\n\tObject getOriginal();\n\n\tIBounds getBoundsInside(AxisAlignedBB boundingBox);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/IRenderState.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic interface IRenderState {\n\n\tvoid reset();\n\n\tvoid setAlphaOverride(int i);\n\n\tvoid draw();\n\n\tvoid setBrightness(IBlockAccess world, BlockPos pos);\n\n\t@SideOnly(Side.CLIENT)\n\tvoid startDrawing(int mode, VertexFormat format);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/ITranslation.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\npublic interface ITranslation {\n\n\tITranslation inverse();\n\n\tObject getOriginal();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/IVec3.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\npublic interface IVec3 {\n\n\tdouble x();\n\n\tdouble y();\n\n\tdouble z();\n\n\tObject getOriginal();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/interfaces/TextureTransformation.java",
    "content": "package logisticspipes.proxy.object3d.interfaces;\n\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic interface TextureTransformation extends I3DOperation {\n\n\t@SideOnly(Side.CLIENT)\n\tvoid update(TextureAtlasSprite registerIcon);\n\n\t@SideOnly(Side.CLIENT)\n\tTextureAtlasSprite getTexture();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPColourMultiplier.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\n\npublic class LPColourMultiplier implements I3DOperation {\n\n\tprivate final Object ori;\n\n\tpublic LPColourMultiplier(int i) {\n\t\tori = SimpleServiceLocator.cclProxy.getColourMultiplier(i);\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn ori;\n\t}\n\n\tpublic static I3DOperation instance(int i) {\n\t\treturn new LPColourMultiplier(i);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPRotation.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\n\npublic class LPRotation implements I3DOperation {\n\n\tprivate final Object ori;\n\n\tprivate LPRotation(int i, int j) {\n\t\tori = SimpleServiceLocator.cclProxy.getRotation(i, j);\n\t}\n\n\tpublic LPRotation(double d, int i, int j, int k) {\n\t\tori = SimpleServiceLocator.cclProxy.getRotation(d, i, j, k);\n\t}\n\n\tpublic static I3DOperation sideOrientation(int i, int j) {\n\t\treturn new LPRotation(i, j);\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn ori;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPScale.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\n\npublic class LPScale implements I3DOperation {\n\n\tprivate final Object ori;\n\n\tpublic LPScale(double d) {\n\t\tori = SimpleServiceLocator.cclProxy.getScale(d);\n\t}\n\n\tpublic LPScale(double d, double e, double f) {\n\t\tori = SimpleServiceLocator.cclProxy.getScale(d, e, f);\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn ori;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPTranslation.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.ITranslation;\nimport logisticspipes.proxy.object3d.interfaces.IVec3;\n\npublic class LPTranslation implements I3DOperation {\n\n\tprivate final ITranslation trans;\n\n\tpublic LPTranslation(double d, double e, double f) {\n\t\ttrans = SimpleServiceLocator.cclProxy.getTranslation(d, e, f);\n\t}\n\n\tpublic LPTranslation(IVec3 min) {\n\t\ttrans = SimpleServiceLocator.cclProxy.getTranslation(min);\n\t}\n\n\tprivate LPTranslation(ITranslation trans) {\n\t\tthis.trans = trans;\n\t}\n\n\tpublic LPTranslation inverse() {\n\t\treturn new LPTranslation(trans.inverse());\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn trans.getOriginal();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPUVScale.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\n\npublic class LPUVScale implements I3DOperation {\n\n\tprivate final Object obj;\n\n\tpublic LPUVScale(double i, double d) {\n\t\tobj = SimpleServiceLocator.cclProxy.getUVScale(i, d);\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn obj;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPUVTransformationList.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\n\npublic class LPUVTransformationList implements I3DOperation {\n\n\tprivate final Object obj;\n\n\tpublic LPUVTransformationList(I3DOperation... uvTranslation) {\n\t\tobj = SimpleServiceLocator.cclProxy.getUVTransformationList(uvTranslation);\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn obj;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/object3d/operation/LPUVTranslation.java",
    "content": "package logisticspipes.proxy.object3d.operation;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\n\npublic class LPUVTranslation implements I3DOperation {\n\n\tprivate final Object obj;\n\n\tpublic LPUVTranslation(float i, float f) {\n\t\tobj = SimpleServiceLocator.cclProxy.getUVTranslation(i, f);\n\t}\n\n\t@Override\n\tpublic Object getOriginal() {\n\t\treturn obj;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/opencomputers/IOCTile.java",
    "content": "package logisticspipes.proxy.opencomputers;\n\npublic interface IOCTile {\n\n\tObject getOCNode();\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/opencomputers/OpenComputersProxy.java",
    "content": "package logisticspipes.proxy.opencomputers;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\n\nimport li.cil.oc.api.Network;\nimport li.cil.oc.api.network.Node;\nimport li.cil.oc.api.network.Visibility;\n\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.interfaces.IOpenComputersProxy;\n\npublic class OpenComputersProxy implements IOpenComputersProxy {\n\n\t@Override\n\tpublic void initLogisticsTileGenericPipe(LogisticsTileGenericPipe tile) {\n\t\ttile.node = Network.newNode(tile, Visibility.Neighbors).withComponent(\"logisticspipe\", Visibility.Neighbors).create();\n\t}\n\n\t@Override\n\tpublic void initLogisticsSolidTileEntity(LogisticsSolidTileEntity tile) {\n\t\ttile.node = Network.newNode(tile, Visibility.Neighbors).withComponent(\"logisticssolidblock\", Visibility.Neighbors).create();\n\t}\n\n\t@Override\n\tpublic void addToNetwork(TileEntity tile) {\n\t\tNetwork.joinOrCreateNetwork(tile);\n\t}\n\n\t@Override\n\tpublic void handleInvalidate(IOCTile tile) {\n\t\tif (tile.getOCNode() != null) {\n\t\t\t((Node) tile.getOCNode()).remove();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleChunkUnload(IOCTile tile) {\n\t\tif (tile.getOCNode() != null) {\n\t\t\t((Node) tile.getOCNode()).remove();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleReadFromNBT(IOCTile tile, NBTTagCompound nbt) {\n\t\tif (tile.getOCNode() != null && ((Node) tile.getOCNode()).host() == tile) {\n\t\t\t((Node) tile.getOCNode()).load(nbt.getCompoundTag(\"oc:node\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void handleWriteToNBT(IOCTile tile, NBTTagCompound nbt) {\n\t\tif (tile.getOCNode() != null && ((Node) tile.getOCNode()).host() == tile) {\n\t\t\tfinal NBTTagCompound nodeNbt = new NBTTagCompound();\n\t\t\t((Node) tile.getOCNode()).save(nodeNbt);\n\t\t\tnbt.setTag(\"oc:node\", nodeNbt);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/opencomputers/asm/BaseWrapperClass.java",
    "content": "package logisticspipes.proxy.opencomputers.asm;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.DimensionManager;\n\nimport li.cil.oc.api.machine.Arguments;\nimport li.cil.oc.api.machine.Callback;\nimport li.cil.oc.api.machine.Context;\nimport li.cil.oc.api.prefab.AbstractValue;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.computers.interfaces.CCCommand;\nimport logisticspipes.proxy.computers.interfaces.CCDirectCall;\nimport logisticspipes.proxy.computers.interfaces.CCQueued;\nimport logisticspipes.proxy.computers.interfaces.ICCTypeWrapped;\nimport logisticspipes.proxy.computers.objects.CCItemIdentifier.CCItemIdentifierImplementation;\nimport logisticspipes.proxy.computers.objects.CCItemIdentifierBuilder;\nimport logisticspipes.proxy.computers.objects.CCItemIdentifierStack.CCItemIdentifierStackImplementation;\nimport logisticspipes.proxy.computers.objects.LPGlobalCCAccess;\nimport logisticspipes.proxy.computers.wrapper.CCObjectWrapper;\nimport logisticspipes.proxy.computers.wrapper.CCWrapperInformation;\nimport logisticspipes.proxy.computers.wrapper.ICommandWrapper;\nimport logisticspipes.security.PermissionException;\nimport logisticspipes.ticks.QueuedTasks;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic abstract class BaseWrapperClass extends AbstractValue {\n\n\tpublic static final ICommandWrapper WRAPPER = new ICommandWrapper() {\n\n\t\tprivate Map<Class<?>, Class<? extends BaseWrapperClass>> map = new HashMap<>();\n\n\t\t@Override\n\t\tpublic Object getWrappedObject(CCWrapperInformation info, Object object) {\n\t\t\ttry {\n\t\t\t\tClass<? extends BaseWrapperClass> clazz = map.get(object.getClass());\n\t\t\t\tif (clazz == null) {\n\t\t\t\t\tclazz = ClassCreator.getWrapperClass(info, object.getClass().getName());\n\t\t\t\t\tmap.put(object.getClass(), clazz);\n\t\t\t\t}\n\t\t\t\treturn clazz.getConstructor(CCWrapperInformation.class, Object.class).newInstance(info, object);\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate final CCWrapperInformation info;\n\tprivate Object object;\n\tpublic boolean isDirectCall;\n\n\tpublic BaseWrapperClass(String wrappedClass) throws ClassNotFoundException {\n\t\tthis(CCObjectWrapper.getWrapperInformation(Class.forName(wrappedClass)), null);\n\t}\n\n\tpublic BaseWrapperClass(CCWrapperInformation info, Object object) {\n\t\tsuper();\n\t\tthis.info = info;\n\t\tthis.object = object;\n\t}\n\n\t@Callback(direct = true)\n\tpublic Object[] help(Context context, Arguments args) throws Exception {\n\t\tif (object == null) {\n\t\t\tthrow new Exception(\"This LP object is not persistable\");\n\t\t}\n\t\tStringBuilder help = new StringBuilder();\n\t\tStringBuilder head = new StringBuilder();\n\t\tStringBuilder head2 = new StringBuilder();\n\t\thead.append(\"Type: \");\n\t\thead.append(info.type);\n\t\thead.append(\"\\n\");\n\t\thead2.append(\"Commands: \\n\");\n\t\tfor (Integer num : info.commands.keySet()) {\n\t\t\tMethod method = info.commands.get(num);\n\t\t\tStringBuilder command = new StringBuilder();\n\t\t\tif (help.length() != 0) {\n\t\t\t\tcommand.append(\"\\n\");\n\t\t\t}\n\t\t\tint number = num.intValue();\n\t\t\tif (number < 10) {\n\t\t\t\tcommand.append(\" \");\n\t\t\t}\n\t\t\tcommand.append(number);\n\t\t\tcommand.append(\" \");\n\t\t\tif (method.isAnnotationPresent(CCDirectCall.class)) {\n\t\t\t\tcommand.append(\"D\");\n\t\t\t} else {\n\t\t\t\tcommand.append(\" \");\n\t\t\t}\n\t\t\tif (method.isAnnotationPresent(CCQueued.class)) {\n\t\t\t\tcommand.append(\"Q\");\n\t\t\t} else {\n\t\t\t\tcommand.append(\" \");\n\t\t\t}\n\t\t\tcommand.append(\": \");\n\t\t\tcommand.append(method.getName());\n\t\t\tStringBuilder param = new StringBuilder();\n\t\t\tparam.append(\"(\");\n\t\t\tboolean a = false;\n\t\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\t\tif (a) {\n\t\t\t\t\tparam.append(\", \");\n\t\t\t\t}\n\t\t\t\tparam.append(clazz.getSimpleName());\n\t\t\t\ta = true;\n\t\t\t}\n\t\t\tparam.append(\")\");\n\t\t\tif (param.toString().length() + command.length() > 50) {\n\t\t\t\tcommand.append(\"\\n      ---\");\n\t\t\t}\n\t\t\tcommand.append(param.toString());\n\t\t\thelp.append(command.toString());\n\t\t}\n\t\tString commands = help.toString();\n\t\tString[] lines = commands.split(\"\\n\");\n\t\tif (lines.length > 16) {\n\t\t\tint pageNumber = 1;\n\t\t\tif (args.count() > 0) {\n\t\t\t\tif (args.isDouble(0) || args.isInteger(0)) {\n\t\t\t\t\tpageNumber = args.checkInteger(0);\n\t\t\t\t\tif (pageNumber < 1) {\n\t\t\t\t\t\tpageNumber = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tStringBuilder page = new StringBuilder();\n\t\t\tpage.append(head.toString());\n\t\t\tpage.append(\"Page \");\n\t\t\tpage.append(pageNumber);\n\t\t\tpage.append(\" of \");\n\t\t\tpage.append((int) (Math.floor(lines.length / 10) + (lines.length % 10 == 0 ? 0 : 1)));\n\t\t\tpage.append(\"\\n\");\n\t\t\tpage.append(head2.toString());\n\t\t\tpageNumber--;\n\t\t\tint from = pageNumber * 11;\n\t\t\tint to = pageNumber * 11 + 11;\n\t\t\tfor (int i = from; i < to; i++) {\n\t\t\t\tif (i < lines.length) {\n\t\t\t\t\tpage.append(lines[i]);\n\t\t\t\t}\n\t\t\t\tif (i < to - 1) {\n\t\t\t\t\tpage.append(\"\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn new Object[] { page.toString() };\n\t\t} else {\n\t\t\tfor (int i = 0; i < 16 - lines.length; i++) {\n\t\t\t\tString buffer = head.toString();\n\t\t\t\thead = new StringBuilder();\n\t\t\t\thead.append(\"\\n\").append(buffer);\n\t\t\t}\n\t\t}\n\t\treturn new Object[] { String.format(\"%s%s%s\", head, head2, help) };\n\t}\n\n\t@Callback(direct = true)\n\tpublic Object[] helpCommand(Context context, Arguments args) throws Exception {\n\t\tif (object == null) {\n\t\t\tthrow new Exception(\"This LP object is not persistable\");\n\t\t}\n\t\tif (args.count() != 1) {\n\t\t\treturn new Object[] { \"Wrong Argument Count\" };\n\t\t}\n\t\tif (!args.isInteger(0)) {\n\t\t\treturn new Object[] { \"Wrong Argument Type\" };\n\t\t}\n\t\tInteger number = args.checkInteger(0);\n\t\tif (!info.commands.containsKey(number)) {\n\t\t\treturn new Object[] { \"No command with that index\" };\n\t\t}\n\t\tMethod method = info.commands.get(number);\n\t\tStringBuilder help = new StringBuilder();\n\t\thelp.append(\"---------------------------------\\n\");\n\t\thelp.append(\"Command: \");\n\t\thelp.append(method.getName());\n\t\thelp.append(\"\\n\");\n\t\thelp.append(\"Parameter: \");\n\t\tif (method.getParameterTypes().length > 0) {\n\t\t\thelp.append(\"\\n\");\n\t\t\tboolean a = false;\n\t\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\t\tif (a) {\n\t\t\t\t\thelp.append(\", \");\n\t\t\t\t}\n\t\t\t\thelp.append(clazz.getSimpleName());\n\t\t\t\ta = true;\n\t\t\t}\n\t\t\thelp.append(\"\\n\");\n\t\t} else {\n\t\t\thelp.append(\"NONE\\n\");\n\t\t}\n\t\thelp.append(\"Return Type: \");\n\t\thelp.append(method.getReturnType().getName());\n\t\thelp.append(\"\\n\");\n\t\thelp.append(\"Description: \\n\");\n\t\thelp.append(method.getAnnotation(CCCommand.class).description());\n\t\treturn new Object[] { help.toString() };\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tif (object != null) {\n\t\t\ttry {\n\t\t\t\tif (object.getClass().getMethod(\"toString\").getDeclaringClass() != Object.class) {\n\t\t\t\t\treturn getType() + \": \" + object.toString();\n\t\t\t\t}\n\t\t\t\tif (object instanceof ICCTypeWrapped) {\n\t\t\t\t\tif (((ICCTypeWrapped) object).getObject().getClass().getMethod(\"toString\").getDeclaringClass() != Object.class) {\n\t\t\t\t\t\treturn getType() + \": \" + ((ICCTypeWrapped) object).getObject().toString();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (NoSuchMethodException | SecurityException e) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn getType();\n\t}\n\n\tpublic Object[] invokeMethod(String methodName, Context context, Arguments args) throws Exception {\n\t\tif (object == null) {\n\t\t\tthrow new Exception(\"This LP object is not persistable\");\n\t\t}\n\n\t\tint length = args.count();\n\t\tObject[] arguments = new Object[length];\n\t\tfor (int i = 0; i < length; i++) {\n\t\t\tif (args.isString(i)) {\n\t\t\t\targuments[i] = args.checkString(i);\n\t\t\t} else {\n\t\t\t\tObject tmp = args.checkAny(i);\n\t\t\t\tif (tmp instanceof BaseWrapperClass) {\n\t\t\t\t\ttmp = ((BaseWrapperClass) tmp).getObject();\n\t\t\t\t}\n\t\t\t\tif (tmp instanceof ICCTypeWrapped) {\n\t\t\t\t\ttmp = ((ICCTypeWrapped) tmp).getObject();\n\t\t\t\t}\n\t\t\t\targuments[i] = tmp;\n\t\t\t}\n\t\t}\n\n\t\tMethod match = null;\n\t\tfor (Method method : info.commands.values()) {\n\t\t\tif (!method.getName().equalsIgnoreCase(methodName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!argumentsMatch(method, arguments)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmatch = method;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (match == null) {\n\t\t\tStringBuilder error = new StringBuilder();\n\t\t\terror.append(\"No such method.\");\n\t\t\tboolean handled = false;\n\t\t\tfor (Method method : info.commands.values()) {\n\t\t\t\tif (!method.getName().equalsIgnoreCase(methodName)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (handled) {\n\t\t\t\t\terror.append(\"\\n\");\n\t\t\t\t}\n\t\t\t\thandled = true;\n\t\t\t\terror.append(method.getName());\n\t\t\t\terror.append(\"(\");\n\t\t\t\tboolean a = false;\n\t\t\t\tfor (Class<?> clazz : method.getParameterTypes()) {\n\t\t\t\t\tif (a) {\n\t\t\t\t\t\terror.append(\", \");\n\t\t\t\t\t}\n\t\t\t\t\terror.append(clazz.getName());\n\t\t\t\t\ta = true;\n\t\t\t\t}\n\t\t\t\terror.append(\")\");\n\t\t\t}\n\t\t\tif (!handled) {\n\t\t\t\terror = new StringBuilder();\n\t\t\t\terror.append(\"Internal Excption (Code: 1, \");\n\t\t\t\terror.append(methodName);\n\t\t\t\terror.append(\")\");\n\t\t\t}\n\t\t\tthrow new UnsupportedOperationException(error.toString());\n\t\t}\n\n\t\tif (match.getAnnotation(CCDirectCall.class) != null) {\n\t\t\tif (!isDirectCall) {\n\t\t\t\tthrow new PermissionException();\n\t\t\t}\n\t\t}\n\n\t\tif (match.getAnnotation(CCCommand.class).needPermission()) {\n\t\t\tif (info.securityMethod != null) {\n\t\t\t\ttry {\n\t\t\t\t\tinfo.securityMethod.invoke(object);\n\t\t\t\t} catch (InvocationTargetException e) {\n\t\t\t\t\tif (e.getTargetException() instanceof Exception) {\n\t\t\t\t\t\tthrow (Exception) e.getTargetException();\n\t\t\t\t\t}\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tObject result;\n\t\ttry {\n\t\t\tresult = match.invoke(object, arguments);\n\t\t} catch (InvocationTargetException e) {\n\t\t\tif (e.getTargetException() instanceof Exception) {\n\t\t\t\tthrow (Exception) e.getTargetException();\n\t\t\t}\n\t\t\tthrow e;\n\t\t}\n\t\treturn CCObjectWrapper.createArray(CCObjectWrapper.getWrappedObject(result, BaseWrapperClass.WRAPPER));\n\t}\n\n\tprivate boolean argumentsMatch(Method method, Object[] arguments) {\n\t\tint i = 0;\n\t\tfor (Class<?> args : method.getParameterTypes()) {\n\t\t\tif (arguments.length <= i) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!args.isAssignableFrom(arguments[i].getClass())) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ti++;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic String getType() {\n\t\treturn info.type;\n\t}\n\n\tpublic Object getObject() {\n\t\treturn object;\n\t}\n\n\t@Override\n\tpublic void load(NBTTagCompound nbt) {\n\t\tif (object != null) {\n\t\t\treturn;\n\t\t}\n\t\tString type = nbt.getString(\"Type\");\n\t\tif (type.equals(\"\")) {\n\t\t\treturn;\n\t\t}\n\t\tif (type.equals(\"LPGlobalCCAccess\")) {\n\t\t\tobject = LogisticsPipes.getComputerLP();\n\t\t\tcheckType();\n\t\t} else if (type.equals(\"CoreRoutedPipe\")) {\n\t\t\tint x = nbt.getInteger(\"X\");\n\t\t\tint y = nbt.getInteger(\"Y\");\n\t\t\tint z = nbt.getInteger(\"Z\");\n\t\t\tfinal DoubleCoordinates pos = new DoubleCoordinates(x, y, z);\n\t\t\tfinal int dim = nbt.getInteger(\"Dim\");\n\t\t\tQueuedTasks.queueTask(() -> {\n\t\t\t\tWorld world = DimensionManager.getWorld(dim);\n\t\t\t\tif (world != null) {\n\t\t\t\t\tTileEntity tile = pos.getTileEntity(world);\n\t\t\t\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe instanceof CoreRoutedPipe) {\n\t\t\t\t\t\tobject = ((LogisticsTileGenericPipe) tile).pipe;\n\t\t\t\t\t\tcheckType();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t} else if (type.equals(\"CCItemIdentifierImplementation\")) {\n\t\t\tItemStack stack = ItemStackLoader.loadAndFixItemStackFromNBT(nbt);\n\t\t\tif (!stack.isEmpty()) {\n\t\t\t\tobject = new CCItemIdentifierImplementation(ItemIdentifier.get(stack));\n\t\t\t\tcheckType();\n\t\t\t}\n\t\t} else if (type.equals(\"CCItemIdentifierStackImplementation\")) {\n\t\t\tItemStack stack = ItemStackLoader.loadAndFixItemStackFromNBT(nbt);\n\t\t\tif (!stack.isEmpty()) {\n\t\t\t\tobject = new CCItemIdentifierStackImplementation(ItemIdentifierStack.getFromStack(stack));\n\t\t\t\tcheckType();\n\t\t\t}\n\t\t} else if (type.equals(\"CCItemIdentifierBuilder\")) {\n\t\t\tItemStack stack = ItemStackLoader.loadAndFixItemStackFromNBT(nbt);\n\t\t\tif (!stack.isEmpty()) {\n\t\t\t\tCCItemIdentifierBuilder builder = new CCItemIdentifierBuilder();\n\t\t\t\tbuilder.setItemID(Double.valueOf(Item.getIdFromItem(stack.getItem())));\n\t\t\t\tbuilder.setItemData((double) stack.getItemDamage());\n\t\t\t\tobject = builder;\n\t\t\t\tcheckType();\n\t\t\t}\n\t\t} else if (type.equals(\"LogisticsSolidTileEntity\")) {\n\t\t\tint x = nbt.getInteger(\"X\");\n\t\t\tint y = nbt.getInteger(\"Y\");\n\t\t\tint z = nbt.getInteger(\"Z\");\n\t\t\tfinal DoubleCoordinates pos = new DoubleCoordinates(x, y, z);\n\t\t\tfinal int dim = nbt.getInteger(\"Dim\");\n\t\t\tQueuedTasks.queueTask(() -> {\n\t\t\t\tWorld world = DimensionManager.getWorld(dim);\n\t\t\t\tif (world != null) {\n\t\t\t\t\tTileEntity tile = pos.getTileEntity(world);\n\t\t\t\t\tif (tile instanceof LogisticsSolidTileEntity) {\n\t\t\t\t\t\tobject = tile;\n\t\t\t\t\t\tcheckType();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t} else {\n\t\t\tSystem.out.println(\"Unknown type to load\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic void save(NBTTagCompound nbt) {\n\t\tif (object == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (object instanceof LPGlobalCCAccess) {\n\t\t\tnbt.setString(\"Type\", \"LPGlobalCCAccess\");\n\t\t} else if (object instanceof CoreRoutedPipe) {\n\t\t\tDoubleCoordinates pos = ((CoreRoutedPipe) object).getLPPosition();\n\t\t\tnbt.setString(\"Type\", \"CoreRoutedPipe\");\n\t\t\tnbt.setInteger(\"Dim\", ((CoreRoutedPipe) object).getWorld().provider.getDimension());\n\t\t\tnbt.setInteger(\"X\", pos.getXInt());\n\t\t\tnbt.setInteger(\"Y\", pos.getYInt());\n\t\t\tnbt.setInteger(\"Z\", pos.getZInt());\n\t\t} else if (object instanceof CCItemIdentifierImplementation) {\n\t\t\tnbt.setString(\"Type\", \"CCItemIdentifierImplementation\");\n\t\t\t((CCItemIdentifierImplementation) object).getObject().makeNormalStack(1).writeToNBT(nbt);\n\t\t} else if (object instanceof CCItemIdentifierStackImplementation) {\n\t\t\tnbt.setString(\"Type\", \"CCItemIdentifierStackImplementation\");\n\t\t\t((CCItemIdentifierStackImplementation) object).getObject().makeNormalStack().writeToNBT(nbt);\n\t\t} else if (object instanceof CCItemIdentifierBuilder) {\n\t\t\tnbt.setString(\"Type\", \"CCItemIdentifierBuilder\");\n\t\t\t((CCItemIdentifierBuilder) object).build().makeNormalStack(1).writeToNBT(nbt);\n\t\t} else if (object instanceof LogisticsSolidTileEntity) {\n\t\t\tDoubleCoordinates pos = ((LogisticsSolidTileEntity) object).getLPPosition();\n\t\t\tnbt.setString(\"Type\", \"LogisticsSolidTileEntity\");\n\t\t\tnbt.setInteger(\"Dim\", ((LogisticsSolidTileEntity) object).getWorld().provider.getDimension());\n\t\t\tnbt.setInteger(\"X\", pos.getXInt());\n\t\t\tnbt.setInteger(\"Y\", pos.getYInt());\n\t\t\tnbt.setInteger(\"Z\", pos.getZInt());\n\t\t} else {\n\t\t\tSystem.out.println(\"Couldn't find mapping for: \" + object.getClass());\n\t\t}\n\t}\n\n\tprivate void checkType() {\n\t\tif (object != null) {\n\t\t\tif (CCObjectWrapper.getWrapperInformation(object.getClass()) != info) {\n\t\t\t\tSystem.out.println(\"WrapperInformationTypes didn't match\");\n\t\t\t\tobject = null;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object[] call(Context context, Arguments arguments) {\n\t\ttry {\n\t\t\treturn help(context, arguments);\n\t\t} catch (Exception e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/opencomputers/asm/ClassCreator.java",
    "content": "package logisticspipes.proxy.opencomputers.asm;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.launchwrapper.Launch;\n\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\n\nimport logisticspipes.proxy.computers.wrapper.CCWrapperInformation;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class ClassCreator {\n\n\tprivate static List<String> createdClasses = new ArrayList<>();\n\n\tpublic static byte[] getWrappedClassAsBytes(CCWrapperInformation info, String className) {\n\n\t\tString newClassName_DOT = \"logisticspipes.proxy.opencomputers.asm.BaseWrapperClass$\" + className + \"$OpenComputersWrapper\";\n\t\tString newClassName_SLASH = newClassName_DOT.replace('.', '/');\n\t\tString newClassName_TYPE = \"L\" + newClassName_SLASH + \";\";\n\n\t\tClassWriter cw = new ClassWriter(0);\n\n\t\tcw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, newClassName_SLASH, null, \"logisticspipes/proxy/opencomputers/asm/BaseWrapperClass\", null);\n\n\t\t{\n\t\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, \"<init>\", \"()V\", null, new String[] { \"java/lang/ClassNotFoundException\" });\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitLineNumber(10, l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitLdcInsn(className);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKESPECIAL, \"logisticspipes/proxy/opencomputers/asm/BaseWrapperClass\", \"<init>\", \"(Ljava/lang/String;)V\");\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitLineNumber(11, l1);\n\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\tLabel l2 = new Label();\n\t\t\tmv.visitLabel(l2);\n\t\t\tmv.visitLocalVariable(\"this\", newClassName_TYPE, null, l0, l2, 0);\n\t\t\tmv.visitMaxs(2, 1);\n\t\t\tmv.visitEnd();\n\t\t}\n\t\t{\n\t\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, \"<init>\", \"(Llogisticspipes/proxy/computers/wrapper/CCWrapperInformation;Ljava/lang/Object;)V\", null, null);\n\t\t\tmv.visitCode();\n\t\t\tLabel l0 = new Label();\n\t\t\tmv.visitLabel(l0);\n\t\t\tmv.visitLineNumber(14, l0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\t\tmv.visitVarInsn(Opcodes.ALOAD, 2);\n\t\t\tmv.visitMethodInsn(Opcodes.INVOKESPECIAL, \"logisticspipes/proxy/opencomputers/asm/BaseWrapperClass\", \"<init>\", \"(Llogisticspipes/proxy/computers/wrapper/CCWrapperInformation;Ljava/lang/Object;)V\");\n\t\t\tLabel l1 = new Label();\n\t\t\tmv.visitLabel(l1);\n\t\t\tmv.visitLineNumber(15, l1);\n\t\t\tmv.visitInsn(Opcodes.RETURN);\n\t\t\tLabel l2 = new Label();\n\t\t\tmv.visitLabel(l2);\n\t\t\tmv.visitLocalVariable(\"this\", newClassName_TYPE, null, l0, l2, 0);\n\t\t\tmv.visitLocalVariable(\"info\", \"Llogisticspipes/proxy/computers/wrapper/CCWrapperInformation;\", null, l0, l2, 1);\n\t\t\tmv.visitLocalVariable(\"object\", \"Ljava/lang/Object;\", null, l0, l2, 2);\n\t\t\tmv.visitMaxs(3, 3);\n\t\t\tmv.visitEnd();\n\t\t}\n\n\t\tfor (String method : info.commandTypes.keySet()) {\n\t\t\tPair<Boolean, String> desc = info.commandTypes.get(method);\n\t\t\tClassCreator.addMethod(cw, method, !desc.getValue1(), desc.getValue2(), newClassName_TYPE);\n\t\t}\n\n\t\tcw.visitEnd();\n\n\t\tClassCreator.createdClasses.add(className);\n\n\t\treturn cw.toByteArray();\n\t}\n\n\tpublic static Class<? extends BaseWrapperClass> getWrapperClass(CCWrapperInformation info, String className) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n\t\tString newClassName_DOT = \"logisticspipes.proxy.opencomputers.asm.BaseWrapperClass$\" + className + \"$OpenComputersWrapper\";\n\t\tif (ClassCreator.createdClasses.contains(className)) {\n\t\t\ttry {\n\t\t\t\treturn (Class<? extends BaseWrapperClass>) Class.forName(newClassName_DOT);\n\t\t\t} catch (ClassNotFoundException ignored) {}\n\t\t}\n\t\tbyte[] bytes = ClassCreator.getWrappedClassAsBytes(info, className);\n\t\treturn (Class<? extends BaseWrapperClass>) ClassCreator.loadClass(bytes, newClassName_DOT);\n\t}\n\n\tprivate static void addMethod(ClassWriter cw, String name, boolean direct, String doc, String newClassName_TYPE) {\n\t\tMethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, \"(Lli/cil/oc/api/machine/Context;Lli/cil/oc/api/machine/Arguments;)[Ljava/lang/Object;\", null, new String[] { \"java/lang/Exception\" });\n\t\t{\n\t\t\tAnnotationVisitor av0 = mv.visitAnnotation(\"Lli/cil/oc/api/machine/Callback;\", true);\n\t\t\tif (direct) {\n\t\t\t\tav0.visit(\"direct\", Boolean.TRUE);\n\t\t\t} else {\n\t\t\t\tav0.visit(\"direct\", Boolean.FALSE);\n\t\t\t}\n\t\t\tav0.visit(\"doc\", doc);\n\t\t\tav0.visitEnd();\n\t\t}\n\t\tmv.visitCode();\n\t\tLabel l0 = new Label();\n\t\tmv.visitLabel(l0);\n\t\tmv.visitLineNumber(19, l0);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 0);\n\t\tmv.visitLdcInsn(name);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 1);\n\t\tmv.visitVarInsn(Opcodes.ALOAD, 2);\n\t\tmv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"logisticspipes/proxy/opencomputers/asm/BaseWrapperClass\", \"invokeMethod\", \"(Ljava/lang/String;Lli/cil/oc/api/machine/Context;Lli/cil/oc/api/machine/Arguments;)[Ljava/lang/Object;\");\n\t\tmv.visitInsn(Opcodes.ARETURN);\n\t\tLabel l1 = new Label();\n\t\tmv.visitLabel(l1);\n\t\tmv.visitLocalVariable(\"this\", newClassName_TYPE, null, l0, l1, 0);\n\t\tmv.visitLocalVariable(\"context\", \"Lli/cil/oc/api/machine/Context;\", null, l0, l1, 1);\n\t\tmv.visitLocalVariable(\"args\", \"Lli/cil/oc/api/machine/Arguments;\", null, l0, l1, 2);\n\t\tmv.visitMaxs(4, 3);\n\t\tmv.visitEnd();\n\t}\n\n\tprivate static Method m_defineClass = null;\n\n\tprivate static Class<?> loadClass(byte[] data, String lookfor) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {\n\t\tif (ClassCreator.m_defineClass == null) {\n\t\t\tClassCreator.m_defineClass = ClassLoader.class.getDeclaredMethod(\"defineClass\", byte[].class, int.class, int.class);\n\t\t\tClassCreator.m_defineClass.setAccessible(true);\n\t\t}\n\t\treturn (Class<?>) ClassCreator.m_defineClass.invoke(Launch.classLoader, data, 0, data.length);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/opencomputers/asm/DummyWrapperClass.java",
    "content": "package logisticspipes.proxy.opencomputers.asm;\n\nimport li.cil.oc.api.machine.Arguments;\nimport li.cil.oc.api.machine.Callback;\nimport li.cil.oc.api.machine.Context;\n\nimport logisticspipes.proxy.computers.wrapper.CCWrapperInformation;\n\npublic class DummyWrapperClass extends BaseWrapperClass {\n\n\tpublic DummyWrapperClass() throws ClassNotFoundException {\n\t\tsuper(\"dummy.class.replace.automaticly\");\n\t}\n\n\tpublic DummyWrapperClass(CCWrapperInformation info, Object object) {\n\t\tsuper(info, object);\n\t}\n\n\t@Callback(direct = true, doc = \"Dummy documentation\")\n\tpublic Object[] dummyCall(Context context, Arguments args) throws Exception {\n\t\treturn invokeMethod(\"dummyCall\", context, args);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/progressprovider/MachineProgressProvider.java",
    "content": "package logisticspipes.proxy.progressprovider;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.api.IProgressProvider;\nimport logisticspipes.proxy.interfaces.IGenericProgressProvider;\n\npublic class MachineProgressProvider {\n\n\tprivate List<IGenericProgressProvider> providers = new ArrayList<>();\n\n\tpublic void registerProgressProvider(IGenericProgressProvider provider) {\n\t\tproviders.add(provider);\n\t}\n\n\tpublic byte getProgressForTile(TileEntity tile) {\n\t\tif (tile instanceof IProgressProvider) {\n\t\t\treturn ((IProgressProvider) tile).getMachineProgressForLP();\n\t\t}\n\t\tfor (IGenericProgressProvider provider : providers) {\n\t\t\tif (provider.isType(tile)) {\n\t\t\t\treturn provider.getProgress(tile);\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/recipeproviders/AssemblyAdvancedWorkbench.java",
    "content": "/*\npackage logisticspipes.proxy.recipeproviders;\n\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\n\nimport buildcraft.silicon.TileAdvancedCraftingTable;\n\npublic class AssemblyAdvancedWorkbench implements ICraftingRecipeProvider {\n\n\t@Override\n\tpublic boolean canOpenGui(TileEntity tile) {\n\t\treturn (tile instanceof TileAdvancedCraftingTable);\n\t}\n\n\t@Override\n\tpublic boolean importRecipe(TileEntity tile, ItemIdentifierInventory inventory) {\n\t\tif (!(tile instanceof TileAdvancedCraftingTable)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tTileAdvancedCraftingTable bench = (TileAdvancedCraftingTable) tile;\n\t\tItemStack result = bench.getOutputSlot().getStackInSlot(0);\n\n\t\tif (result == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tinventory.setInventorySlotContents(9, result);\n\n\t\t// Import\n\t\tfor (int i = 0; i < bench.getCraftingSlots().getSizeInventory(); i++) {\n\t\t\tif (i >= inventory.getSizeInventory() - 2) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfinal ItemStack newStack = bench.getCraftingSlots().getStackInSlot(i) == null ? null : bench.getCraftingSlots().getStackInSlot(i).copy();\n\t\t\tinventory.setInventorySlotContents(i, newStack);\n\t\t}\n\n\t\t// Compact\n\t\tfor (int i = 0; i < inventory.getSizeInventory() - 2; i++) {\n\t\t\tfinal ItemIdentifierStack stackInSlot = inventory.getIDStackInSlot(i);\n\t\t\tif (stackInSlot == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfinal ItemIdentifier itemInSlot = stackInSlot.getItem();\n\t\t\tfor (int j = i + 1; j < inventory.getSizeInventory() - 2; j++) {\n\t\t\t\tfinal ItemIdentifierStack stackInOtherSlot = inventory.getIDStackInSlot(j);\n\t\t\t\tif (stackInOtherSlot == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (itemInSlot.equals(stackInOtherSlot.getItem())) {\n\t\t\t\t\tstackInSlot.setStackSize(stackInSlot.getStackSize() + stackInOtherSlot.getStackSize());\n\t\t\t\t\tinventory.setInventorySlotContents(i, stackInSlot);\n\t\t\t\t\tinventory.clearInventorySlotContents(j);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (int i = 0; i < inventory.getSizeInventory() - 2; i++) {\n\t\t\tif (inventory.getStackInSlot(i) != null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (int j = i + 1; j < inventory.getSizeInventory() - 2; j++) {\n\t\t\t\tif (inventory.getStackInSlot(j) == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tinventory.setInventorySlotContents(i, inventory.getIDStackInSlot(j));\n\t\t\t\tinventory.clearInventorySlotContents(j);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/proxy/recipeproviders/AutoWorkbench.java",
    "content": "/*\npackage logisticspipes.proxy.recipeproviders;\n\nimport logisticspipes.proxy.interfaces.ICraftingRecipeProvider;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\n\nimport buildcraft.factory.TileAutoWorkbench;\n\npublic class AutoWorkbench implements ICraftingRecipeProvider {\n\n\t@Override\n\tpublic boolean canOpenGui(TileEntity tile) {\n\t\treturn (tile instanceof TileAutoWorkbench);\n\t}\n\n\t@Override\n\tpublic boolean importRecipe(TileEntity tile, ItemIdentifierInventory inventory) {\n\t\tif (!(tile instanceof TileAutoWorkbench)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tTileAutoWorkbench bench = (TileAutoWorkbench) tile;\n\t\tItemStack result = bench.craftMatrix.getRecipeOutput();\n\t\t//ItemStack result = bench.getStackInSlot(TileAutoWorkbench.SLOT_RESULT);\n\n\t\tif (result == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tinventory.setInventorySlotContents(9, result);\n\n\t\t// Import\n\t\tfor (int i = 0; i < bench.craftMatrix.getSizeInventory(); i++) {\n\t\t\tif (i >= inventory.getSizeInventory() - 2) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfinal ItemStack newStack = bench.craftMatrix.getStackInSlot(i).copy();\n\t\t\tif (!newStack.isEmpty() && newStack.stackSize > 1) {\n\t\t\t\tnewStack.stackSize = 1;\n\t\t\t}\n\t\t\tinventory.setInventorySlotContents(i, newStack);\n\t\t}\n\n\t\tinventory.compactFirst(9);\n\n\t\treturn true;\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/proxy/recipeproviders/LogisticsCraftingTable.java",
    "content": "package logisticspipes.proxy.recipeproviders;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity;\nimport logisticspipes.proxy.interfaces.IFuzzyRecipeProvider;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.inventory.FuzzySlotAccess;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.inventory.SlotAccess;\nimport network.rs485.logisticspipes.property.BitSetProperty;\n\npublic class LogisticsCraftingTable implements IFuzzyRecipeProvider {\n\n\t@Override\n\tpublic boolean canOpenGui(TileEntity tile) {\n\t\treturn (tile instanceof LogisticsCraftingTableTileEntity);\n\t}\n\n\t@Override\n\tpublic boolean importRecipe(TileEntity tile, IItemIdentifierInventory inventory) {\n\t\tif (!(tile instanceof LogisticsCraftingTableTileEntity)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tLogisticsCraftingTableTileEntity bench = (LogisticsCraftingTableTileEntity) tile;\n\t\tItemIdentifierStack result = bench.resultInv.getIDStackInSlot(0);\n\n\t\tif (result == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tinventory.setInventorySlotContents(9, result);\n\n\t\t// Import\n\t\tfor (int i = 0; i < bench.matrix.getSizeInventory(); i++) {\n\t\t\tif (i >= inventory.getSizeInventory() - 2) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tItemStack stackInSlot = bench.matrix.getStackInSlot(i);\n\t\t\tif (!stackInSlot.isEmpty() && stackInSlot.getCount() > 1) {\n\t\t\t\tstackInSlot = stackInSlot.copy();\n\t\t\t\tstackInSlot.setCount(1);\n\t\t\t}\n\t\t\tinventory.setInventorySlotContents(i, stackInSlot);\n\t\t}\n\n\t\tif (!bench.isFuzzy()) {\n\t\t\tinventory.getSlotAccess().compactFirst(9);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void importFuzzyFlags(TileEntity tile, SlotAccess slotAccess, BitSetProperty fuzzyFlags) {\n\t\tif (!(tile instanceof LogisticsCraftingTableTileEntity)) {\n\t\t\treturn;\n\t\t}\n\n\t\tLogisticsCraftingTableTileEntity bench = (LogisticsCraftingTableTileEntity) tile;\n\n\t\tif (!bench.isFuzzy()) {\n\t\t\treturn;\n\t\t}\n\n\t\tfuzzyFlags.replaceWith(bench.fuzzyFlags);\n\t\tnew FuzzySlotAccess(slotAccess, fuzzyFlags).compactFirst(9);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/side/ClientProxy.java",
    "content": "package logisticspipes.proxy.side;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.block.model.ModelResourceLocation;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.network.INetHandler;\nimport net.minecraft.network.NetHandlerPlayServer;\nimport net.minecraft.server.integrated.IntegratedServer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.TextComponentString;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.model.ModelLoader;\nimport net.minecraftforge.client.model.ModelLoaderRegistry;\nimport net.minecraftforge.common.DimensionManager;\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.client.registry.ClientRegistry;\nimport net.minecraftforge.fml.common.FMLCommonHandler;\nimport net.minecraftforge.fml.common.registry.ForgeRegistries;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.gui.GuiCraftingPipe;\nimport logisticspipes.gui.modules.ModuleBaseGui;\nimport logisticspipes.gui.popup.SelectItemOutOfList;\nimport logisticspipes.interfaces.ILogisticsItem;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.DummyContainerSlotClick;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipefxhandlers.PipeFXRenderHandler;\nimport logisticspipes.pipefxhandlers.providers.EntityBlueSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityGoldSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityGreenSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityLightGreenSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityLightRedSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityOrangeSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityRedSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityVioletSparkleFXProvider;\nimport logisticspipes.pipefxhandlers.providers.EntityWhiteSparkleFXProvider;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.interfaces.IProxy;\nimport logisticspipes.renderer.FluidContainerRenderer;\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.renderer.newpipe.GLRenderListHandler;\nimport logisticspipes.renderer.newpipe.LogisticsBlockModel;\nimport logisticspipes.renderer.newpipe.LogisticsNewPipeModel;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen;\nimport logisticspipes.utils.gui.SubGuiScreen;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\n@SideOnly(Side.CLIENT)\npublic class ClientProxy implements IProxy {\n\n\tint renderIndex = 0;\n\n\t@Override\n\tpublic String getSide() {\n\t\treturn \"Client\";\n\t}\n\n\t@Override\n\tpublic World getWorld() {\n\t\treturn FMLClientHandler.instance().getClient().world;\n\t}\n\n\t@Override\n\tpublic void registerTileEntities() {\n\t\tLogisticsRenderPipe lrp = new LogisticsRenderPipe();\n\t\tClientRegistry.bindTileEntitySpecialRenderer(LogisticsTileGenericPipe.class, lrp);\n\n\t\tSimpleServiceLocator.setRenderListHandler(new GLRenderListHandler());\n\t}\n\n\t@Override\n\tpublic EntityPlayer getClientPlayer() {\n\t\treturn FMLClientHandler.instance().getClient().player;\n\t}\n\n\t@Override\n\tpublic void registerParticles() {\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.WhiteParticle, new EntityWhiteSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.RedParticle, new EntityRedSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.BlueParticle, new EntityBlueSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.GreenParticle, new EntityGreenSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.GoldParticle, new EntityGoldSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.VioletParticle, new EntityVioletSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.OrangeParticle, new EntityOrangeSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.LightGreenParticle, new EntityLightGreenSparkleFXProvider());\n\t\tPipeFXRenderHandler.registerParticleHandler(Particles.LightRedParticle, new EntityLightRedSparkleFXProvider());\n\t}\n\n\t@Override\n\tpublic String getName(ItemIdentifier item) {\n\t\treturn item.getFriendlyName();\n\t}\n\n\t@Override\n\tpublic void updateNames(ItemIdentifier item, String name) {\n\t\t//Not Client Side\n\t}\n\n\t@Override\n\tpublic void tick() {\n\t\t//Not Client Side\n\t}\n\n\t@Override\n\tpublic void sendNameUpdateRequest(EntityPlayer player) {\n\t\t//Not Client Side\n\t}\n\n\t@Override\n\tpublic LogisticsTileGenericPipe getPipeInDimensionAt(int dimension, int x, int y, int z, EntityPlayer player) {\n\t\treturn ClientProxy.getPipe(DimensionManager.getWorld(dimension), x, y, z);\n\t}\n\n\t// BuildCraft method\n\n\t/**\n\t * Retrieves pipe at specified coordinates if any.\n\t *\n\t * @param world\n\t * @param x\n\t * @param y\n\t * @param z\n\t * @return\n\t */\n\tprivate static LogisticsTileGenericPipe getPipe(World world, int x, int y, int z) {\n\t\tif (world == null || world.isAirBlock(new BlockPos(x, y, z))) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfinal TileEntity tile = world.getTileEntity(new BlockPos(x, y, z));\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (LogisticsTileGenericPipe) tile;\n\t}\n\n\t// BuildCraft method end\n\n\t@Override\n\tpublic void addLogisticsPipesOverride(Object par1IIconRegister, int index, String override1, String override2, boolean flag) {\n\t\tif (par1IIconRegister != null) {\n\t\t\tTextureMap par1 = (TextureMap) par1IIconRegister;\n\t\t\tif (\"NewPipeTexture\".equals(override2) && !override1.contains(\"status_overlay\")) {\n\t\t\t\tTextures.LPnewPipeIconProvider.setIcon(index, par1.registerSprite(new ResourceLocation(\"logisticspipes\", override1.replace(\"pipes/\", \"blocks/pipes/new_texture/\"))));\n\t\t\t} else if (flag) {\n\t\t\t\tTextures.LPpipeIconProvider.setIcon(index, par1.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/\" + override1)));\n\t\t\t} else {\n\t\t\t\tTextures.LPpipeIconProvider.setIcon(index, par1.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/\" + override1.replace(\"pipes/\", \"pipes/overlay_gen/\") + \"/\" + override2.replace(\"pipes/status_overlay/\", \"\"))));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void sendBroadCast(String message) {\n\t\tif (Minecraft.getMinecraft().player != null) {\n\t\t\tMinecraft.getMinecraft().player.sendMessage(new TextComponentString(\"[LP] Client: \" + message));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void tickServer() {}\n\n\t@Override\n\tpublic void tickClient() {\n\t\tMainProxy.addTick();\n\t\tSimpleServiceLocator.renderListHandler.tick();\n\t}\n\n\t@Override\n\tpublic EntityPlayer getEntityPlayerFromNetHandler(INetHandler handler) {\n\t\tif (handler instanceof NetHandlerPlayServer) {\n\t\t\tEntityPlayerMP player = ((NetHandlerPlayServer) handler).player;\n\t\t\tif (player != null) {\n\t\t\t\treturn player;\n\t\t\t}\n\t\t}\n\t\treturn Minecraft.getMinecraft().player;\n\t}\n\n\t@Override\n\tpublic void setIconProviderFromPipe(ItemLogisticsPipe item, CoreUnroutedPipe dummyPipe) {\n\t\titem.setPipesIcons(dummyPipe.getIconProvider());\n\t}\n\n\t@Override\n\tpublic LogisticsModule getModuleFromGui() {\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof ModuleBaseGui) {\n\t\t\treturn ((ModuleBaseGui) FMLClientHandler.instance().getClient().currentScreen).getModule();\n\t\t}\n\t\tif (FMLClientHandler.instance().getClient().currentScreen instanceof GuiCraftingPipe) {\n\t\t\treturn ((GuiCraftingPipe) FMLClientHandler.instance().getClient().currentScreen).getCraftingModule();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean checkSinglePlayerOwner(String commandSenderName) {\n\t\treturn FMLCommonHandler.instance().getMinecraftServerInstance().isSinglePlayer() && FMLCommonHandler.instance().getMinecraftServerInstance() instanceof IntegratedServer && !((IntegratedServer) FMLCommonHandler.instance().getMinecraftServerInstance()).getPublic();\n\t}\n\n\t@Override\n\tpublic void openFluidSelectGui(final int slotId) {\n\t\tif (Minecraft.getMinecraft().currentScreen instanceof LogisticsBaseGuiScreen) {\n\t\t\tfinal List<ItemIdentifierStack> list = new ArrayList<>();\n\t\t\tfor (FluidIdentifier fluid : FluidIdentifier.all()) {\n\t\t\t\tif (fluid == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlist.add(fluid.getItemIdentifier().makeStack(1));\n\t\t\t}\n\t\t\tSelectItemOutOfList subGui = new SelectItemOutOfList(list, slot -> {\n\t\t\t\tif (slot == -1) return;\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DummyContainerSlotClick.class).setSlotId(slotId).setStack(list.get(slot).makeNormalStack()).setButton(0));\n\t\t\t});\n\t\t\tLogisticsBaseGuiScreen gui = (LogisticsBaseGuiScreen) Minecraft.getMinecraft().currentScreen;\n\t\t\tif (!gui.hasSubGui()) {\n\t\t\t\tgui.setSubGui(subGui);\n\t\t\t} else {\n\t\t\t\tSubGuiScreen nextGui = gui.getSubGui();\n\t\t\t\twhile (nextGui.hasSubGui()) {\n\t\t\t\t\tnextGui = nextGui.getSubGui();\n\t\t\t\t}\n\t\t\t\tnextGui.setSubGui(subGui);\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(String.valueOf(Minecraft.getMinecraft().currentScreen));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void registerModels() {\n\t\tForgeRegistries.ITEMS.getValuesCollection().stream()\n\t\t\t\t.filter(item -> item.getRegistryName().getNamespace().equals(LPConstants.LP_MOD_ID))\n\t\t\t\t.filter(item -> item instanceof ILogisticsItem)\n\t\t\t\t.forEach(item -> registerModels((ILogisticsItem) item));\n\t}\n\n\tprivate void registerModels(ILogisticsItem item) {\n\t\tint mc = item.getModelCount();\n\t\tfor (int i = 0; i < mc; i++) {\n\t\t\tString modelPath = item.getModelPath();\n\t\t\tif (mc > 1) {\n\t\t\t\tString resourcePath = item.getItem().getRegistryName().getPath();\n\t\t\t\tif (modelPath.matches(String.format(\".*%s/%s\", resourcePath, resourcePath))) {\n\t\t\t\t\tmodelPath = String.format(\"%s/%d\", modelPath.substring(0, modelPath.length() - resourcePath.length() - 1), i);\n\t\t\t\t} else {\n\t\t\t\t\tmodelPath = String.format(\"%s.%d\", modelPath, i);\n\t\t\t\t}\n\t\t\t}\n\t\t\tModelLoader.setCustomModelResourceLocation(item.getItem(), i, new ModelResourceLocation(new ResourceLocation(item.getItem().getRegistryName().getNamespace(), modelPath), \"inventory\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void registerTextures() {\n\t\tLogisticsPipes.textures.registerBlockIcons(Minecraft.getMinecraft().getTextureMapBlocks());\n\t\tLogisticsNewRenderPipe.registerTextures(Minecraft.getMinecraft().getTextureMapBlocks());\n\t\tLogisticsNewPipeModel.registerTextures(Minecraft.getMinecraft().getTextureMapBlocks());\n\t\tSimpleServiceLocator.thermalDynamicsProxy.registerTextures(Minecraft.getMinecraft().getTextureMapBlocks());\n\t\trenderIndex++;\n\t}\n\n\t@Override\n\tpublic void initModelLoader() {\n\t\tModelLoaderRegistry.registerLoader(new LogisticsNewPipeModel.LogisticsNewPipeModelLoader());\n\t\tModelLoaderRegistry.registerLoader(new LogisticsBlockModel.Loader());\n\t\tModelLoaderRegistry.registerLoader(new FluidContainerRenderer.FluidContainerRendererModelLoader());\n\t}\n\n\t@Override\n\tpublic int getRenderIndex() {\n\t\treturn renderIndex;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/side/ServerProxy.java",
    "content": "package logisticspipes.proxy.side;\n\nimport java.io.File;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.item.Item;\nimport net.minecraft.network.INetHandler;\nimport net.minecraft.network.NetHandlerPlayServer;\nimport net.minecraft.server.MinecraftServer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.TextComponentString;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.DimensionManager;\nimport net.minecraftforge.common.config.Configuration;\nimport net.minecraftforge.fml.server.FMLServerHandler;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.UpdateName;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.interfaces.IProxy;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class ServerProxy implements IProxy {\n\n\tprivate Configuration langDatabase;\n\tprivate long saveThreadTime = 0;\n\n\tpublic ServerProxy() {\n\t\tlangDatabase = new Configuration(new File(\"config/LogisticsPipes-LangDatabase.cfg\"));\n\t}\n\n\t@Override\n\tpublic String getSide() {\n\t\treturn \"Server\";\n\t}\n\n\t@Override\n\tpublic World getWorld() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void registerTileEntities() {\n\t}\n\n\t@Override\n\tpublic EntityPlayer getClientPlayer() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void registerParticles() {\n\t\t//Only Client Side\n\t}\n\n\tprivate String getNameForCategory(String category, ItemIdentifier item) {\n\t\tString name = langDatabase.get(category, \"name\", \"\").getString();\n\t\tif (name.equals(\"\")) {\n\t\t\tsaveLangDatabase();\n\t\t\tif (item.isDamageable()) {\n\t\t\t\treturn item.getFriendlyName();\n\t\t\t} else {\n\t\t\t\treturn \"LP|UNDEFINED\";\n\t\t\t}\n\t\t}\n\t\treturn name;\n\t}\n\n\tprivate void setNameForCategory(String category, ItemIdentifier item, String newName) {\n\t\tlangDatabase.get(category, \"name\", newName).set(newName);\n\t\tsaveLangDatabase();\n\t}\n\n\tprivate void saveLangDatabase() {\n\t\tsaveThreadTime = System.currentTimeMillis() + 30 * 1000;\n\t}\n\n\t@Override\n\tpublic String getName(ItemIdentifier item) {\n\t\tString category;\n\t\tif (item.isDamageable()) {\n\t\t\tcategory = String.format(\"itemNames.%d\", Item.getIdFromItem(item.item));\n\t\t} else {\n\t\t\tif (item.itemDamage == 0) {\n\t\t\t\tcategory = String.format(\"itemNames.%d\", Item.getIdFromItem(item.item));\n\t\t\t} else {\n\t\t\t\tcategory = String.format(\"itemNames.%d.%d\", Item.getIdFromItem(item.item), item.itemDamage);\n\t\t\t}\n\t\t}\n\t\tString name = getNameForCategory(category, item);\n\t\tif (name.equals(\"LP|UNDEFINED\")) {\n\t\t\tif (item.itemDamage == 0) {\n\t\t\t\treturn item.getFriendlyName();\n\t\t\t} else {\n\t\t\t\tcategory = String.format(\"itemNames.%d\", Item.getIdFromItem(item.item));\n\t\t\t\tname = getNameForCategory(category, item);\n\t\t\t\tif (name.equals(\"LP|UNDEFINED\")) {\n\t\t\t\t\treturn item.getFriendlyName();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic void updateNames(ItemIdentifier item, String name) {\n\t\tString category;\n\t\tif (item.isDamageable()) {\n\t\t\tcategory = String.format(\"itemNames.%d\", Item.getIdFromItem(item.item));\n\t\t} else {\n\t\t\tif (item.itemDamage == 0) {\n\t\t\t\tcategory = String.format(\"itemNames.%d\", Item.getIdFromItem(item.item));\n\t\t\t} else {\n\t\t\t\tcategory = String.format(\"itemNames.%d.%d\", Item.getIdFromItem(item.item), item.itemDamage);\n\t\t\t}\n\t\t}\n\t\tsetNameForCategory(category, item, name);\n\t}\n\n\t@Override\n\tpublic void tick() {\n\t\t//Save Language Database\n\t\tif (saveThreadTime != 0) {\n\t\t\tif (saveThreadTime < System.currentTimeMillis()) {\n\t\t\t\tsaveThreadTime = 0;\n\t\t\t\tlangDatabase.save();\n\t\t\t\tLogisticsPipes.log.info(\"LangDatabase saved\");\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void sendNameUpdateRequest(EntityPlayer player) {\n\t\tfor (String category : langDatabase.getCategoryNames()) {\n\t\t\tif (!category.startsWith(\"itemNames.\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tString name = langDatabase.get(category, \"name\", \"\").getString();\n\t\t\tif (name.equals(\"\")) {\n\t\t\t\tString itemPart = category.substring(10);\n\t\t\t\tString metaPart = \"0\";\n\t\t\t\tif (itemPart.contains(\".\")) {\n\t\t\t\t\tString[] itemPartSplit = itemPart.split(\"\\\\.\");\n\t\t\t\t\titemPart = itemPartSplit[0];\n\t\t\t\t\tmetaPart = itemPartSplit[1];\n\t\t\t\t}\n\t\t\t\tint id = Integer.valueOf(itemPart);\n\t\t\t\tint meta = Integer.valueOf(metaPart);\n\t\t\t\tSimpleServiceLocator.serverBufferHandler.addPacketToCompressor(PacketHandler.getPacket(UpdateName.class).setIdent(ItemIdentifier.get(Item.getItemById(id), meta, null)).setName(\"-\"), player);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic LogisticsTileGenericPipe getPipeInDimensionAt(int dimension, int x, int y, int z, EntityPlayer player) {\n\t\treturn ServerProxy.getPipe(DimensionManager.getWorld(dimension), x, y, z);\n\t}\n\n\t// BuildCraft method\n\n\t/**\n\t * Retrieves pipe at specified coordinates if any.\n\t *\n\t * @param world\n\t * @param x\n\t * @param y\n\t * @param z\n\t * @return\n\t */\n\tprotected static LogisticsTileGenericPipe getPipe(World world, int x, int y, int z) {\n\t\tif (world == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (world.isAirBlock(new BlockPos(x, y, z))) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfinal TileEntity tile = world.getTileEntity(new BlockPos(x, y, z));\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (LogisticsTileGenericPipe) tile;\n\t}\n\n\t// BuildCraft method end\n\t@Override\n\tpublic void addLogisticsPipesOverride(Object par1IIconRegister, int index, String override1, String override2, boolean flag) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"rawtypes\")\n\tpublic void sendBroadCast(String message) {\n\t\tMinecraftServer server = FMLServerHandler.instance().getServer();\n\t\tif (server != null && server.getPlayerList() != null) {\n\t\t\tList<EntityPlayerMP> list = server.getPlayerList().getPlayers();\n\t\t\tif (list != null && !list.isEmpty()) {\n\t\t\t\tlist.forEach(obj -> obj.sendMessage(new TextComponentString(\"[LP] Server: \" + message)));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void tickServer() {\n\t\tMainProxy.addTick();\n\t}\n\n\t@Override\n\tpublic void tickClient() {}\n\n\t@Override\n\tpublic EntityPlayer getEntityPlayerFromNetHandler(INetHandler handler) {\n\t\tif (handler instanceof NetHandlerPlayServer) {\n\t\t\treturn ((NetHandlerPlayServer) handler).player;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void setIconProviderFromPipe(ItemLogisticsPipe item, CoreUnroutedPipe dummyPipe) {}\n\n\t@Override\n\tpublic LogisticsModule getModuleFromGui() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean checkSinglePlayerOwner(String commandSenderName) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void openFluidSelectGui(int slotId) {}\n\n\t@Override\n\tpublic void registerTextures() {}\n\n\t@Override\n\tpublic void initModelLoader() {}\n\n\t@Override\n\tpublic int getRenderIndex() {\n\t\treturn 0;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialconnection/SpecialPipeConnection.java",
    "content": "package logisticspipes.proxy.specialconnection;\n\nimport java.util.ArrayList;\nimport java.util.EnumSet;\nimport java.util.List;\n\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\nimport logisticspipes.interfaces.routing.ISpecialPipedConnection;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\n\npublic class SpecialPipeConnection {\n\n\tprivate List<ISpecialPipedConnection> handler = new ArrayList<>();\n\n\tpublic void registerHandler(ISpecialPipedConnection connectionHandler) {\n\t\tif (connectionHandler.init()) {\n\t\t\thandler.add(connectionHandler);\n\t\t}\n\t}\n\n\tpublic List<ConnectionInformation> getConnectedPipes(IPipeInformationProvider startPipe, EnumSet<PipeRoutingConnectionType> connection, EnumFacing side) {\n\t\tfor (ISpecialPipedConnection connectionHandler : handler) {\n\t\t\tif (connectionHandler.isType(startPipe)) {\n\t\t\t\treturn connectionHandler.getConnections(startPipe, connection, side);\n\t\t\t}\n\t\t}\n\t\treturn new ArrayList<>();\n\t}\n\n\t@Data\n\t@AllArgsConstructor\n\tpublic static class ConnectionInformation {\n\n\t\tprivate IPipeInformationProvider connectedPipe;\n\t\tprivate EnumSet<PipeRoutingConnectionType> connectionFlags;\n\t\tprivate EnumFacing insertOrientation;\n\t\tprivate EnumFacing exitOrientation;\n\t\tprivate double distance;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialconnection/SpecialTileConnection.java",
    "content": "package logisticspipes.proxy.specialconnection;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport logisticspipes.interfaces.routing.ISpecialTileConnection;\nimport logisticspipes.logisticspipes.IRoutedItem;\n\npublic class SpecialTileConnection {\n\n\tprivate List<ISpecialTileConnection> handler = new ArrayList<>();\n\n\tpublic void registerHandler(ISpecialTileConnection connectionHandler) {\n\t\tif (connectionHandler.init()) {\n\t\t\thandler.add(connectionHandler);\n\t\t}\n\t}\n\n\tpublic Collection<TileEntity> getConnectedPipes(TileEntity tile) {\n\t\tfor (ISpecialTileConnection connectionHandler : handler) {\n\t\t\tif (connectionHandler.isType(tile)) {\n\t\t\t\treturn connectionHandler.getConnections(tile);\n\t\t\t}\n\t\t}\n\t\treturn new ArrayList<>();\n\t}\n\n\tpublic boolean needsInformationTransition(TileEntity tile) {\n\t\tfor (ISpecialTileConnection connectionHandler : handler) {\n\t\t\tif (connectionHandler.isType(tile)) {\n\t\t\t\treturn connectionHandler.needsInformationTransition();\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void transmit(TileEntity tile, IRoutedItem arrivingItem) {\n\t\tfor (ISpecialTileConnection connectionHandler : handler) {\n\t\t\tif (connectionHandler.isType(tile)) {\n\t\t\t\tconnectionHandler.transmit(tile, arrivingItem);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic boolean isType(TileEntity tile) {\n\t\tfor (ISpecialTileConnection connectionHandler : handler) {\n\t\t\tif (connectionHandler.isType(tile)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialconnection/TeleportPipes.java",
    "content": ""
  },
  {
    "path": "common/logisticspipes/proxy/specialinventoryhandler/AEInterfaceInventoryHandler.java",
    "content": "package logisticspipes.proxy.specialinventoryhandler;\n\nimport java.util.HashMap;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTBase;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.capabilities.CapabilityInject;\nimport net.minecraftforge.common.capabilities.ICapabilitySerializable;\n\nimport appeng.api.AEApi;\nimport appeng.api.config.Actionable;\nimport appeng.api.networking.IGridHost;\nimport appeng.api.networking.IGridNode;\nimport appeng.api.networking.security.IActionHost;\nimport appeng.api.networking.security.IActionSource;\nimport appeng.api.storage.IStorageMonitorable;\nimport appeng.api.storage.IStorageMonitorableAccessor;\nimport appeng.api.storage.channels.IItemStorageChannel;\nimport appeng.api.storage.data.IAEItemStack;\nimport appeng.api.storage.data.IItemList;\nimport appeng.api.util.AEPartLocation;\n\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\n\npublic class AEInterfaceInventoryHandler extends SpecialInventoryHandler implements SpecialInventoryHandler.Factory {\n\n\tpublic boolean init = false;\n\tprivate final LPActionSource source;\n\tprivate IStorageMonitorableAccessor acc;\n\tIGridHost host;\n\tpublic IGridNode node;\n\tprivate LinkedList<Entry<ItemIdentifier, Integer>> cached;\n\tprivate final boolean hideOne;\n\n\tprivate AEInterfaceInventoryHandler(TileEntity tile, EnumFacing dir, ProviderMode mode) {\n\t\thideOne = mode.getHideOnePerStack() || mode.getHideOnePerType();\n\t\tthis.acc = tile.getCapability(LPStorageMonitorableAccessor.STORAGE_MONITORABLE_ACCESSOR_CAPABILITY, dir);\n\t\tnode = ((IGridHost) tile).getGridNode(AEPartLocation.fromFacing(dir));\n\t\thost = node.getMachine();\n\t\tsource = new LPActionSource(this);\n\t}\n\n\tpublic AEInterfaceInventoryHandler() {\n\t\tsource = null;\n\t\thideOne = false;\n\t}\n\n\t@Override\n\tpublic boolean isType(@Nonnull TileEntity tile, @Nullable EnumFacing dir) {\n\t\tif (tile instanceof IGridHost && tile.hasCapability(LPStorageMonitorableAccessor.STORAGE_MONITORABLE_ACCESSOR_CAPABILITY, dir)) {\n\t\t\t// for some reason when AE loads (5 ticks) this is null\n\t\t\treturn ((IGridHost) tile).getGridNode(AEPartLocation.fromFacing(dir)) != null;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean init() {\n\t\tinit = true;\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SpecialInventoryHandler getUtilForTile(@Nonnull TileEntity tile, @Nullable EnumFacing direction, @Nonnull ProviderMode mode) {\n\t\treturn new AEInterfaceInventoryHandler(tile, direction, mode);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Map<ItemIdentifier, Integer> getItemsAndCount() {\n\t\treturn getItemsAndCount(false);\n\t}\n\n\tprivate Map<ItemIdentifier, Integer> getItemsAndCount(boolean linked) {\n\t\tMap<ItemIdentifier, Integer> result;\n\t\tif (linked) {\n\t\t\tresult = new LinkedHashMap<>();\n\t\t} else {\n\t\t\tresult = new HashMap<>();\n\t\t}\n\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null || tmp.getInventory(channel).getStorageList() == null) {\n\t\t\treturn result;\n\t\t}\n\n\t\tIItemList<IAEItemStack> items = tmp.getInventory(channel).getStorageList();\n\t\tfor (IAEItemStack item : items) {\n\t\t\tItemIdentifier ident = ItemIdentifier.get(item.createItemStack());\n\t\t\tInteger count = result.get(ident);\n\t\t\tif (count != null) {\n\t\t\t\tresult.put(ident, (int) (count + item.getStackSize() - (hideOne ? 1 : 0)));\n\t\t\t} else {\n\t\t\t\tresult.put(ident, (int) (item.getStackSize() - (hideOne ? 1 : 0)));\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getSingleItem(ItemIdentifier item) {\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tIAEItemStack stack = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(item.makeNormalStack(1));\n\t\tIAEItemStack extract = tmp.getInventory(channel).extractItems(stack, Actionable.MODULATE, source);\n\t\tif (extract == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn extract.createItemStack();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getMultipleItems(@Nonnull ItemIdentifier itemIdent, int count) {\n\t\tif (itemCount(itemIdent) < count) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tIAEItemStack stack = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(itemIdent.makeNormalStack(count));\n\t\tIAEItemStack extract = tmp.getInventory(channel).extractItems(stack, Actionable.MODULATE, source);\n\t\tif (extract == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn extract.createItemStack();\n\t}\n\n\t@Override\n\tpublic boolean containsUndamagedItem(@Nonnull ItemIdentifier itemIdent) {\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null || tmp.getInventory(channel).getStorageList() == null) {\n\t\t\treturn false;\n\t\t}\n\t\tIItemList<IAEItemStack> items = tmp.getInventory(channel).getStorageList();\n\t\tfor (IAEItemStack item : items) {\n\t\t\tItemIdentifier ident = ItemIdentifier.get(item.createItemStack());\n\t\t\tif (ident.equals(itemIdent)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int roomForItem(@Nonnull ItemStack itemStack) {\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null) {\n\t\t\treturn 0;\n\t\t}\n\t\tIAEItemStack stack = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(itemStack);\n\t\tif (stack == null) return 0;\n\t\twhile (stack.getStackSize() > 0) {\n\t\t\tif (tmp.getInventory(channel).canAccept(stack)) {\n\t\t\t\treturn stack.getStackSize() > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) stack.getStackSize();\n\t\t\t}\n\t\t\tstack.decStackSize(1);\n\t\t}\n\t\treturn 0;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Set<ItemIdentifier> getItems() {\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tSet<ItemIdentifier> result = new TreeSet<>();\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null || tmp.getInventory(channel).getStorageList() == null) {\n\t\t\treturn result;\n\t\t}\n\t\tIItemList<IAEItemStack> items = tmp.getInventory(channel).getStorageList();\n\t\tfor (IAEItemStack item : items) {\n\t\t\tItemIdentifier ident = ItemIdentifier.get(item.createItemStack());\n\t\t\tresult.add(ident);\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\tif (cached == null) {\n\t\t\tinitCache();\n\t\t}\n\n\t\t// allow LP putting items into AE\n\t\treturn cached.size() + 1;\n\t}\n\n\tprivate void initCache() {\n\t\tMap<ItemIdentifier, Integer> map = getItemsAndCount(true);\n\t\tcached = new LinkedList<>();\n\t\tcached.addAll(map.entrySet());\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getStackInSlot(int slot) {\n\t\tif (cached == null) {\n\t\t\tinitCache();\n\t\t}\n\t\tif (slot >= cached.size()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tEntry<ItemIdentifier, Integer> entry = cached.get(slot);\n\t\tif (entry.getValue() == 0) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn entry.getKey().makeNormalStack(entry.getValue());\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack decrStackSize(int slot, int amount) {\n\t\tif (cached == null) {\n\t\t\tinitCache();\n\t\t}\n\t\tif (slot >= cached.size()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tEntry<ItemIdentifier, Integer> entry = cached.get(slot);\n\t\treturn getMultipleItems(entry.getKey(), amount);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack add(@Nonnull ItemStack stack, EnumFacing from, boolean doAdd) {\n\t\tItemStack st = stack.copy();\n\t\tIItemStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);\n\t\tIAEItemStack tst = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(stack);\n\t\tIStorageMonitorable tmp = acc.getInventory(source);\n\t\tif (tmp == null || tmp.getInventory(channel) == null) {\n\t\t\treturn st;\n\t\t}\n\t\tIAEItemStack overflow = tmp.getInventory(channel).injectItems(tst, Actionable.MODULATE, source);\n\t\tif (overflow != null) {\n\t\t\tst.setCount((int) (st.getCount() - overflow.getStackSize()));\n\t\t}\n\t\treturn st;\n\t}\n}\n\nclass LPStorageMonitorableAccessor implements ICapabilitySerializable<NBTBase> {\n\n\t@CapabilityInject(IStorageMonitorableAccessor.class)\n\tpublic static Capability<IStorageMonitorableAccessor> STORAGE_MONITORABLE_ACCESSOR_CAPABILITY;\n\n\tprivate final IStorageMonitorableAccessor instance = STORAGE_MONITORABLE_ACCESSOR_CAPABILITY.getDefaultInstance();\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, EnumFacing facing) {\n\t\treturn capability == STORAGE_MONITORABLE_ACCESSOR_CAPABILITY;\n\t}\n\n\t@Override\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, EnumFacing facing) {\n\t\treturn capability == STORAGE_MONITORABLE_ACCESSOR_CAPABILITY ? STORAGE_MONITORABLE_ACCESSOR_CAPABILITY.cast(this.instance) : null;\n\t}\n\n\t@Override\n\tpublic NBTBase serializeNBT() {\n\t\treturn STORAGE_MONITORABLE_ACCESSOR_CAPABILITY.getStorage().writeNBT(STORAGE_MONITORABLE_ACCESSOR_CAPABILITY, this.instance, null);\n\t}\n\n\t@Override\n\tpublic void deserializeNBT(NBTBase nbt) {\n\t\tSTORAGE_MONITORABLE_ACCESSOR_CAPABILITY.getStorage().readNBT(STORAGE_MONITORABLE_ACCESSOR_CAPABILITY, this.instance, null, nbt);\n\t}\n}\n\nclass LPActionSource implements IActionSource {\n\n\tfinal IGridHost host;\n\n\tpublic LPActionSource(AEInterfaceInventoryHandler invh) {\n\t\thost = invh.host;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Optional<EntityPlayer> player() {\n\t\treturn Optional.empty();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Optional<IActionHost> machine() {\n\t\treturn Optional.ofNullable((IActionHost) this.host);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <T> Optional<T> context(@Nonnull Class<T> key) {\n\t\treturn Optional.empty();\n\t}\n}\n\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialinventoryhandler/BuildCraftTransactorHandler.java",
    "content": "package logisticspipes.proxy.specialinventoryhandler;\n\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport buildcraft.api.inventory.IItemTransactor;\nimport buildcraft.lib.misc.CapUtil;\n\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\n\npublic class BuildCraftTransactorHandler extends SpecialInventoryHandler implements SpecialInventoryHandler.Factory {\n\n\tprivate IItemTransactor cap = null;\n\n\tprivate BuildCraftTransactorHandler(IItemTransactor cap) {\n\t\tthis.cap = cap;\n\t}\n\n\tpublic BuildCraftTransactorHandler() {}\n\n\t@Override\n\tpublic boolean init() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isType(@Nonnull TileEntity tile, @Nullable EnumFacing dir) {\n\t\treturn tile.hasCapability(CapUtil.CAP_ITEM_TRANSACTOR, dir);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic SpecialInventoryHandler getUtilForTile(@Nonnull TileEntity tile, @Nullable EnumFacing direction, @Nonnull ProviderMode mode) {\n\t\tIItemTransactor cap = tile.getCapability(CapUtil.CAP_ITEM_TRANSACTOR, direction);\n\t\tif (cap != null) {\n\t\t\treturn new BuildCraftTransactorHandler(cap);\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Map<ItemIdentifier, Integer> getItemsAndCount() {\n\t\treturn Collections.emptyMap();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getSingleItem(ItemIdentifier item) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\tpublic boolean containsUndamagedItem(@Nonnull ItemIdentifier item) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int roomForItem(@Nonnull ItemStack stack) {\n\t\treturn stack.getCount() - cap.insert(stack, false, true).getCount();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Set<ItemIdentifier> getItems() {\n\t\treturn Collections.emptySet();\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn 1;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getStackInSlot(int slot) {\n\t\tif (slot != 0) return ItemStack.EMPTY;\n\t\treturn cap.extract(it -> true, 0, 64, true);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack decrStackSize(int slot, int amount) {\n\t\tif (slot != 0) return ItemStack.EMPTY;\n\t\treturn cap.extract(it -> true, amount, amount, false);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack add(@Nonnull ItemStack stack, EnumFacing orientation, boolean doAdd) {\n\t\tItemStack overflow = cap.insert(stack.copy(), false, !doAdd);\n\t\tstack.setCount(stack.getCount() - overflow.getCount());\n\t\treturn stack;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialinventoryhandler/SpecialInventoryHandler.java",
    "content": "package logisticspipes.proxy.specialinventoryhandler;\n\nimport java.util.Map;\nimport java.util.stream.IntStream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.transactor.ITransactor;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\n\npublic abstract class SpecialInventoryHandler implements IInventoryUtil, ITransactor {\n\n\t@Override\n\tpublic int itemCount(@Nonnull ItemIdentifier itemIdent) {\n\t\tfinal Map<ItemIdentifier, Integer> map = getItemsAndCount();\n\t\treturn map.getOrDefault(itemIdent, 0);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getMultipleItems(@Nonnull ItemIdentifier itemIdent, int count) {\n\t\tif (itemCount(itemIdent) < count) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn IntStream.range(0, count).mapToObj((i) -> getSingleItem(itemIdent)).filter(itemStack -> !itemStack.isEmpty()).reduce((left, right) -> {\n\t\t\tleft.grow(right.getCount());\n\t\t\treturn left;\n\t\t}).orElse(ItemStack.EMPTY);\n\t}\n\n\tpublic interface Factory {\n\n\t\tboolean init();\n\n\t\tboolean isType(@Nonnull TileEntity tile, @Nullable EnumFacing dir);\n\n\t\t@Nullable\n\t\tSpecialInventoryHandler getUtilForTile(@Nonnull TileEntity tile, @Nullable EnumFacing direction, @Nonnull ProviderMode mode);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialtankhandler/AETankHandler.java",
    "content": "/*\npackage logisticspipes.proxy.specialtankhandler;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport logisticspipes.interfaces.ISpecialTankAccessHandler;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.FluidIdentifier;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.world.World;\n\nimport net.minecraft.util.EnumFacing;\nimport net.minecraftforge.fluids.FluidStack;\n\nimport appeng.api.AEApi;\nimport appeng.api.config.Actionable;\nimport appeng.api.networking.IGrid;\nimport appeng.api.networking.IGridBlock;\nimport appeng.api.networking.IGridHost;\nimport appeng.api.networking.IGridNode;\nimport appeng.api.networking.security.IActionHost;\nimport appeng.api.storage.IMEMonitor;\nimport appeng.api.storage.IStorageMonitorable;\nimport appeng.api.storage.data.IAEFluidStack;\nimport appeng.api.util.AECableType;\nimport appeng.api.util.DimensionalCoord;\n\npublic class AETankHandler implements ISpecialTankAccessHandler {\n\n\t@Override\n\tpublic boolean init() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isType(TileEntity tile) {\n\t\treturn tile instanceof ITileStorageMonitorable && tile instanceof IGridHost;\n\t}\n\n\t@Override\n\tpublic List<TileEntity> getBaseTilesFor(TileEntity tile) {\n\t\tList<TileEntity> tiles = new ArrayList<>(1);\n\t\tif (tile instanceof IGridHost) {\n\t\t\tIGridHost host = (IGridHost) tile;\n\t\t\tIGridNode node = host.getGridNode(null);\n\t\t\tif (node != null) {\n\t\t\t\tTileEntity base = getBaseTileEntity(node);\n\t\t\t\tif (base != null) {\n\t\t\t\t\ttiles.add(base);\n\t\t\t\t\treturn tiles;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\ttiles.add(tile);\n\t\treturn tiles;\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\t@Override\n\tpublic Map<FluidIdentifier, Long> getAvailableLiquid(TileEntity tile) {\n\t\tMap<FluidIdentifier, Long> map = new HashMap<>();\n\t\tif (tile instanceof ITileStorageMonitorable) {\n\t\t\tITileStorageMonitorable mon = (ITileStorageMonitorable) tile;\n\t\t\tif (mon == null) {\n\t\t\t\treturn map;\n\t\t\t}\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tMachineSource source = new MachineSource(new LPActionHost(((IGridHost) tile).getGridNode(dir)));\n\t\t\t\tIStorageMonitorable monitor = mon.getMonitorable(dir, source);\n\t\t\t\tif (monitor == null || monitor.getFluidInventory() == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tIMEMonitor<IAEFluidStack> fluids = monitor.getFluidInventory();\n\t\t\t\tfor (IAEFluidStack stack : fluids.getStorageList()) {\n\t\t\t\t\tif (SimpleServiceLocator.extraCellsProxy.canSeeFluidInNetwork(stack.getFluid())) {\n\t\t\t\t\t\tmap.put(FluidIdentifier.get(stack.getFluid(), stack.getTagCompound() != null ? stack.getTagCompound().getNBTTagCompoundCopy() : null, null), stack.getStackSize());\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn map;\n\t\t\t}\n\t\t}\n\t\treturn map;\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\t@Override\n\tpublic FluidStack drainFrom(TileEntity tile, FluidIdentifier ident, Integer amount, boolean drain) {\n\t\tif (tile instanceof ITileStorageMonitorable) {\n\t\t\tITileStorageMonitorable mon = (ITileStorageMonitorable) tile;\n\t\t\tif (mon == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tMachineSource source = new MachineSource(new LPActionHost(((IGridHost) tile).getGridNode(dir)));\n\t\t\t\tIStorageMonitorable monitor = mon.getMonitorable(dir, source);\n\t\t\t\tif (monitor == null || monitor.getFluidInventory() == null) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tIMEMonitor<IAEFluidStack> fluids = monitor.getFluidInventory();\n\t\t\t\tIAEFluidStack s = AEApi.instance().storage().createFluidStack(ident.makeFluidStack(amount));\n\t\t\t\tIAEFluidStack extracted = fluids.extractItems(s, drain ? Actionable.MODULATE : Actionable.SIMULATE, source);\n\t\t\t\tif (extracted == null) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\treturn extracted.getFluidStack();\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tprivate TileEntity getBaseTileEntity(IGridNode node) {\n\t\tIGrid grid = node.getGrid();\n\t\tif (grid == null) {\n\t\t\treturn null;\n\t\t}\n\t\tIGridNode pivot = grid.getPivot();\n\t\tif (pivot == null) {\n\t\t\treturn null;\n\t\t}\n\t\tIGridBlock block = pivot.getGridBlock();\n\t\tif (block == null) {\n\t\t\treturn null;\n\t\t}\n\t\tDimensionalCoord coord = block.getLocation();\n\t\tif (coord == null) {\n\t\t\treturn null;\n\t\t}\n\t\tWorld world = coord.getWorld();\n\t\tif (world == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn world.getTileEntity(coord.x, coord.y, coord.z);\n\t}\n\n\tprivate class LPActionHost implements IActionHost {\n\n\t\tpublic IGridNode node;\n\n\t\tpublic LPActionHost(IGridNode node) {\n\t\t\tthis.node = node;\n\t\t}\n\n\t\t@Override\n\t\tpublic void securityBreak() {}\n\n\t\t@Override\n\t\tpublic IGridNode getGridNode(EnumFacing paramEnumFacing) {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic AECableType getCableConnectionType(EnumFacing paramEnumFacing) {\n\t\t\treturn null;\n\t\t}\n\n\t\t@Override\n\t\tpublic IGridNode getActionableNode() {\n\t\t\treturn node;\n\t\t}\n\t}\n}\n*/\n"
  },
  {
    "path": "common/logisticspipes/proxy/specialtankhandler/BuildCraftTankHandler.java",
    "content": "/*\npackage logisticspipes.proxy.specialtankhandler;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport logisticspipes.interfaces.ISpecialTankAccessHandler;\nimport logisticspipes.utils.FluidIdentifier;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraft.util.EnumFacing;\nimport net.minecraftforge.fluids.FluidStack;\nimport net.minecraftforge.fluids.FluidTankInfo;\nimport net.minecraftforge.fluids.IFluidHandler;\n\nimport buildcraft.factory.TileTank;\n\npublic class BuildCraftTankHandler implements ISpecialTankAccessHandler {\n\n\t@Override\n\tpublic boolean init() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isType(TileEntity tile) {\n\t\treturn tile instanceof TileTank;\n\t}\n\n\t@Override\n\tpublic List<TileEntity> getBaseTilesFor(TileEntity tile) {\n\t\tList<TileEntity> tiles = new ArrayList<>(1);\n\t\ttiles.add(((TileTank) tile).getBottomTank());\n\t\treturn tiles;\n\t}\n\n\t@Override\n\tpublic Map<FluidIdentifier, Long> getAvailableLiquid(TileEntity tile) {\n\t\tMap<FluidIdentifier, Long> map = new HashMap<>();\n\t\tFluidTankInfo[] tanks = ((IFluidHandler) tile).getTankInfo(null);\n\t\tfor (FluidTankInfo tank : tanks) {\n\t\t\tif (tank == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tFluidStack liquid;\n\t\t\tif ((liquid = tank.fluid) != null && liquid.getFluidID() != 0) {\n\t\t\t\tFluidIdentifier ident = FluidIdentifier.get(liquid);\n\t\t\t\tif (((IFluidHandler) tile).drain(null, 1, false) != null) {\n\t\t\t\t\tif (map.containsKey(ident)) {\n\t\t\t\t\t\tlong addition = map.get(ident) + tank.fluid.amount;\n\t\t\t\t\t\tmap.put(ident, addition);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmap.put(ident, (long) tank.fluid.amount);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn map;\n\t}\n\n\t@Override\n\tpublic FluidStack drainFrom(TileEntity tile, FluidIdentifier ident, Integer amount, boolean drain) {\n\t\t//workaround for BC5 and BC6 TileTank behavior before commit 08edcf1759c884cb95b66c53427bbd4b3f3d9751\n\t\ttile = ((TileTank) tile).getBottomTank();\n\t\treturn ((IFluidHandler) tile).drain(null, ident.makeFluidStack(amount), drain);\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/proxy/specialtankhandler/SpecialTankHandler.java",
    "content": "package logisticspipes.proxy.specialtankhandler;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport com.google.common.collect.Lists;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ISpecialTankHandler;\n\npublic class SpecialTankHandler {\n\n\tprivate List<ISpecialTankHandler> handlers = new ArrayList<>();\n\n\tpublic void registerHandler(ISpecialTankHandler handler) {\n\t\ttry {\n\t\t\tif (handler.init()) {\n\t\t\t\thandlers.add(handler);\n\t\t\t\tLogisticsPipes.log.info(\"Loaded SpecialTankHandler: \" + handler.getClass().getName());\n\t\t\t} else {\n\t\t\t\tLogisticsPipes.log.warn(\"Didn't load SpecialTankHandler: \" + handler.getClass().getName());\n\t\t\t}\n\t\t} catch (Exception e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic List<TileEntity> getBaseTileFor(TileEntity tile) {\n\t\tfor (ISpecialTankHandler handler : handlers) {\n\t\t\tif (handler.isType(tile)) {\n\t\t\t\treturn handler.getBaseTilesFor(tile);\n\t\t\t}\n\t\t}\n\t\treturn Lists.newArrayList(tile);\n\t}\n\n\tpublic boolean hasHandlerFor(TileEntity tile) {\n\t\tif (tile == null) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (ISpecialTankHandler handler : handlers) {\n\t\t\tif (handler.isType(tile)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic ISpecialTankHandler getTankHandlerFor(TileEntity tile) {\n\t\tfor (ISpecialTankHandler handler : handlers) {\n\t\t\tif (handler.isType(tile)) {\n\t\t\t\treturn handler;\n\t\t\t}\n\t\t}\n\t\tString name = \"null\";\n\t\tif (tile != null) {\n\t\t\tname = tile.getClass().getName();\n\t\t}\n\t\tthrow new RuntimeException(\"Unknwon TankTileEntity Request, '\" + name + \"'\");\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/td/LPDuctUnitItem.java",
    "content": "package logisticspipes.proxy.td;\n\nimport java.util.Collections;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport cofh.thermaldynamics.duct.ConnectionType;\nimport cofh.thermaldynamics.duct.Duct;\nimport cofh.thermaldynamics.duct.item.DuctUnitItem;\nimport cofh.thermaldynamics.duct.item.TravelingItem;\nimport cofh.thermaldynamics.duct.tiles.TileGrid;\nimport static logisticspipes.pipes.basic.LogisticsBlockGenericPipe.PIPE_CONN_BB;\n\nimport logisticspipes.asm.td.ILPTravelingItemInfo;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.td.subproxies.TDPart;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.logistics.LogisticsManager;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LPDuctUnitItem extends DuctUnitItem {\n\n\tpublic final LogisticsTileGenericPipe pipe;\n\n\tpublic LPDuctUnitItem(TileGrid parent, Duct duct, LogisticsTileGenericPipe pipe) {\n\t\tsuper(parent, duct);\n\t\tthis.pipe = pipe;\n\t}\n\n\tpublic boolean isLPBlockedSide(int paramInt, boolean ignoreSystemDisconnect) {\n\t\tEnumFacing dir = EnumFacing.byIndex(paramInt);\n\n\t\tAxisAlignedBB aabb = PIPE_CONN_BB.get(paramInt);\n\t\tif (SimpleServiceLocator.mcmpProxy.checkIntersectionWith(pipe, aabb)) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (pipe.getTileCache() == null) {\n\t\t\tDoubleCoordinates coords = new DoubleCoordinates(pipe.getTile().getPos());\n\t\t\tif (CoordinateUtils.add(coords, dir, 1).getTileEntity(pipe.getWorld()) instanceof LogisticsTileGenericPipe) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if (pipe.getTileCache()[dir.ordinal()].getTile() instanceof LogisticsTileGenericPipe) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (pipe.pipe != null && pipe.pipe.isSideBlocked(dir, ignoreSystemDisconnect)) {\n\t\t\treturn false;\n\t\t}\n\t\tTDPart.callSuperSideBlock = true;\n\t\tboolean re = parent.isSideBlocked(paramInt);\n\t\tTDPart.callSuperSideBlock = false;\n\t\treturn re;\n\t}\n\n\t@Override\n\tpublic boolean isOutput() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isOutput(int side) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic ConnectionType getConnectionType(byte side) {\n\t\tif (this.tileCache[side] == null) {\n\t\t\tthis.tileCache[side] = new Cache(pipe, null);\n\t\t}\n\t\treturn cofh.thermaldynamics.duct.ConnectionType.NORMAL;\n\t}\n\n\t@Override\n\tpublic boolean isNode() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int canRouteItem(@Nonnull ItemStack stack, byte directionOrdinal) {\n\t\tif (!stack.isEmpty()) {\n\t\t\tif (pipe.pipe.isRoutedPipe() && !((CoreRoutedPipe) pipe.pipe).stillNeedReplace()) {\n\t\t\t\tfinal ServerRouter serverRouter = (ServerRouter) ((CoreRoutedPipe) pipe.pipe).getRouter();\n\t\t\t\tif (LogisticsManager.INSTANCE.getDestination(stack, ItemIdentifier.get(stack), true, serverRouter, Collections.emptyList()) != null) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic void transferItem(TravelingItem item) {\n\t\tItemRoutingInformation info = (ItemRoutingInformation) ((ILPTravelingItemInfo) item).getLPRoutingInfoAddition();\n\t\tif (info != null) {\n\t\t\tinfo.setItem(ItemIdentifierStack.getFromStack(item.stack));\n\t\t\tLPTravelingItem.LPTravelingItemServer lpItem = new LPTravelingItem.LPTravelingItemServer(info);\n\t\t\tlpItem.setSpeed(info._transportMode == IRoutedItem.TransportMode.Active ? 0.3F : 0.2F);\n\t\t\tpipe.pipe.transport.injectItem(lpItem, EnumFacing.byIndex(item.direction).getOpposite());\n\t\t} else if (item.stack != null) {\n\t\t\tint consumed = pipe.injectItem(item.stack, true, EnumFacing.byIndex(item.direction).getOpposite());\n\t\t\titem.stack.shrink(consumed);\n\t\t\tif (item.stack.getCount() > 0) {\n\t\t\t\tpipe.pipe.transport._itemBuffer.add(new Triplet<>(ItemIdentifierStack\n\t\t\t\t\t\t.getFromStack(item.stack), new Pair<>(20 * 2, 0), null));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/td/TDDuctInformationProvider.java",
    "content": "package logisticspipes.proxy.td;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport cofh.core.util.helpers.BlockHelper;\nimport cofh.thermaldynamics.duct.item.DuctUnitItem;\nimport cofh.thermaldynamics.duct.item.GridItem;\nimport cofh.thermaldynamics.duct.item.TravelingItem;\nimport cofh.thermaldynamics.duct.tiles.DuctToken;\nimport cofh.thermaldynamics.duct.tiles.IDuctHolder;\nimport cofh.thermaldynamics.duct.tiles.TileDuctItem;\nimport cofh.thermaldynamics.multiblock.Route;\nimport cofh.thermaldynamics.multiblock.RouteCache;\n\nimport logisticspipes.asm.td.ILPTravelingItemInfo;\nimport logisticspipes.asm.te.ILPTEInformation;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.routing.pathfinder.IRouteProvider;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.utils.CacheHolder.CacheTypes;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.connection.ConnectionType;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class TDDuctInformationProvider implements IPipeInformationProvider, IRouteProvider {\n\n\tprivate final TileDuctItem duct;\n\n\tpublic TDDuctInformationProvider(TileDuctItem duct) {\n\t\tthis.duct = duct;\n\t}\n\n\t@Override\n\tpublic boolean isCorrect(ConnectionType type) {\n\t\treturn duct != null && !duct.isInvalid() && SimpleServiceLocator.thermalDynamicsProxy.isActive();\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn duct.getPos().getX();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn duct.getPos().getY();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn duct.getPos().getZ();\n\t}\n\n\t@Override\n\tpublic World getWorld() {\n\t\treturn duct.getWorld();\n\t}\n\n\t@Override\n\tpublic boolean isRouterInitialized() {\n\t\treturn !duct.isInvalid();\n\t}\n\n\t@Override\n\tpublic boolean isRoutingPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getRoutingPipe() {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic TileEntity getNextConnectedTile(EnumFacing direction) {\n\t\treturn BlockHelper.getAdjacentTileEntity(duct, direction);\n\t}\n\n\t@Override\n\tpublic boolean isFirewallPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IFilter getFirewallFilter() {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic TileEntity getTile() {\n\t\treturn duct;\n\t}\n\n\t@Override\n\tpublic boolean divideNetwork() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean powerOnly() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isOnewayPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isOutputClosed(EnumFacing direction) {\n\t\tfinal DuctUnitItem duct = this.duct.getDuct(DuctToken.ITEMS);\n\t\tif (duct == null) return true;\n\t\treturn !duct.isSideConnected((byte) direction.ordinal());\n\t}\n\n\t@Override\n\tpublic boolean canConnect(TileEntity to, EnumFacing direction, boolean ignoreSystemDisconnect) {\n\t\tTileEntity connection = CoordinateUtils.add(new DoubleCoordinates(duct.getPos()), direction).getTileEntity(duct.getWorld());\n\t\tif (duct.isSideBlocked((byte) direction.ordinal())) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!(connection instanceof IDuctHolder)) {\n\t\t\treturn false;\n\t\t}\n\t\tDuctUnitItem connectedDuct = ((IDuctHolder) connection).getDuct(DuctToken.ITEMS);\n\t\tif (connectedDuct == null) {\n\t\t\treturn false;\n\t\t} else if (connectedDuct instanceof LPDuctUnitItem) {\n\t\t\treturn !((LPDuctUnitItem) connectedDuct).isLPBlockedSide(direction.getOpposite().ordinal(), ignoreSystemDisconnect);\n\t\t} else {\n\t\t\treturn !connectedDuct.parent.isSideBlocked(direction.getOpposite().ordinal());\n\t\t}\n\t}\n\n\t@Nonnull\n\tprivate DuctUnitItem getDuct() {\n\t\treturn Objects.requireNonNull(this.duct.getDuct(DuctToken.ITEMS), \"duct must be non-null\");\n\t}\n\n\t@Override\n\tpublic double getDistance() {\n\t\treturn Math.max(getDuct().getDuctLength(), 0);\n\t}\n\n\t@Override\n\tpublic double getDistanceWeight() {\n\t\treturn Math.max(getDuct().getWeight(), 0);\n\t}\n\n\t@Override\n\tpublic boolean isItemPipe() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isFluidPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isPowerPipe() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic double getDistanceTo(int destinationint, EnumFacing ignore, ItemIdentifier ident, boolean isActive, double traveled, double max,\n\t\t\tList<DoubleCoordinates> visited) {\n\t\tif (traveled >= max) {\n\t\t\treturn Integer.MAX_VALUE;\n\t\t}\n\t\tIRouter destination = SimpleServiceLocator.routerManager.getRouter(destinationint);\n\t\tif (destination == null) {\n\t\t\treturn Integer.MAX_VALUE;\n\t\t}\n\t\tLinkedList<Route<DuctUnitItem, GridItem>> paramIterable = getDuct().getCache(true).outputRoutes;\n\t\tdouble closesedConnection = Integer.MAX_VALUE;\n\t\tfor (Route<DuctUnitItem, GridItem> localRoute1 : paramIterable) {\n\t\t\tif (localRoute1.endPoint instanceof LPDuctUnitItem) {\n\t\t\t\tLPDuctUnitItem lpDuct = (LPDuctUnitItem) localRoute1.endPoint;\n\n\t\t\t\tif (traveled + localRoute1.pathWeight > max) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tDoubleCoordinates pos = new DoubleCoordinates((TileEntity) lpDuct.pipe);\n\t\t\t\tif (visited.contains(pos)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tvisited.add(pos);\n\n\t\t\t\tdouble distance = lpDuct.pipe\n\t\t\t\t\t\t.getDistanceTo(destinationint, EnumFacing.byIndex(localRoute1.pathDirections.get(localRoute1.pathDirections.size() - 1)).getOpposite(),\n\t\t\t\t\t\t\t\tident, isActive, traveled + localRoute1.pathWeight, Math.min(max, closesedConnection), visited);\n\n\t\t\t\tvisited.remove(pos);\n\n\t\t\t\tif (distance != Integer.MAX_VALUE && distance + localRoute1.pathWeight < closesedConnection) {\n\t\t\t\t\tclosesedConnection = distance + localRoute1.pathWeight;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn closesedConnection;\n\t}\n\n\t@Override\n\tpublic boolean acceptItem(LPTravelingItem item, TileEntity from) {\n\t\tif (item instanceof LPTravelingItemServer) {\n\t\t\tLPTravelingItemServer serverItem = (LPTravelingItemServer) item;\n\t\t\tint id = serverItem.getInfo().destinationint;\n\t\t\tif (id == -1) {\n\t\t\t\tid = SimpleServiceLocator.routerManager.getIDforUUID(serverItem.getInfo().destinationUUID);\n\t\t\t}\n\t\t\tIRouter destination = SimpleServiceLocator.routerManager.getRouter(id);\n\t\t\tif (destination == null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tRouteCache<DuctUnitItem, GridItem> routes = getDuct().getCache(true);\n\t\t\tIterable<Route<DuctUnitItem, GridItem>> paramIterable = routes.outputRoutes;\n\t\t\tRoute<DuctUnitItem, GridItem> route = null;\n\t\t\tObject cache = null;\n\t\t\tTriplet<Integer, ItemIdentifier, Boolean> key = new Triplet<>(id, item.getItemIdentifierStack()\n\t\t\t\t\t.getItem(), serverItem.getInfo()._transportMode == TransportMode.Active);\n\t\t\tif (duct instanceof ILPTEInformation && ((ILPTEInformation) duct).getLPTileEntityObject() != null) {\n\t\t\t\tcache = ((ILPTEInformation) duct).getLPTileEntityObject().getCacheHolder().getCacheFor(CacheTypes.Routing, key);\n\t\t\t}\n\t\t\tif (cache instanceof Route) {\n\t\t\t\t//noinspection unchecked\n\t\t\t\troute = (Route<DuctUnitItem, GridItem>) cache;\n\t\t\t\tif (!routes.outputRoutes.contains(route)) {\n\t\t\t\t\troute = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (route == null) {\n\t\t\t\tPair<Double, Route<DuctUnitItem, GridItem>> closesedConnection = null;\n\t\t\t\tList<DoubleCoordinates> visited = new ArrayList<>();\n\t\t\t\tvisited.add(new DoubleCoordinates(from));\n\t\t\t\tfor (Route<DuctUnitItem, GridItem> localRoute1 : paramIterable) {\n\t\t\t\t\tif (localRoute1.endPoint instanceof LPDuctUnitItem) {\n\t\t\t\t\t\tLPDuctUnitItem lpDuct = (LPDuctUnitItem) localRoute1.endPoint;\n\n\t\t\t\t\t\tdouble max = Integer.MAX_VALUE;\n\t\t\t\t\t\tif (closesedConnection != null) {\n\t\t\t\t\t\t\tmax = closesedConnection.getValue1();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tDoubleCoordinates pos = new DoubleCoordinates((TileEntity) lpDuct.pipe);\n\t\t\t\t\t\tif (visited.contains(pos)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvisited.add(pos);\n\n\t\t\t\t\t\tdouble distance = lpDuct.pipe\n\t\t\t\t\t\t\t\t.getDistanceTo(id, EnumFacing.byIndex(localRoute1.pathDirections.get(localRoute1.pathDirections.size() - 1)).getOpposite(),\n\t\t\t\t\t\t\t\t\t\titem.getItemIdentifierStack().getItem(), serverItem.getInfo()._transportMode == TransportMode.Active,\n\t\t\t\t\t\t\t\t\t\tlocalRoute1.pathWeight, max,\n\t\t\t\t\t\t\t\t\t\tvisited);\n\n\t\t\t\t\t\tvisited.remove(pos);\n\n\t\t\t\t\t\tif (distance != Integer.MAX_VALUE && (closesedConnection == null || distance + localRoute1.pathDirections.size() < closesedConnection\n\t\t\t\t\t\t\t\t.getValue1())) {\n\t\t\t\t\t\t\tclosesedConnection = new Pair<>(distance + localRoute1.pathWeight, localRoute1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (closesedConnection != null) {\n\t\t\t\t\troute = closesedConnection.getValue2();\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (route != null) {\n\t\t\t\tif (duct instanceof ILPTEInformation && ((ILPTEInformation) duct).getLPTileEntityObject() != null) {\n\t\t\t\t\t((ILPTEInformation) duct).getLPTileEntityObject().getCacheHolder().setCache(CacheTypes.Routing, key, route);\n\t\t\t\t}\n\t\t\t\tTravelingItem travelItem = new TravelingItem(item.getItemIdentifierStack().makeNormalStack(), getDuct(), route.copy(), (byte) serverItem.output.ordinal(), (byte) 1 /* Speed */);\n\t\t\t\t//noinspection ConstantConditions\n\t\t\t\t((ILPTravelingItemInfo) travelItem).setLPRoutingInfoAddition(serverItem.getInfo());\n\t\t\t\tgetDuct().insertNewItem(travelItem);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void refreshTileCacheOnSide(EnumFacing side) {\n\t\tif (duct.getDuct(DuctToken.ITEMS) == null || getDuct().getGrid() == null) return;\n\t\tgetDuct().getGrid().destroyAndRecreate();\n\t}\n\n\t@Override\n\tpublic boolean isMultiBlock() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic Stream<TileEntity> getPartsOfPipe() {\n\t\treturn Stream.empty();\n\t}\n\n\t@Override\n\tpublic List<RouteInfo> getConnectedPipes(EnumFacing from) {\n\t\tList<RouteInfo> list = new ArrayList<>();\n\t\tif (duct.getDuct(DuctToken.ITEMS) == null || getDuct().getGrid() == null) return null;\n\t\tLinkedList<Route<DuctUnitItem, GridItem>> paramIterable = getDuct().getCache(true).outputRoutes;\n\t\tfor (Route<DuctUnitItem, GridItem> localRoute1 : paramIterable) {\n\t\t\tif (localRoute1.endPoint instanceof LPDuctUnitItem) {\n\t\t\t\tLPDuctUnitItem lpDuct = (LPDuctUnitItem) localRoute1.endPoint;\n\t\t\t\tlist.add(new RouteInfo(lpDuct.pipe, localRoute1.pathWeight,\n\t\t\t\t\t\tEnumFacing.byIndex(localRoute1.pathDirections.get(localRoute1.pathDirections.size() - 1))));\n\t\t\t}\n\t\t}\n\t\treturn list;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/td/ThermalDynamicsProxy.java",
    "content": "package logisticspipes.proxy.td;\n\nimport java.util.List;\n\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport cofh.thermaldynamics.duct.tiles.TileDuctItem;\nimport cofh.thermaldynamics.render.RenderDuct;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.interfaces.ITDProxy;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.proxy.td.subproxies.ITDPart;\nimport logisticspipes.proxy.td.subproxies.TDPart;\nimport logisticspipes.renderer.newpipe.RenderEntry;\n\npublic class ThermalDynamicsProxy implements ITDProxy {\n\n\tprivate TextureTransformation connectionTextureBasic;\n\tprivate TextureTransformation connectionTextureActive;\n\tprivate TextureTransformation connectionTextureInactive;\n\n\t@Override\n\tpublic void registerPipeInformationProvider() {\n\t\tSimpleServiceLocator.pipeInformationManager.registerProvider(TileDuctItem.class, TDDuctInformationProvider.class);\n\t}\n\n\t@Override\n\tpublic ITDPart getTDPart(LogisticsTileGenericPipe pipe) {\n\t\treturn new TDPart(pipe);\n\t}\n\n\t@Override\n\tpublic boolean isActive() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isItemDuct(TileEntity tile) {\n\t\treturn tile instanceof TileDuctItem;\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void renderPipeConnections(LogisticsTileGenericPipe pipeTile, List<RenderEntry> renderList) {\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (pipeTile.renderState.pipeConnectionMatrix.isTDConnected(dir)) {\n\t\t\t\tTextureTransformation texture = connectionTextureBasic;\n\t\t\t\tif (pipeTile.renderState.textureMatrix.isRouted()) {\n\t\t\t\t\tif (pipeTile.renderState.textureMatrix.isRoutedInDir(dir)) {\n\t\t\t\t\t\ttexture = connectionTextureActive;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttexture = connectionTextureInactive;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdouble move = 0.25;\n\t\t\t\tLPTranslation localTranslation = new LPTranslation(0.5D + dir.getDirectionVec().getX() * move, 0.5D + dir.getDirectionVec().getY() * move, 0.5D + dir.getDirectionVec().getZ() * move);\n\t\t\t\trenderList.add(new RenderEntry(SimpleServiceLocator.cclProxy.wrapModel(RenderDuct.modelConnection[2][dir.ordinal()]), localTranslation, texture));\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void registerTextures(TextureMap iconRegister) {\n\t\tif (connectionTextureBasic == null) {\n\t\t\tconnectionTextureBasic = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/thermaldynamicsconnection-basic\")));\n\t\t\tconnectionTextureActive = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/thermaldynamicsconnection-active\")));\n\t\t\tconnectionTextureInactive = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/thermaldynamicsconnection-inactive\")));\n\t\t} else {\n\t\t\tconnectionTextureBasic.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/thermaldynamicsconnection-basic\")));\n\t\t\tconnectionTextureActive.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/thermaldynamicsconnection-active\")));\n\t\t\tconnectionTextureInactive.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/thermaldynamicsconnection-inactive\")));\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isBlockedSide(TileEntity with, EnumFacing opposite) {\n\t\tif (!(with instanceof TileDuctItem)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn ((TileDuctItem) with).isSideBlocked(opposite.ordinal());\n\t}\n}"
  },
  {
    "path": "common/logisticspipes/proxy/td/subproxies/ITDPart.java",
    "content": "package logisticspipes.proxy.td.subproxies;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\npublic interface ITDPart {\n\n\tTileEntity getInternalDuct();\n\n\tvoid setWorld_LP(World world);\n\n\tvoid invalidate();\n\n\tvoid onChunkUnload();\n\n\tvoid scheduleNeighborChange();\n\n\tvoid connectionsChanged();\n\n\tboolean isLPSideBlocked(int i);\n\n\tvoid setPos(BlockPos pos);\n}"
  },
  {
    "path": "common/logisticspipes/proxy/td/subproxies/TDPart.java",
    "content": "package logisticspipes.proxy.td.subproxies;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport cofh.thermaldynamics.duct.TDDucts;\nimport cofh.thermaldynamics.duct.tiles.DuctToken;\nimport cofh.thermaldynamics.duct.tiles.TileDuctItem;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.td.LPDuctUnitItem;\n\npublic class TDPart implements ITDPart {\n\n\tpublic static boolean callSuperSideBlock = false;\n\n\tprivate final LogisticsTileGenericPipe pipe;\n\tprivate final TileDuctItem thermalDynamicsDucts;\n\tprivate final LPDuctUnitItem lpDuctUnit;\n\n\tpublic TDPart(LogisticsTileGenericPipe pipe) {\n\t\tthis.pipe = pipe;\n\t\tthermalDynamicsDucts = new TileDuctItem.Basic.Transparent() {\n\n\t\t\t@Override\n\t\t\tpublic boolean isSideBlocked(int side) {\n\t\t\t\tif (callSuperSideBlock) {\n\t\t\t\t\treturn super.isSideBlocked(side);\n\t\t\t\t}\n\t\t\t\treturn lpDuctUnit.isLPBlockedSide(side, false);\n\t\t\t}\n\t\t};\n\t\tlpDuctUnit = new LPDuctUnitItem(thermalDynamicsDucts, TDDucts.itemBasic, pipe);\n\t\tthermalDynamicsDucts.addDuctUnits(DuctToken.ITEMS, lpDuctUnit);\n\t}\n\n\t@Override\n\tpublic TileEntity getInternalDuct() {\n\t\treturn thermalDynamicsDucts;\n\t}\n\n\t@Override\n\tpublic void setWorld_LP(World world) {\n\t\tif (thermalDynamicsDucts != null) {\n\t\t\tthermalDynamicsDucts.setWorld(world);\n\t\t\tthermalDynamicsDucts.setPos(pipe.getPos());\n\t\t\tthermalDynamicsDucts.validate();\n\t\t\t//\t\t\tthermalDynamicsDucts.onNeighborBlockChange();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void invalidate() {\n\t\tif (thermalDynamicsDucts != null) {\n\t\t\tthermalDynamicsDucts.invalidate();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onChunkUnload() {\n\t\tif (thermalDynamicsDucts != null) {\n\t\t\tthermalDynamicsDucts.onChunkUnload();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void scheduleNeighborChange() {\n\t\tif (thermalDynamicsDucts != null) {\n\t\t\tthermalDynamicsDucts.onNeighborBlockChange();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void connectionsChanged() {\n\t\tif (thermalDynamicsDucts != null) {\n\t\t\tthermalDynamicsDucts.onNeighborBlockChange();\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isLPSideBlocked(int i) {\n\t\treturn lpDuctUnit.isLPBlockedSide(i, false);\n\t}\n\n\t@Override\n\tpublic void setPos(BlockPos pos) {\n\t\tthermalDynamicsDucts.setPos(pos);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/te/ThermalExpansionProgressProvider.java",
    "content": "package logisticspipes.proxy.te;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport cofh.core.block.TileNameable;\n\nimport logisticspipes.proxy.interfaces.IGenericProgressProvider;\n\npublic class ThermalExpansionProgressProvider implements IGenericProgressProvider {\n\n\t@Override\n\tpublic boolean isType(TileEntity tile) {\n\t\treturn tile instanceof TileNameable;\n\t}\n\n\t@Override\n\tpublic byte getProgress(TileEntity tile) {\n\t\treturn (byte) Math.max(0, Math.min(((TileNameable) tile).getScaledProgress(100), 100));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/proxy/te/ThermalExpansionProxy.java",
    "content": "package logisticspipes.proxy.te;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.math.BlockPos;\n\nimport cofh.api.item.IToolHammer;\n\nimport logisticspipes.proxy.interfaces.IThermalExpansionProxy;\nimport logisticspipes.recipes.CraftingParts;\n\npublic class ThermalExpansionProxy implements IThermalExpansionProxy {\n\n\t/*\n\t@Override\n\tpublic boolean isTesseract(TileEntity tile) {\n\t\treturn tile instanceof TileTesseract;\n\t}\n\n\t@Override\n\tpublic List<TileEntity> getConnectedTesseracts(TileEntity tile) {\n\t\tEnderRegistry registry = RegistryEnderAttuned.getRegistry();\n\t\tList<TileEntity> validOutputs = new LinkedList<>();\n\t\tif(registry == null) return validOutputs;\n\t\tList<IEnderItemHandler> interfaces = registry.getLinkedItemOutputs((TileTesseract) tile);\n\t\tif (interfaces == null) {\n\t\t\treturn validOutputs;\n\t\t}\n\t\tvalidOutputs.addAll(interfaces.stream()\n\t\t\t\t.filter(object -> object.canReceiveItems() && object.canSendItems() && object instanceof TileEntity)\n\t\t\t\t.map(object -> (TileEntity) object).collect(Collectors.toList()));\n\t\treturn validOutputs;\n\t}\n\t*/\n\n\t@Override\n\tpublic boolean isTE() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic CraftingParts getRecipeParts() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isToolHammer(Item item) {\n\t\treturn item instanceof IToolHammer;\n\t}\n\n\t@Override\n\tpublic boolean canHammer(@Nonnull ItemStack stack, EntityPlayer entityplayer, BlockPos pos) {\n\t\treturn isToolHammer(stack.getItem()) && ((IToolHammer) stack.getItem()).isUsable(stack, entityplayer, pos);\n\t}\n\n\t@Override\n\tpublic void toolUsed(@Nonnull ItemStack stack, EntityPlayer entityplayer, BlockPos pos) {\n\t\tif (isToolHammer(stack.getItem())) ((IToolHammer) stack.getItem()).toolUsed(stack, entityplayer, pos);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/CraftingPartRecipes.java",
    "content": "package logisticspipes.recipes;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.Ingredient;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.items.ItemLogisticsProgrammer;\n\npublic abstract class CraftingPartRecipes implements IRecipeProvider {\n\n\tprivate static List<CraftingParts> craftingPartList = null;\n\n\tpublic static List<CraftingParts> getCraftingPartList() {\n\t\tif (craftingPartList == null) {\n\t\t\tcraftingPartList = new ArrayList<>();\n\t\t\t/*\n\t\t\tCraftingParts parts = SimpleServiceLocator.buildCraftProxy.getRecipeParts();\n\t\t\t// NO BC => NO RECIPES (for now)\n\t\t\tif (parts != null) {\n\t\t\t\tSimpleServiceLocator.IC2Proxy.addCraftingRecipes(parts);\n\t\t\t\tSimpleServiceLocator.thaumCraftProxy.addCraftingRecipes(parts);\n\t\t\t\tSimpleServiceLocator.ccProxy.addCraftingRecipes(parts);\n\t\t\t\tSimpleServiceLocator.buildCraftProxy.addCraftingRecipes(parts);\n\n\t\t\t\tRecipeManager.loadRecipes();\n\t\t\t}\n\t\t\t*/\n\n\t\t\tif (true) { // TODO: Add Config Option\n\t\t\t\tcraftingPartList.add(new CraftingParts(\n\t\t\t\t\t\tnew ItemStack(LPItems.chipFPGA, 1),\n\t\t\t\t\t\tnew ItemStack(LPItems.chipBasic, 1),\n\t\t\t\t\t\tnew ItemStack(LPItems.chipAdvanced, 1)));\n\t\t\t}\n\t\t}\n\n\t\treturn craftingPartList;\n\t}\n\n\t@Override\n\tpublic final void loadRecipes() {\n\t\tgetCraftingPartList().forEach(this::loadRecipes);\n\t}\n\n\t@Nonnull\n\tprotected Ingredient programmerIngredient(String recipeTarget) {\n\t\tItemStack programmerStack = new ItemStack(LPItems.logisticsProgrammer);\n\t\tfinal NBTTagCompound tag = new NBTTagCompound();\n\t\ttag.setString(ItemLogisticsProgrammer.RECIPE_TARGET, recipeTarget);\n\t\tprogrammerStack.setTagCompound(tag);\n\t\treturn NBTIngredient.fromStacks(programmerStack);\n\t}\n\n\tprotected abstract void loadRecipes(CraftingParts parts);\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/CraftingParts.java",
    "content": "package logisticspipes.recipes;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport lombok.Data;\n\n@Data\npublic class CraftingParts {\n\n\t/**\n\t * Iron Chip\n\t * FPGA\n\t */\n\t@Nonnull\n\tprivate final ItemStack chipFpga;\n\t/**\n\t * Gold Chip\n\t * Basic Microcontroller\n\t */\n\t@Nonnull\n\tprivate final ItemStack chipBasic;\n\t/**\n\t * Diamond Chip\n\t * Advanced Microcontroller\n\t */\n\t@Nonnull\n\tprivate final ItemStack chipAdvanced;\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/CraftingRecipes.java",
    "content": "package logisticspipes.recipes;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.modules.LogisticsModule;\n\npublic class CraftingRecipes implements IRecipeProvider {\n\n\t@Override\n\tpublic void loadRecipes() {\n\t\t// @formatter:off\n\t\tString[] dyes = {\n\t\t\t\"dyeBlack\",\n\t\t\t\"dyeRed\",\n\t\t\t\"dyeGreen\",\n\t\t\t\"dyeBrown\",\n\t\t\t\"dyeBlue\",\n\t\t\t\"dyePurple\",\n\t\t\t\"dyeCyan\",\n\t\t\t\"dyeLightGray\",\n\t\t\t\"dyeGray\",\n\t\t\t\"dyePink\",\n\t\t\t\"dyeLime\",\n\t\t\t\"dyeYellow\",\n\t\t\t\"dyeLightBlue\",\n\t\t\t\"dyeMagenta\",\n\t\t\t\"dyeOrange\",\n\t\t\t\"dyeWhite\"\n\t\t};\n\t\t// @formatter:on\n\n\t\tregisterResetRecipe(dyes);\n\t}\n\n\tprivate void registerResetRecipe(String[] dyes) {\n\t\tfor (ResourceLocation moduleResource : LPItems.modules.values()) {\n\t\t\tfinal Item item = Item.REGISTRY.getObject(moduleResource);\n\t\t\tif (item instanceof ItemModule) {\n\t\t\t\tLogisticsModule module = ((ItemModule) item).getModuleForItem(new ItemStack(item), null, null, null);\n\t\t\t\tif (module == null) continue;\n\t\t\t\tNBTTagCompound tag = new NBTTagCompound();\n\t\t\t\tmodule.writeToNBT(tag);\n\t\t\t\tif (!tag.isEmpty()) {\n\t\t\t\t\tRecipeManager.craftingManager.addShapelessResetRecipe(item, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (int i = 1; i < 17; i++) {\n\t\t\tRecipeManager.craftingManager.addOrdererRecipe(new ItemStack(LPItems.remoteOrderer, 1, i), dyes[i - 1], new ItemStack(LPItems.remoteOrderer, 1, -1));\n\t\t\tRecipeManager.craftingManager.addShapelessResetRecipe(LPItems.remoteOrderer, i);\n\t\t}\n\t\tRecipeManager.craftingManager.addShapelessResetRecipe(LPItems.remoteOrderer, 0);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/IRecipeProvider.java",
    "content": "package logisticspipes.recipes;\n\npublic interface IRecipeProvider {\n\n\tvoid loadRecipes();\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/LPChipRecipes.java",
    "content": "package logisticspipes.recipes;\n\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.fml.common.registry.GameRegistry;\n\nimport logisticspipes.LPItems;\n\npublic class LPChipRecipes implements IRecipeProvider {\n\n\t@Override\n\tpublic void loadRecipes() {\n\t\tGameRegistry.addSmelting(new ItemStack(LPItems.chipBasicRaw, 1), new ItemStack(LPItems.chipBasic, 1), 0);\n\t\tGameRegistry.addSmelting(new ItemStack(LPItems.chipAdvancedRaw, 1), new ItemStack(LPItems.chipAdvanced, 1), 0);\n\t\tGameRegistry.addSmelting(new ItemStack(LPItems.chipFPGARaw, 1), new ItemStack(LPItems.chipFPGA, 1), 0);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/ModuleChippedCraftingRecipes.java",
    "content": "package logisticspipes.recipes;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.init.Items;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.Ingredient;\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.modules.ModuleActiveSupplier;\nimport logisticspipes.modules.ModuleCrafter;\nimport logisticspipes.modules.ModuleCreativeTabBasedItemSink;\nimport logisticspipes.modules.ModuleEnchantmentSink;\nimport logisticspipes.modules.ModuleEnchantmentSinkMK2;\nimport logisticspipes.modules.ModuleItemSink;\nimport logisticspipes.modules.ModuleModBasedItemSink;\nimport logisticspipes.modules.ModuleOreDictItemSink;\nimport logisticspipes.modules.ModulePassiveSupplier;\nimport logisticspipes.modules.ModulePolymorphicItemSink;\nimport logisticspipes.modules.ModuleProvider;\nimport logisticspipes.modules.ModuleTerminus;\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor;\nimport network.rs485.logisticspipes.module.AsyncExtractorModule;\nimport network.rs485.logisticspipes.module.AsyncQuicksortModule;\n\npublic class ModuleChippedCraftingRecipes extends CraftingPartRecipes {\n\n\tenum RecipeType {\n\t\tLEVEL_1,\n\t\tLEVEL_2,\n\t\tLEVEL_3,\n\t\tUPGRADE_1,\n\t\tUPGRADE_2,\n\t\tUPGRADE_3,\n\t\tLEVEL_4,\n\t\tUPGRADE_4,\n\t\tUPGRADE_5,\n\t\tUPGRADE_6,\n\t\tADVANCED_1,\n\t\tADVANCED_2,\n\t\tADVANCED_3,\n\t\tADVANCED_4\n\t}\n\n\tprivate void registerModuleRecipe(CraftingParts parts, RecipeType type, ResourceLocation recipeCategory, @Nonnull String moduleName, @Nullable String baseModuleName) {\n\t\tfinal ResourceLocation moduleResource = LPItems.modules.get(moduleName);\n\t\tItem module = Item.REGISTRY.getObject(moduleResource);\n\t\tif (module == null) return;\n\t\tItem baseModule;\n\t\tif (baseModuleName == null) {\n\t\t\tbaseModule = LPItems.blankModule;\n\t\t} else {\n\t\t\tbaseModule = Item.REGISTRY.getObject(LPItems.modules.get(baseModuleName));\n\t\t}\n\t\tif (baseModule == null) return;\n\n\t\tIngredient programmer = programmerIngredient(moduleResource.toString());\n\t\tfinal Set<ResourceLocation> compilerPrograms = LogisticsProgramCompilerTileEntity.programByCategory.putIfAbsent(recipeCategory, new HashSet<>());\n\t\tObjects.requireNonNull(compilerPrograms).add(moduleResource);\n\n\t\tRecipeManager.RecipeLayout layout = null;\n\t\tswitch (type) {\n\t\t\tcase LEVEL_1:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rfr\",\n\t\t\t\t\t\t\"imi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_2:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"fpf\",\n\t\t\t\t\t\t\"rbr\",\n\t\t\t\t\t\t\"imi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_3:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"fpf\",\n\t\t\t\t\t\t\"rar\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase UPGRADE_1:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"p\",\n\t\t\t\t\t\t\"f\",\n\t\t\t\t\t\t\"m\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase UPGRADE_2:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rfr\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase UPGRADE_3:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"bpb\",\n\t\t\t\t\t\t\"rar\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_4:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"fpf\",\n\t\t\t\t\t\t\"lbl\",\n\t\t\t\t\t\t\"imi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase UPGRADE_4:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"fpf\",\n\t\t\t\t\t\t\"lal\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase UPGRADE_5:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rbr\",\n\t\t\t\t\t\t\"imi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase UPGRADE_6:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rbr\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase ADVANCED_1:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"fpf\",\n\t\t\t\t\t\t\"lbl\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase ADVANCED_2:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"bpb\",\n\t\t\t\t\t\t\"lal\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase ADVANCED_3:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"apa\",\n\t\t\t\t\t\t\"zbz\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase ADVANCED_4:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"bpb\",\n\t\t\t\t\t\t\"zaz\",\n\t\t\t\t\t\t\"gmg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (layout != null) {\n\t\t\tfinal RecipeManager.RecipeLayout fLayout = layout;\n\t\t\tList<RecipeManager.RecipeIndex> recipeIndexes = Arrays.asList(\n\t\t\t\t\tnew RecipeManager.RecipeIndex('a', parts.getChipAdvanced()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('f', parts.getChipFpga()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('g', \"ingotGold\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('i', \"ingotIron\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('l', \"gemLapis\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('m', baseModule),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('p', programmer),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('r', \"dustRedstone\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('z', Items.BLAZE_POWDER));\n\t\t\tLinkedList<Object> indexToUse = recipeIndexes.stream()\n\t\t\t\t\t.filter(recipeIndex -> !(fLayout.getLine1() + fLayout.getLine2() + fLayout.getLine3()).replace(recipeIndex.getIndex(), ' ')\n\t\t\t\t\t\t\t.equals((fLayout.getLine1() + fLayout.getLine2() + fLayout.getLine3()))).collect(Collectors.toCollection(LinkedList::new));\n\t\t\tindexToUse.addFirst(layout);\n\t\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(module), indexToUse.toArray());\n\t\t}\n\t}\n\n\t@Override\n\tprotected void loadRecipes(CraftingParts parts) {\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, ModuleItemSink.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, ModulePassiveSupplier.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, AsyncExtractorModule.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, ModulePolymorphicItemSink.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_3, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, AsyncQuicksortModule.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, ModuleTerminus.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.UPGRADE_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, AsyncAdvancedExtractor.getName(), AsyncExtractorModule.getName());\n\t\tregisterModuleRecipe(parts, RecipeType.LEVEL_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, ModuleProvider.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.UPGRADE_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleModBasedItemSink.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.UPGRADE_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleOreDictItemSink.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.UPGRADE_5, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleEnchantmentSink.getName(), ModuleItemSink.getName());\n\t\tregisterModuleRecipe(parts, RecipeType.UPGRADE_6, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleEnchantmentSinkMK2.getName(), ModuleEnchantmentSink.getName());\n\t\tregisterModuleRecipe(parts, RecipeType.UPGRADE_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleCreativeTabBasedItemSink.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.ADVANCED_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleCrafter.getName(), null);\n\t\tregisterModuleRecipe(parts, RecipeType.ADVANCED_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS_2, ModuleActiveSupplier.getName(), null);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/NBTIngredient.java",
    "content": "package logisticspipes.recipes;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.util.RecipeItemHelper;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.Ingredient;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport it.unimi.dsi.fastutil.ints.IntArrayList;\nimport it.unimi.dsi.fastutil.ints.IntComparators;\nimport it.unimi.dsi.fastutil.ints.IntList;\n\npublic class NBTIngredient extends Ingredient {\n\n\tprivate final ItemStack[] matchingStacks;\n\tprivate IntList matchingStacksPacked;\n\n\tprotected NBTIngredient(ItemStack... stacks) {\n\t\tthis.matchingStacks = stacks;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack[] getMatchingStacks() {\n\t\treturn this.matchingStacks;\n\t}\n\n\t@Override\n\tpublic boolean apply(@Nullable final ItemStack inputStack) {\n\t\tif (inputStack == null) return false;\n\t\tfor (final ItemStack stack : matchingStacks) {\n\t\t\tif (stack.getItem() == inputStack.getItem()) {\n\t\t\t\tfinal int metadata = stack.getMetadata();\n\t\t\t\tif ((metadata == OreDictionary.WILDCARD_VALUE || metadata == inputStack.getMetadata()) && ItemStack.areItemStackTagsEqual(inputStack, stack)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IntList getValidItemStacksPacked() {\n\t\tif (matchingStacksPacked == null) {\n\t\t\tmatchingStacksPacked = new IntArrayList(this.matchingStacks.length);\n\t\t\tfor (final ItemStack stack : this.matchingStacks) {\n\t\t\t\tmatchingStacksPacked.add(RecipeItemHelper.pack(stack));\n\t\t\t}\n\t\t\tmatchingStacksPacked.sort(IntComparators.NATURAL_COMPARATOR);\n\t\t}\n\t\treturn matchingStacksPacked;\n\t}\n\n\t@Override\n\tprotected void invalidate() {\n\t\tmatchingStacksPacked = null;\n\t}\n\n\t@Nonnull\n\tpublic static Ingredient fromStacks(final ItemStack... stacks) {\n\t\tif (stacks.length > 0) {\n\t\t\tfor (final ItemStack itemstack : stacks) {\n\t\t\t\tif (!itemstack.isEmpty()) {\n\t\t\t\t\treturn new NBTIngredient(stacks);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn EMPTY;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/PipeChippedCraftingRecipes.java",
    "content": "package logisticspipes.recipes;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.init.Items;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.Ingredient;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.items.ItemLogisticsProgrammer;\n\npublic class PipeChippedCraftingRecipes extends CraftingPartRecipes {\n\n\tenum RecipeType {\n\t\tLEVEL_1,\n\t\tLEVEL_2,\n\t\tLEVEL_3,\n\t\tENDER_1,\n\t\tENDER_2,\n\t}\n\n\tprivate void registerPipeRecipeCategory(ResourceLocation recipeCategory, Item targetPipe) {\n\t\tif (!LogisticsProgramCompilerTileEntity.programByCategory.containsKey(recipeCategory)) {\n\t\t\tLogisticsProgramCompilerTileEntity.programByCategory.put(recipeCategory, new HashSet<>());\n\t\t}\n\t\tLogisticsProgramCompilerTileEntity.programByCategory.get(recipeCategory).add(targetPipe.getRegistryName());\n\t}\n\n\tprivate void registerPipeRecipe(CraftingParts parts, RecipeType type, ResourceLocation recipeCategory, Item targetPipe, Item basePipe) {\n\t\tIngredient programmer = getIngredientForProgrammer(targetPipe);\n\n\t\tregisterPipeRecipeCategory(recipeCategory, targetPipe);\n\n\t\tRecipeManager.RecipeLayout layout = null;\n\t\tswitch (type) {\n\t\t\tcase LEVEL_1:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rfr\",\n\t\t\t\t\t\t\" s \"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_2:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rbr\",\n\t\t\t\t\t\t\"isi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_3:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"rar\",\n\t\t\t\t\t\t\"gsg\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase ENDER_1:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"ebr\",\n\t\t\t\t\t\t\"isi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase ENDER_2:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"ear\",\n\t\t\t\t\t\t\"isi\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (layout != null) {\n\t\t\tfinal RecipeManager.RecipeLayout fLayout = layout;\n\t\t\tList<RecipeManager.RecipeIndex> recipeIndexes = Arrays.asList(\n\t\t\t\t\tnew RecipeManager.RecipeIndex('a', parts.getChipAdvanced()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('f', parts.getChipFpga()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('g', \"ingotGold\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('n', \"nuggetGold\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('i', \"ingotIron\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('l', \"gemLapis\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('p', programmer),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('r', \"dustRedstone\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('s', basePipe),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('z', Items.BLAZE_POWDER),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('e', Items.ENDER_PEARL));\n\t\t\tLinkedList<Object> indexToUse = recipeIndexes.stream()\n\t\t\t\t\t.filter(recipeIndex -> !(fLayout.getLine1() + fLayout.getLine2() + fLayout.getLine3()).replace(recipeIndex.getIndex(), ' ')\n\t\t\t\t\t\t\t.equals((fLayout.getLine1() + fLayout.getLine2() + fLayout.getLine3()))).collect(Collectors.toCollection(LinkedList::new));\n\t\t\tindexToUse.addFirst(layout);\n\t\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(targetPipe), indexToUse.toArray());\n\t\t}\n\t}\n\n\tprivate Ingredient getIngredientForProgrammer(Item targetPipe) {\n\t\tItemStack programmerStack = new ItemStack(LPItems.logisticsProgrammer);\n\t\tprogrammerStack.setTagCompound(new NBTTagCompound());\n\t\tprogrammerStack.getTagCompound().setString(ItemLogisticsProgrammer.RECIPE_TARGET, targetPipe.getRegistryName().toString());\n\t\treturn NBTIngredient.fromStacks(programmerStack);\n\t}\n\n\t@Override\n\tprotected void loadRecipes(CraftingParts parts) {\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, LPItems.pipeRequest, LPItems.pipeBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, LPItems.pipeProvider, LPItems.pipeBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, LPItems.pipeCrafting, LPItems.pipeBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, LPItems.pipeSatellite, LPItems.pipeBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, LPItems.pipeSupplier, LPItems.pipeBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_3, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, LPItems.pipeRequestMk2, LPItems.pipeRequest);\n\t\tregisterPipeRecipe(parts, RecipeType.ENDER_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, LPItems.pipeRemoteOrderer, LPItems.pipeBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.ENDER_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_3, LPItems.pipeInvSystemConnector, LPItems.pipeBasic);\n\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, LPItems.pipeSystemEntrance, LPItems.pipeProvider);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, LPItems.pipeSystemDestination, LPItems.pipeProvider);\n\t\tregisterPipeRecipe(parts, RecipeType.ENDER_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_3, LPItems.pipeFirewall, LPItems.pipeBasic);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, LPItems.pipeChassisMk1);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeChassisMk1),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\" b \",\n\t\t\t\t\t\t\"fsf\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeChassisMk1)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeBasic),\n\t\t\t\tnew RecipeManager.RecipeIndex('f', parts.getChipFpga())\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, LPItems.pipeChassisMk2);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeChassisMk2),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"bsb\",\n\t\t\t\t\t\t\"ili\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeChassisMk2)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeChassisMk1),\n\t\t\t\tnew RecipeManager.RecipeIndex('l', \"gemLapis\"),\n\t\t\t\tnew RecipeManager.RecipeIndex('i', \"ingotIron\")\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, LPItems.pipeChassisMk3);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeChassisMk3),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"gsg\",\n\t\t\t\t\t\t\"iai\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('a', parts.getChipAdvanced()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeChassisMk3)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeChassisMk2),\n\t\t\t\tnew RecipeManager.RecipeIndex('g', \"dustGlowstone\"),\n\t\t\t\tnew RecipeManager.RecipeIndex('i', \"ingotIron\")\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, LPItems.pipeChassisMk4);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeChassisMk4),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"bsb\",\n\t\t\t\t\t\t\"gag\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('a', parts.getChipAdvanced()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeChassisMk4)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeChassisMk3),\n\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\tnew RecipeManager.RecipeIndex('g', \"ingotGold\")\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.CHASSIS, LPItems.pipeChassisMk5);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeChassisMk5),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"asa\",\n\t\t\t\t\t\t\"dnd\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('a', parts.getChipAdvanced()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeChassisMk5)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeChassisMk4),\n\t\t\t\tnew RecipeManager.RecipeIndex('d', \"gemDiamond\"),\n\t\t\t\tnew RecipeManager.RecipeIndex('n', \"gemQuartz\")\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidSupplier);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeFluidSupplier),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"bsb\",\n\t\t\t\t\t\t\"iwi\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeFluidSupplier)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeBasic),\n\t\t\t\tnew RecipeManager.RecipeIndex('w', Items.BUCKET),\n\t\t\t\tnew RecipeManager.RecipeIndex('i', \"ingotIron\")\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidBasic);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeFluidBasic),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"bsb\",\n\t\t\t\t\t\t\"gwg\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeFluidBasic)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeBasic),\n\t\t\t\tnew RecipeManager.RecipeIndex('w', Items.BUCKET),\n\t\t\t\tnew RecipeManager.RecipeIndex('g', \"ingotGold\")\n\t\t);\n\n\t\tregisterPipeRecipeCategory(LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidTerminus);\n\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(LPItems.pipeFluidTerminus),\n\t\t\t\tnew RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\" p \",\n\t\t\t\t\t\t\"wsv\",\n\t\t\t\t\t\t\"gbg\"\n\t\t\t\t),\n\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\tnew RecipeManager.RecipeIndex('p', getIngredientForProgrammer(LPItems.pipeFluidTerminus)),\n\t\t\t\tnew RecipeManager.RecipeIndex('s', LPItems.pipeFluidBasic),\n\t\t\t\tnew RecipeManager.RecipeIndex('w', \"dyeBlack\"),\n\t\t\t\tnew RecipeManager.RecipeIndex('v', \"dyePurple\"),\n\t\t\t\tnew RecipeManager.RecipeIndex('g', \"ingotIron\")\n\t\t);\n\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidRequest, LPItems.pipeFluidBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidProvider, LPItems.pipeFluidBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidSupplierMk2, LPItems.pipeFluidSupplier);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidSatellite, LPItems.pipeFluidBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidInsertion, LPItems.pipeFluidBasic);\n\t\tregisterPipeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.FLUID, LPItems.pipeFluidExtractor, LPItems.pipeFluidBasic);\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/RecipeManager.java",
    "content": "package logisticspipes.recipes;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.nio.file.Files;\nimport java.nio.file.StandardOpenOption;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.inventory.InventoryCrafting;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.CraftingManager;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.oredict.ShapedOreRecipe;\nimport net.minecraftforge.oredict.ShapelessOreRecipe;\nimport net.minecraftforge.registries.GameData;\n\nimport com.google.gson.Gson;\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonObject;\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.items.RemoteOrderer;\n\npublic class RecipeManager {\n\n\tpublic static final List<IRecipeProvider> recipeProvider = new ArrayList<>();\n\tpublic static final LocalCraftingManager craftingManager = new LocalCraftingManager();\n\n\tpublic static void loadRecipes() {\n\t\trecipeProvider.forEach(IRecipeProvider::loadRecipes);\n\t}\n\n\t@AllArgsConstructor\n\t@Getter\n\tpublic static class RecipeIndex {\n\n\t\tprivate char index;\n\t\tprivate Object value;\n\t}\n\n\t@AllArgsConstructor\n\t@Getter\n\tpublic static class RecipeLayout {\n\n\t\tprivate String line1;\n\t\tprivate String line2;\n\t\tprivate String line3;\n\t}\n\n\t@AllArgsConstructor\n\t@Getter\n\tpublic static class RecipeLayoutSmall {\n\n\t\tprivate String line1;\n\t\tprivate String line2;\n\t}\n\n\t@AllArgsConstructor\n\t@Getter\n\tpublic static class RecipeLayoutSmaller {\n\n\t\tprivate String line1;\n\t}\n\n\tpublic static class LocalCraftingManager {\n\n\t\tpublic LocalCraftingManager() {\n\t\t}\n\n\t\t@SuppressWarnings(\"unchecked\")\n\t\tpublic void addRecipe(@Nonnull ItemStack stack, Object... objects) {\n\t\t\tList<Object> result = new ArrayList<>();\n\t\t\tfinal boolean[] addRecipe = { true };\n\t\t\tArrays.stream(objects).forEach(o -> {\n\t\t\t\tif (!addRecipe[0]) return;\n\t\t\t\tif (o instanceof RecipeLayout) {\n\t\t\t\t\tresult.add(((RecipeLayout) o).getLine1());\n\t\t\t\t\tresult.add(((RecipeLayout) o).getLine2());\n\t\t\t\t\tresult.add(((RecipeLayout) o).getLine3());\n\t\t\t\t} else if (o instanceof RecipeLayoutSmall) {\n\t\t\t\t\tresult.add(((RecipeLayoutSmall) o).getLine1());\n\t\t\t\t\tresult.add(((RecipeLayoutSmall) o).getLine2());\n\t\t\t\t} else if (o instanceof RecipeLayoutSmaller) {\n\t\t\t\t\tresult.add(((RecipeLayoutSmaller) o).getLine1());\n\t\t\t\t} else if (o instanceof RecipeIndex) {\n\t\t\t\t\tresult.add(((RecipeIndex) o).getIndex());\n\t\t\t\t\tresult.add(((RecipeIndex) o).getValue());\n\t\t\t\t\tif (((RecipeIndex) o).getValue() == null) {\n\t\t\t\t\t\taddRecipe[0] = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresult.add(o);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (!addRecipe[0]) return;\n\n\t\t\t//\t\t\tRecipeIndex[] indices = new RecipeIndex[objects.length-1];\n\t\t\t//\t\t\tSystem.arraycopy(objects, 1, indices, 0, indices.length);\n\t\t\t//\t\t\tdumpRecipe(stack, objects[0], indices);\n\n\t\t\tGameData.register_impl(new ShapedOreRecipe(new ResourceLocation(LPConstants.LP_MOD_ID, \"group.mainRecipeGroup\"), stack, result.toArray()).setRegistryName(getFreeRecipeResourceLocation(stack)));\n\t\t}\n\n\t\tprivate void dumpRecipe(@Nonnull ItemStack result, Object layout, RecipeIndex... indices) {\n\t\t\tJsonObject obj = new JsonObject();\n\t\t\tJsonArray pattern = new JsonArray();\n\t\t\tJsonObject keys = new JsonObject();\n\t\t\tobj.addProperty(\"type\", \"minecraft:crafting_shaped\");\n\n\t\t\tif (layout instanceof RecipeLayout) {\n\t\t\t\tpattern.add(((RecipeLayout) layout).getLine1());\n\t\t\t\tpattern.add(((RecipeLayout) layout).getLine2());\n\t\t\t\tpattern.add(((RecipeLayout) layout).getLine3());\n\t\t\t} else if (layout instanceof RecipeLayoutSmall) {\n\t\t\t\tpattern.add(((RecipeLayoutSmall) layout).getLine1());\n\t\t\t\tpattern.add(((RecipeLayoutSmall) layout).getLine2());\n\t\t\t} else if (layout instanceof RecipeLayoutSmaller) {\n\t\t\t\tpattern.add(((RecipeLayoutSmaller) layout).getLine1());\n\t\t\t}\n\n\t\t\tfor (RecipeIndex index : indices) {\n\t\t\t\tJsonObject key = new JsonObject();\n\t\t\t\tif (index.getValue() instanceof String) {\n\t\t\t\t\tkey.addProperty(\"type\", \"forge:ore_dict\");\n\t\t\t\t\tkey.addProperty(\"ore\", (String) index.getValue());\n\t\t\t\t} else if (index.getValue() instanceof ItemStack) {\n\t\t\t\t\tItemStack stack = (ItemStack) index.getValue();\n\t\t\t\t\tkey.addProperty(\"item\", stack.getItem().getRegistryName().toString());\n\t\t\t\t\tif (stack.getHasSubtypes()) key.addProperty(\"data\", stack.getItemDamage());\n\t\t\t\t} else if (index.getValue() instanceof Item) {\n\t\t\t\t\tkey.addProperty(\"item\", ((Item) index.getValue()).getRegistryName().toString());\n\t\t\t\t} else if (index.getValue() instanceof Block) {\n\t\t\t\t\tkey.addProperty(\"item\", Item.getItemFromBlock((Block) index.getValue()).getRegistryName().toString());\n\t\t\t\t\t//\t\t\t\t} else if (index.getValue() instanceof NBTIngredient) {\n\t\t\t\t\t//\t\t\t\t\tkey.addProperty(\"type\", \"minecraft:item_nbt\");\n\t\t\t\t\t//\t\t\t\t\tNBTIngredient value = (NBTIngredient) index.getValue();\n\t\t\t\t\t//\t\t\t\t\tItemStack stack = value.getMatchingStacks()[0];\n\t\t\t\t\t//\t\t\t\t\tif (value.getMatchingStacks().length > 1) throw new NotImplementedException(\"valid stacks size > 1\");\n\t\t\t\t\t//\t\t\t\t\tkey.addProperty(\"item\", stack.getItem().getRegistryName().toString());\n\t\t\t\t\t//\t\t\t\t\tif (stack.getHasSubtypes()) key.addProperty(\"data\", stack.getItemDamage());\n\t\t\t\t\t//\t\t\t\t\tJsonObject nbt = new JsonObject();\n\t\t\t\t\t//\t\t\t\t\t// TODO\n\t\t\t\t\t//\t\t\t\t\tkey.add(\"nbt\", nbt);\n\t\t\t\t} else {\n\t\t\t\t\tSystem.out.printf(\"unhandled ingredient type, skipping export (%s)\\n\", index.getValue());\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tkeys.add(index.getIndex() + \"\", key);\n\t\t\t}\n\n\t\t\tJsonObject r = new JsonObject();\n\t\t\tr.addProperty(\"item\", result.getItem().getRegistryName().toString());\n\t\t\tif (result.getItemDamage() > 0) r.addProperty(\"data\", result.getItemDamage());\n\t\t\tif (result.getCount() > 1) r.addProperty(\"count\", result.getCount());\n\t\t\tobj.add(\"result\", r);\n\t\t\tobj.add(\"key\", keys);\n\t\t\tobj.add(\"pattern\", pattern);\n\n\t\t\tString format;\n\t\t\tif (result.getHasSubtypes()) {\n\t\t\t\tformat = String.format(\"generated_recipes/%s.%d.json\", result.getItem().getRegistryName().getPath(), result.getItemDamage());\n\t\t\t} else {\n\t\t\t\tformat = String.format(\"generated_recipes/%s.json\", result.getItem().getRegistryName().getPath());\n\t\t\t}\n\n\t\t\tFile out = new File(format);\n\t\t\tout.getParentFile().mkdirs();\n\t\t\tString text = new Gson().toJson(obj);\n\t\t\ttry {\n\t\t\t\tFiles.write(out.toPath(), text.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE_NEW);\n\t\t\t} catch (IOException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\n\t\tpublic void addOrdererRecipe(@Nonnull ItemStack stack, String dye, ItemStack orderer) {\n\t\t\tGameData.register_impl(new ShapelessOrdererRecipe(getFreeRecipeResourceLocation(stack), stack, dye, orderer));\n\t\t}\n\n\t\tpublic void addShapelessRecipe(@Nonnull ItemStack stack, Object... objects) {\n\t\t\tGameData.register_impl(new ShapelessOreRecipe(new ResourceLocation(LPConstants.LP_MOD_ID, \"group.mainRecipeGroup\"), stack, objects).setRegistryName(getFreeRecipeResourceLocation(stack)));\n\t\t}\n\n\t\tpublic void addShapelessResetRecipe(Item item, int meta) {\n\t\t\tShapelessResetRecipe value = new ShapelessResetRecipe(item, meta);\n\t\t\tvalue.setRegistryName(getFreeRecipeResourceLocation(item));\n\t\t\tGameData.register_impl(value);\n\t\t}\n\n\t\tpublic static class ShapelessOrdererRecipe extends ShapelessOreRecipe {\n\n\t\t\tpublic ShapelessOrdererRecipe(ResourceLocation registryName, @Nonnull ItemStack result, Object... recipe) {\n\t\t\t\tsuper(new ResourceLocation(LPConstants.LP_MOD_ID, \"group.mainRecipeGroup\"), result, recipe);\n\t\t\t\tsetRegistryName(registryName);\n\t\t\t}\n\n\t\t\t@Nonnull\n\t\t\t@Override\n\t\t\tpublic ItemStack getCraftingResult(@Nonnull InventoryCrafting var1) {\n\t\t\t\tItemStack result = super.getCraftingResult(var1);\n\t\t\t\tfor (int i = 0; i < var1.getInventoryStackLimit(); i++) {\n\t\t\t\t\tItemStack stack = var1.getStackInSlot(i);\n\t\t\t\t\tif (!stack.isEmpty() && stack.getItem() instanceof RemoteOrderer) {\n\t\t\t\t\t\tresult.setTagCompound(stack.getTagCompound());\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static ResourceLocation getFreeRecipeResourceLocation(@Nonnull ItemStack stack) {\n\t\treturn getFreeRecipeResourceLocation(stack.getItem());\n\t}\n\n\tprivate static ResourceLocation getFreeRecipeResourceLocation(Item item) {\n\t\tResourceLocation baseLoc = new ResourceLocation(LPConstants.LP_MOD_ID, item.getRegistryName().getPath());\n\t\tResourceLocation recipeLoc = baseLoc;\n\t\tint index = 0;\n\t\twhile (CraftingManager.REGISTRY.containsKey(recipeLoc)) {\n\t\t\tindex++;\n\t\t\trecipeLoc = new ResourceLocation(LPConstants.LP_MOD_ID, baseLoc.getPath() + \"_\" + index);\n\t\t}\n\t\treturn recipeLoc;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/ShapelessResetRecipe.java",
    "content": "package logisticspipes.recipes;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.inventory.InventoryCrafting;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.IRecipe;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.registries.IForgeRegistryEntry;\n\npublic class ShapelessResetRecipe extends IForgeRegistryEntry.Impl<IRecipe> implements IRecipe {\n\n\tprivate final Item item;\n\tprivate final int meta;\n\tprivate final ItemStack output;\n\n\tpublic ShapelessResetRecipe(Item item, int meta) {\n\t\toutput = new ItemStack(item, 1, meta);\n\t\tthis.item = item;\n\t\tthis.meta = meta;\n\t}\n\n\t@Override\n\tpublic boolean matches(InventoryCrafting var1, World var2) {\n\t\tint nmatches = 0;\n\t\tfor (int i = 0; i < var1.getSizeInventory(); i++) {\n\t\t\tItemStack stack = var1.getStackInSlot(i);\n\t\t\tif (stack.isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (stack.getItem() != item || stack.getItemDamage() != meta) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tnmatches++;\n\t\t}\n\t\treturn (nmatches > 0);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack getCraftingResult(InventoryCrafting var1) {\n\t\tint nmatches = 0;\n\t\tfor (int i = 0; i < var1.getSizeInventory(); i++) {\n\t\t\tif (var1.getStackInSlot(i).isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnmatches++;\n\t\t}\n\t\treturn new ItemStack(item, nmatches, meta);\n\t}\n\n\t@Override\n\tpublic boolean canFit(int width, int height) {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack getRecipeOutput() {\n\t\treturn output;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/UpgradeChippedCraftingRecipes.java",
    "content": "package logisticspipes.recipes;\n\nimport java.util.Arrays;\nimport java.util.HashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.init.Items;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.Ingredient;\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.blocks.LogisticsProgramCompilerTileEntity;\nimport logisticspipes.pipes.upgrades.ActionSpeedUpgrade;\nimport logisticspipes.pipes.upgrades.AdvancedSatelliteUpgrade;\nimport logisticspipes.pipes.upgrades.CombinedSneakyUpgrade;\nimport logisticspipes.pipes.upgrades.ConnectionUpgradeConfig;\nimport logisticspipes.pipes.upgrades.CraftingByproductUpgrade;\nimport logisticspipes.pipes.upgrades.CraftingCleanupUpgrade;\nimport logisticspipes.pipes.upgrades.CraftingMonitoringUpgrade;\nimport logisticspipes.pipes.upgrades.FluidCraftingUpgrade;\nimport logisticspipes.pipes.upgrades.FuzzyUpgrade;\nimport logisticspipes.pipes.upgrades.ItemExtractionUpgrade;\nimport logisticspipes.pipes.upgrades.ItemStackExtractionUpgrade;\nimport logisticspipes.pipes.upgrades.OpaqueUpgrade;\nimport logisticspipes.pipes.upgrades.PatternUpgrade;\nimport logisticspipes.pipes.upgrades.PowerTransportationUpgrade;\nimport logisticspipes.pipes.upgrades.SneakyUpgradeConfig;\nimport logisticspipes.pipes.upgrades.SpeedUpgrade;\nimport logisticspipes.pipes.upgrades.UpgradeModuleUpgrade;\n\npublic class UpgradeChippedCraftingRecipes extends CraftingPartRecipes {\n\n\tenum RecipeType {\n\t\tLEVEL_1,\n\t\tLEVEL_2,\n\t\tLEVEL_3,\n\t\tLEVEL_4,\n\t}\n\n\tprivate void registerUpgradeRecipe(CraftingParts parts, RecipeType type, ResourceLocation recipeCategory, String upgradeName) {\n\t\tregisterUpgradeRecipe(parts, type, recipeCategory, upgradeName, 1);\n\t}\n\n\tprivate void registerUpgradeRecipe(CraftingParts parts, RecipeType type, ResourceLocation recipeCategory, String upgradeName, int amount) {\n\t\tResourceLocation upgradeResource = LPItems.upgrades.get(upgradeName);\n\t\tItem upgrade = Item.REGISTRY.getObject(upgradeResource);\n\t\tif (upgrade == null) return;\n\n\t\tIngredient programmer = programmerIngredient(upgradeResource.toString());\n\t\tfinal Set<ResourceLocation> compilerPrograms = LogisticsProgramCompilerTileEntity.programByCategory.putIfAbsent(recipeCategory, new HashSet<>());\n\t\tObjects.requireNonNull(compilerPrograms).add(upgradeResource);\n\n\t\tRecipeManager.RecipeLayout layout = null;\n\t\tswitch (type) {\n\t\t\tcase LEVEL_1:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"rpr\",\n\t\t\t\t\t\t\"ibi\",\n\t\t\t\t\t\t\"qnq\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_2:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"rpr\",\n\t\t\t\t\t\t\"iai\",\n\t\t\t\t\t\t\"qnq\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_3:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"rpr\",\n\t\t\t\t\t\t\"gbg\",\n\t\t\t\t\t\t\"qnq\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase LEVEL_4:\n\t\t\t\tlayout = new RecipeManager.RecipeLayout(\n\t\t\t\t\t\t\"rpr\",\n\t\t\t\t\t\t\"gag\",\n\t\t\t\t\t\t\"qnq\"\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t\tif (layout != null) {\n\t\t\tfinal RecipeManager.RecipeLayout fLayout = layout;\n\t\t\tList<RecipeManager.RecipeIndex> recipeIndexes = Arrays.asList(\n\t\t\t\t\tnew RecipeManager.RecipeIndex('a', parts.getChipAdvanced()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('b', parts.getChipBasic()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('f', parts.getChipFpga()),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('g', \"ingotGold\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('n', \"nuggetGold\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('i', \"ingotIron\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('l', \"gemLapis\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('p', programmer),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('r', \"dustRedstone\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('q', \"paper\"),\n\t\t\t\t\tnew RecipeManager.RecipeIndex('z', Items.BLAZE_POWDER));\n\t\t\tLinkedList<Object> indexToUse = recipeIndexes.stream()\n\t\t\t\t\t.filter(recipeIndex -> !(fLayout.getLine1() + fLayout.getLine2() + fLayout.getLine3()).replace(recipeIndex.getIndex(), ' ')\n\t\t\t\t\t\t\t.equals((fLayout.getLine1() + fLayout.getLine2() + fLayout.getLine3()))).collect(Collectors.toCollection(LinkedList::new));\n\t\t\tindexToUse.addFirst(layout);\n\t\t\tRecipeManager.craftingManager.addRecipe(new ItemStack(upgrade, amount), indexToUse.toArray());\n\t\t}\n\t}\n\n\t@Override\n\tprotected void loadRecipes(CraftingParts parts) {\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, SneakyUpgradeConfig.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, SpeedUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, CombinedSneakyUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, ConnectionUpgradeConfig.getName(), 8);\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, AdvancedSatelliteUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, FluidCraftingUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, CraftingByproductUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, PatternUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, FuzzyUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, PowerTransportationUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, CraftingMonitoringUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_1, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, OpaqueUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_2, LogisticsProgramCompilerTileEntity.ProgrammCategories.BASIC, CraftingCleanupUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_3, UpgradeModuleUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_3, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, ActionSpeedUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_3, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, ItemExtractionUpgrade.getName());\n\t\tregisterUpgradeRecipe(parts, RecipeType.LEVEL_4, LogisticsProgramCompilerTileEntity.ProgrammCategories.TIER_2, ItemStackExtractionUpgrade.getName());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/conditions/ConditionOreExists.java",
    "content": "package logisticspipes.recipes.conditions;\n\nimport java.util.function.BooleanSupplier;\n\nimport net.minecraftforge.common.crafting.IConditionFactory;\nimport net.minecraftforge.common.crafting.JsonContext;\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport com.google.gson.JsonObject;\n\n@SuppressWarnings(\"unused\")\npublic class ConditionOreExists implements IConditionFactory {\n\n\t@Override\n\tpublic BooleanSupplier parse(JsonContext context, JsonObject json) {\n\t\tString str = json.get(\"ore\").getAsString();\n\t\tboolean invert = str.startsWith(\"!\");\n\t\tif (invert) str = str.substring(1);\n\t\tString ore = str;\n\t\treturn () -> invert ^ OreDictionary.doesOreNameExist(ore);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/recipes/ingredients/IngredientPart.java",
    "content": "package logisticspipes.recipes.ingredients;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.item.crafting.Ingredient;\n\nimport net.minecraftforge.common.crafting.IIngredientFactory;\nimport net.minecraftforge.common.crafting.JsonContext;\n\nimport com.google.gson.JsonObject;\n\nimport logisticspipes.recipes.CraftingPartRecipes;\nimport logisticspipes.recipes.CraftingParts;\n\n@SuppressWarnings(\"unused\") // used in recipes\npublic class IngredientPart implements IIngredientFactory {\n\n\tpublic enum PartType {\n\t\tchip_basic,\n\t\tchip_advanced,\n\t\tchip_fpga,\n\t\t;\n\n\t\t@Nonnull\n\t\tpublic ItemStack getStack(CraftingParts parts) {\n\t\t\tswitch (this) {\n\t\t\t\tcase chip_basic:\n\t\t\t\t\treturn parts.getChipBasic();\n\t\t\t\tcase chip_advanced:\n\t\t\t\t\treturn parts.getChipAdvanced();\n\t\t\t\tcase chip_fpga:\n\t\t\t\t\treturn parts.getChipFpga();\n\t\t\t}\n\t\t\tthrow new IllegalStateException();\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Ingredient parse(JsonContext context, JsonObject json) {\n\t\tPartType ct = PartType.valueOf(json.get(\"part\").getAsString());\n\t\treturn new IngredientPart.Impl(ct);\n\t}\n\n\tprivate static class Impl extends Ingredient {\n\n\t\tImpl(PartType type) {\n\t\t\tsuper(CraftingPartRecipes.getCraftingPartList().stream().map(type::getStack).toArray(ItemStack[]::new));\n\t\t}\n\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/CustomBlockRenderer.java",
    "content": "/*\npackage logisticspipes.renderer;\n\nimport java.util.Arrays;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.renderer.RenderBlocks;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.world.IBlockAccess;\n\npublic final class CustomBlockRenderer {\n\n\tpublic static CustomBlockRenderer INSTANCE = new CustomBlockRenderer();\n\tprotected RenderBlocks renderBlocks = new RenderBlocks();\n\n\tpublic static class RenderInfo {\n\n\t\tpublic double minX;\n\t\tpublic double minY;\n\t\tpublic double minZ;\n\t\tpublic double maxX;\n\t\tpublic double maxY;\n\t\tpublic double maxZ;\n\t\tpublic Block baseBlock = Blocks.sand;\n\t\tpublic TextureAtlasSprite texture = null;\n\t\tpublic TextureAtlasSprite[] textureArray = null;\n\t\tpublic boolean[] renderSide = new boolean[6];\n\t\tpublic float light = -1f;\n\t\tpublic int brightness = -1;\n\n\t\tpublic RenderInfo() {\n\t\t\tsetRenderAllSides();\n\t\t}\n\n\t\tpublic RenderInfo(Block template, TextureAtlasSprite[] texture) {\n\t\t\tthis();\n\t\t\tbaseBlock = template;\n\t\t\ttextureArray = texture;\n\t\t}\n\n\t\tpublic RenderInfo(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {\n\t\t\tthis();\n\t\t\tsetBounds(minX, minY, minZ, maxX, maxY, maxZ);\n\t\t}\n\n\t\tpublic float getBlockBrightness(IBlockAccess iblockaccess, int i, int j, int k) {\n\t\t\treturn baseBlock.getMixedBrightnessForBlock(iblockaccess, i, j, k);\n\t\t}\n\n\t\tpublic final void setBounds(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {\n\t\t\tthis.minX = minX;\n\t\t\tthis.minY = minY;\n\t\t\tthis.minZ = minZ;\n\t\t\tthis.maxX = maxX;\n\t\t\tthis.maxY = maxY;\n\t\t\tthis.maxZ = maxZ;\n\t\t}\n\n\t\tpublic final void setRenderSingleSide(int side) {\n\t\t\tArrays.fill(renderSide, false);\n\t\t\trenderSide[side] = true;\n\t\t}\n\n\t\tpublic final void setRenderAllSides() {\n\t\t\tArrays.fill(renderSide, true);\n\t\t}\n\n\t\tpublic void rotate() {\n\t\t\tdouble temp = minX;\n\t\t\tminX = minZ;\n\t\t\tminZ = temp;\n\n\t\t\ttemp = maxX;\n\t\t\tmaxX = maxZ;\n\t\t\tmaxZ = temp;\n\t\t}\n\n\t\tpublic void reverseX() {\n\t\t\tdouble temp = minX;\n\t\t\tminX = 1 - maxX;\n\t\t\tmaxX = 1 - temp;\n\t\t}\n\n\t\tpublic void reverseZ() {\n\t\t\tdouble temp = minZ;\n\t\t\tminZ = 1 - maxZ;\n\t\t\tmaxZ = 1 - temp;\n\t\t}\n\n\t\tpublic TextureAtlasSprite getBlockTextureFromSide(int i) {\n\t\t\tif (texture != null) {\n\t\t\t\treturn texture;\n\t\t\t}\n\n\t\t\tint index = i;\n\n\t\t\tif (textureArray == null || textureArray.length == 0) {\n\t\t\t\treturn baseBlock.getBlockTextureFromSide(index);\n\t\t\t} else {\n\t\t\t\tif (index >= textureArray.length) {\n\t\t\t\t\tindex = 0;\n\t\t\t\t}\n\n\t\t\t\treturn textureArray[index];\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void renderBlock(RenderInfo info, IBlockAccess blockAccess, int x, int y, int z, boolean doLight, boolean doTessellating) {\n\t\trenderBlock(info, blockAccess, x, y, z, x, y, z, doLight, doTessellating);\n\t}\n\n\tpublic void renderBlock(RenderInfo info, IBlockAccess blockAccess, double x, double y, double z, int lightX, int lightY, int lightZ, boolean doLight, boolean doTessellating) {\n\t\tfloat lightBottom = 0.5F;\n\t\tfloat lightTop = 1.0F;\n\t\tfloat lightEastWest = 0.8F;\n\t\tfloat lightNorthSouth = 0.6F;\n\n\t\tTessellator tessellator = Tessellator.instance;\n\n\t\tboolean realDoLight = doLight;\n\n\t\tif (blockAccess == null) {\n\t\t\trealDoLight = false;\n\t\t}\n\n\t\t// TODO: needs to cancel the test because the variable is now private... May need to\n\t\t// duplicate the tessellator code.\n\t\t//if (doTessellating && !tessellator.isDrawing)\n\t\ttessellator.startDrawingQuads();\n\n\t\tfloat light = 0;\n\t\tif (realDoLight) {\n\t\t\tif (info.light < 0) {\n\t\t\t\tlight = info.baseBlock.getMixedBrightnessForBlock(blockAccess, lightX, lightY, lightZ);\n\t\t\t\tlight = light + ((1.0f - light) * 0.4f);\n\t\t\t} else {\n\t\t\t\tlight = info.light;\n\t\t\t}\n\t\t\tint brightness = 0;\n\t\t\tif (info.brightness < 0) {\n\t\t\t\tbrightness = info.baseBlock.getMixedBrightnessForBlock(blockAccess, lightX, lightY, lightZ);\n\t\t\t} else {\n\t\t\t\tbrightness = info.brightness;\n\t\t\t}\n\t\t\ttessellator.setBrightness(brightness);\n\t\t\ttessellator.setColorOpaque_F(lightBottom * light, lightBottom * light, lightBottom * light);\n\t\t} else {\n\t\t\t//\t\t\ttessellator.setColorOpaque_F(1.0F, 1.0F, 1.0F);\n\t\t\tif (info.brightness >= 0) {\n\t\t\t\ttessellator.setBrightness(info.brightness);\n\t\t\t}\n\t\t}\n\n\t\trenderBlocks.setRenderBounds(info.minX, info.minY, info.minZ, info.maxX, info.maxY, info.maxZ);\n\n\t\tif (info.renderSide[0]) {\n\t\t\trenderBlocks.renderFaceYNeg(info.baseBlock, x, y, z, info.getBlockTextureFromSide(0));\n\t\t}\n\n\t\tif (realDoLight) {\n\t\t\ttessellator.setColorOpaque_F(lightTop * light, lightTop * light, lightTop * light);\n\t\t}\n\n\t\tif (info.renderSide[1]) {\n\t\t\trenderBlocks.renderFaceYPos(info.baseBlock, x, y, z, info.getBlockTextureFromSide(1));\n\t\t}\n\n\t\tif (realDoLight) {\n\t\t\ttessellator.setColorOpaque_F(lightEastWest * light, lightEastWest * light, lightEastWest * light);\n\t\t}\n\n\t\tif (info.renderSide[2]) {\n\t\t\trenderBlocks.renderFaceZNeg(info.baseBlock, x, y, z, info.getBlockTextureFromSide(2));\n\t\t}\n\n\t\tif (realDoLight) {\n\t\t\ttessellator.setColorOpaque_F(lightEastWest * light, lightEastWest * light, lightEastWest * light);\n\t\t}\n\n\t\tif (info.renderSide[3]) {\n\t\t\trenderBlocks.renderFaceZPos(info.baseBlock, x, y, z, info.getBlockTextureFromSide(3));\n\t\t}\n\n\t\tif (realDoLight) {\n\t\t\ttessellator.setColorOpaque_F(lightNorthSouth * light, lightNorthSouth * light, lightNorthSouth * light);\n\t\t}\n\n\t\tif (info.renderSide[4]) {\n\t\t\trenderBlocks.renderFaceXNeg(info.baseBlock, x, y, z, info.getBlockTextureFromSide(4));\n\t\t}\n\n\t\tif (realDoLight) {\n\t\t\ttessellator.setColorOpaque_F(lightNorthSouth * light, lightNorthSouth * light, lightNorthSouth * light);\n\t\t}\n\n\t\tif (info.renderSide[5]) {\n\t\t\trenderBlocks.renderFaceXPos(info.baseBlock, x, y, z, info.getBlockTextureFromSide(5));\n\t\t}\n\n\t\t// TODO: needs to cancel the test because the variable is now private... May need to\n\t\t// duplicate the tessellator code.\n\t\t//if (doTessellating && tessellator.isDrawing)\n\t\ttessellator.draw();\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/FluidContainerRenderer.java",
    "content": "package logisticspipes.renderer;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.IBakedModel;\nimport net.minecraft.client.renderer.block.model.ItemCameraTransforms;\nimport net.minecraft.client.renderer.block.model.ItemOverrideList;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.client.resources.IResourceManager;\nimport net.minecraft.entity.EntityLivingBase;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.model.BakedItemModel;\nimport net.minecraftforge.client.model.ICustomModelLoader;\nimport net.minecraftforge.client.model.IModel;\nimport net.minecraftforge.client.model.ItemLayerModel;\nimport net.minecraftforge.client.model.ItemTextureQuadConverter;\nimport net.minecraftforge.client.model.PerspectiveMapWrapper;\nimport net.minecraftforge.client.model.SimpleModelState;\nimport net.minecraftforge.common.model.IModelState;\nimport net.minecraftforge.common.model.TRSRTransformation;\nimport net.minecraftforge.fluids.Fluid;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableMap;\nimport com.google.common.collect.Maps;\n\nimport logisticspipes.utils.FluidIdentifier;\n\n@SideOnly(Side.CLIENT)\npublic class FluidContainerRenderer implements IModel {\n\n\tpublic static class FluidContainerRendererModelLoader implements ICustomModelLoader {\n\n\t\t@Override\n\t\tpublic boolean accepts(@Nonnull ResourceLocation modelLocation) {\n\t\t\treturn modelLocation.getNamespace().equals(\"logisticspipes\") && modelLocation.getPath().equals(\"models/item/fluid_container\");\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic IModel loadModel(@Nonnull ResourceLocation modelLocation) {\n\t\t\treturn new FluidContainerRenderer();\n\t\t}\n\n\t\t@Override\n\t\tpublic void onResourceManagerReload(@Nonnull IResourceManager resourceManager) {\n\n\t\t}\n\t}\n\n\tprivate static final ResourceLocation STENCIL = new ResourceLocation(\"logisticspipes:items/liquids/stencil\");\n\tprivate static final ResourceLocation EMPTY = new ResourceLocation(\"logisticspipes:items/liquids/empty\");\n\n\t@Nonnull\n\t@Override\n\tpublic Collection<ResourceLocation> getTextures() {\n\t\treturn ImmutableList.of(EMPTY, STENCIL);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBakedModel bake(@Nonnull IModelState state, @Nonnull VertexFormat format, @Nonnull Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {\n\t\tImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap = PerspectiveMapWrapper.getTransforms(state);\n\n\t\tImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();\n\n\t\tIBakedModel model = (new ItemLayerModel(ImmutableList.of(EMPTY))).bake(state, format, bakedTextureGetter);\n\t\tbuilder.addAll(model.getQuads(null, null, 0));\n\t\tTextureAtlasSprite particleSprite = model.getParticleTexture();\n\n\t\treturn new BakedItemModel(builder.build(), particleSprite, Maps.immutableEnumMap(transformMap), new FluidContainerItemOverrideList(state, format, transformMap, bakedTextureGetter));\n\t}\n\n\tprivate static class FluidContainerItemOverrideList extends ItemOverrideList {\n\n\t\tprivate static final float NORTH_Z = 7.502f / 16f;\n\t\tprivate static final float SOUTH_Z = 8.498f / 16f;\n\n\t\tprivate Map<FluidIdentifier, IBakedModel> cache = new HashMap<>();\n\n\t\tprivate VertexFormat format;\n\t\tprivate ImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap;\n\t\tprivate Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter;\n\n\t\tpublic FluidContainerItemOverrideList(IModelState state, VertexFormat format,\n\t\t\t\tImmutableMap<ItemCameraTransforms.TransformType, TRSRTransformation> transformMap,\n\t\t\t\tFunction<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {\n\t\t\tsuper(ImmutableList.of());\n\t\t\tthis.format = format;\n\t\t\tthis.transformMap = transformMap;\n\t\t\tthis.bakedTextureGetter = bakedTextureGetter;\n\t\t}\n\n\t\t@Override\n\t\t@Nonnull\n\t\tpublic IBakedModel handleItemState(@Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, World world, EntityLivingBase entity) {\n\t\t\tFluidIdentifier fluidIdent = FluidIdentifier.get(stack);\n\t\t\tif (fluidIdent != null) {\n\t\t\t\tif (cache.containsKey(fluidIdent)) {\n\t\t\t\t\treturn cache.get(fluidIdent);\n\t\t\t\t}\n\n\t\t\t\tFluid fluid = fluidIdent.getFluid();\n\n\t\t\t\tResourceLocation fluidSprite = fluid.getStill(fluidIdent.makeFluidStack(1000));\n\n\t\t\t\tTRSRTransformation transform = new SimpleModelState(transformMap).apply(Optional.empty())\n\t\t\t\t\t\t.orElse(TRSRTransformation.identity());\n\t\t\t\tImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();\n\n\t\t\t\tbuilder.addAll(\n\t\t\t\t\t\tItemTextureQuadConverter\n\t\t\t\t\t\t\t\t.convertTexture(format, transform, this.bakedTextureGetter.apply(STENCIL), this.bakedTextureGetter.apply(fluidSprite),\n\t\t\t\t\t\t\t\t\t\tNORTH_Z, EnumFacing.NORTH, fluid.getColor()));\n\t\t\t\tbuilder.addAll(\n\t\t\t\t\t\tItemTextureQuadConverter\n\t\t\t\t\t\t\t\t.convertTexture(format, transform, this.bakedTextureGetter.apply(STENCIL), this.bakedTextureGetter.apply(fluidSprite),\n\t\t\t\t\t\t\t\t\t\tSOUTH_Z, EnumFacing.SOUTH, fluid.getColor()));\n\n\t\t\t\tbuilder.addAll(originalModel.getQuads(null, null, 0));\n\n\t\t\t\tBakedItemModel override = new BakedItemModel(builder.build(), bakedTextureGetter.apply(fluidSprite), Maps.immutableEnumMap(transformMap),\n\t\t\t\t\t\tItemOverrideList.NONE);\n\t\t\t\tcache.put(fluidIdent, override);\n\t\t\t\treturn override;\n\t\t\t}\n\t\t\treturn originalModel;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/FluidRenderer.java",
    "content": "/*\npackage logisticspipes.renderer;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport logisticspipes.renderer.CustomBlockRenderer.RenderInfo;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.GLAllocation;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fluids.Fluid;\nimport net.minecraftforge.fluids.FluidStack;\n\nimport org.lwjgl.opengl.GL11;\n\npublic final class FluidRenderer {\n\n\tpublic static final int DISPLAY_STAGES = 100;\n\t//private static final ResourceLocation BLOCK_TEXTURE = TextureMap.locationBlocksTexture;\n\tprivate static Map<Fluid, int[]> flowingRenderCache = new HashMap<>();\n\tprivate static Map<Fluid, int[]> stillRenderCache = new HashMap<>();\n\tprivate static final RenderInfo liquidBlock = new RenderInfo();\n\n\t/**\n\t * Deactivate default constructor\n\t * /\n\tprivate FluidRenderer() {\n\n\t}\n\n\tpublic static TextureAtlasSprite getFluidTexture(FluidStack fluidStack, boolean flowing) {\n\t\tif (fluidStack == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn FluidRenderer.getFluidTexture(fluidStack.getFluid(), flowing);\n\t}\n\n\tpublic static TextureAtlasSprite getFluidTexture(Fluid fluid, boolean flowing) {\n\t\tif (fluid == null) {\n\t\t\treturn null;\n\t\t}\n\t\tTextureAtlasSprite icon = flowing ? fluid.getFlowingIcon() : fluid.getStillIcon();\n\t\tif (icon == null) {\n\t\t\ticon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE)).getAtlasSprite(\"missingno\");\n\t\t}\n\t\treturn icon;\n\t}\n\n\tpublic static ResourceLocation getFluidSheet(FluidStack liquid) {\n\t\tif (liquid == null) {\n\t\t\treturn FluidRenderer.BLOCK_TEXTURE;\n\t\t}\n\t\treturn FluidRenderer.getFluidSheet(liquid.getFluid());\n\t}\n\n\tpublic static ResourceLocation getFluidSheet(Fluid liquid) {\n\t\treturn FluidRenderer.BLOCK_TEXTURE;\n\t}\n\n\tpublic static void setColorForFluidStack(FluidStack fluidstack) {\n\t\tif (fluidstack == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tint color = fluidstack.getFluid().getColor(fluidstack);\n\t\tFluidRenderer.setGLColorFromInt(color);\n\t}\n\n\tprivate static void setGLColorFromInt(int color) {\n\t\tfloat red = (color >> 16 & 255) / 255.0F;\n\t\tfloat green = (color >> 8 & 255) / 255.0F;\n\t\tfloat blue = (color & 255) / 255.0F;\n\t\tGL11.glColor4f(red, green, blue, 1.0F);\n\t}\n\n\tpublic static int[] getFluidDisplayLists(FluidStack fluidStack, World world, boolean flowing) {\n\t\tif (fluidStack == null) {\n\t\t\treturn null;\n\t\t}\n\t\tFluid fluid = fluidStack.getFluid();\n\t\tif (fluid == null) {\n\t\t\treturn null;\n\t\t}\n\t\tMap<Fluid, int[]> cache = flowing ? FluidRenderer.flowingRenderCache : FluidRenderer.stillRenderCache;\n\t\tint[] diplayLists = cache.get(fluid);\n\t\tif (diplayLists != null) {\n\t\t\treturn diplayLists;\n\t\t}\n\n\t\tdiplayLists = new int[FluidRenderer.DISPLAY_STAGES];\n\n\t\tif (fluid.getBlock() != null) {\n\t\t\tFluidRenderer.liquidBlock.baseBlock = fluid.getBlock();\n\t\t\tFluidRenderer.liquidBlock.texture = FluidRenderer.getFluidTexture(fluidStack, flowing);\n\t\t} else {\n\t\t\tFluidRenderer.liquidBlock.baseBlock = Blocks.water;\n\t\t\tFluidRenderer.liquidBlock.texture = FluidRenderer.getFluidTexture(fluidStack, flowing);\n\t\t}\n\n\t\tcache.put(fluid, diplayLists);\n\n\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\tGL11.glDisable(GL11.GL_CULL_FACE);\n\n\t\tfor (int s = 0; s < FluidRenderer.DISPLAY_STAGES; ++s) {\n\t\t\tdiplayLists[s] = GLAllocation.generateDisplayLists(1);\n\t\t\tGL11.glNewList(diplayLists[s], 4864 /*GL_COMPILE* /);\n\n\t\t\tFluidRenderer.liquidBlock.minX = 0.01f;\n\t\t\tFluidRenderer.liquidBlock.minY = 0;\n\t\t\tFluidRenderer.liquidBlock.minZ = 0.01f;\n\n\t\t\tFluidRenderer.liquidBlock.maxX = 0.99f;\n\t\t\tFluidRenderer.liquidBlock.maxY = (float) s / (float) FluidRenderer.DISPLAY_STAGES;\n\t\t\tFluidRenderer.liquidBlock.maxZ = 0.99f;\n\n\t\t\tCustomBlockRenderer.INSTANCE.renderBlock(FluidRenderer.liquidBlock, world, 0, 0, 0, false, true);\n\n\t\t\tGL11.glEndList();\n\t\t}\n\n\t\tGL11.glColor4f(1, 1, 1, 1);\n\t\tGL11.glEnable(GL11.GL_CULL_FACE);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\n\t\treturn diplayLists;\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/GuiOverlay.java",
    "content": "package logisticspipes.renderer;\n\nimport java.lang.reflect.Field;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.inventory.Slot;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.SlotFinderNumberPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.gui.SimpleGraphics;\n\npublic class GuiOverlay {\n\n\t@Getter\n\tprivate static final GuiOverlay instance = new GuiOverlay();\n\n\tprivate int oldX;\n\tprivate int oldY;\n\tprivate boolean hasBeenSaved;\n\tprivate boolean clicked;\n\tprivate Field fX;\n\tprivate Field fY;\n\n\t@Setter\n\tprivate int targetPosX;\n\t@Setter\n\tprivate int targetPosY;\n\t@Setter\n\tprivate int targetPosZ;\n\t@Setter\n\tprivate int pipePosX;\n\t@Setter\n\tprivate int pipePosY;\n\t@Setter\n\tprivate int pipePosZ;\n\t@Setter\n\tprivate ModulePositionType positionType;\n\t@Setter\n\tprivate int positionInt;\n\t@Setter\n\tprivate int slot;\n\t@Setter\n\tprivate boolean isOverlaySlotActive;\n\n\tprivate GuiOverlay() {\n\t\ttry {\n\t\t\tfX = Mouse.class.getDeclaredField(\"x\");\n\t\t\tfY = Mouse.class.getDeclaredField(\"y\");\n\t\t\tfX.setAccessible(true);\n\t\t\tfY.setAccessible(true);\n\t\t} catch (Exception e) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic boolean isCompatibleGui() {\n\t\tFMLClientHandler clientHandler = FMLClientHandler.instance();\n\t\tif (clientHandler == null) return false;\n\n\t\tMinecraft client = clientHandler.getClient();\n\t\tif (client == null) return false;\n\n\t\treturn client.currentScreen instanceof GuiContainer;\n\t}\n\n\tpublic void preRender() {\n\t\tif (isOverlaySlotActive) {\n\n\t\t\t// Save Mouse Pos\n\t\t\toldX = Mouse.getX();\n\t\t\toldY = Mouse.getY();\n\n\t\t\t// Set Pos 0,0\n\t\t\ttry {\n\t\t\t\tfX.set(null, 0);\n\t\t\t\tfY.set(null, 0);\n\t\t\t\thasBeenSaved = true;\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\twhile (Mouse.next()) {\n\t\t\t\tif (Mouse.getEventButton() == 0 && Mouse.getEventButtonState()) {\n\t\t\t\t\tclicked = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void renderOverGui() {\n\t\tif (hasBeenSaved) {\n\t\t\thasBeenSaved = false;\n\n\t\t\t// Restore Mouse Pos\n\t\t\ttry {\n\t\t\t\tfX.set(null, oldX);\n\t\t\t\tfY.set(null, oldY);\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (isOverlaySlotActive) {\n\t\t\tMinecraft client = FMLClientHandler.instance().getClient();\n\t\t\tGuiContainer gui = (GuiContainer) client.currentScreen;\n\n\t\t\tint guiTop = gui.getGuiTop();\n\t\t\tint guiLeft = gui.getGuiLeft();\n\n\t\t\tint x = oldX * gui.width / client.displayWidth;\n\t\t\tint y = gui.height - oldY * gui.height / client.displayHeight - 1;\n\n\t\t\tfor (Slot slot : gui.inventorySlots.inventorySlots) {\n\t\t\t\tif (isMouseOverSlot(gui, slot, x, y)) {\n\t\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\tGL11.glTranslated(guiLeft, guiTop, 0);\n\t\t\t\t\tint k1 = slot.xPos;\n\t\t\t\t\tint i1 = slot.yPos;\n\t\t\t\t\tSimpleGraphics.drawGradientRect(k1, i1, k1 + 16, i1 + 16, 0xa0ff0000, 0xa0ff0000, 0.0);\n\t\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\tif (clicked) {\n\t\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(SlotFinderNumberPacket.class)\n\t\t\t\t\t\t\t\t.setInventorySlot(slot.slotNumber)\n\t\t\t\t\t\t\t\t.setSlot(this.slot)\n\t\t\t\t\t\t\t\t.setPipePosX(pipePosX)\n\t\t\t\t\t\t\t\t.setPipePosY(pipePosY)\n\t\t\t\t\t\t\t\t.setPipePosZ(pipePosZ)\n\t\t\t\t\t\t\t\t.setType(positionType)\n\t\t\t\t\t\t\t\t.setPositionInt(positionInt)\n\t\t\t\t\t\t\t\t.setPosX(targetPosX)\n\t\t\t\t\t\t\t\t.setPosY(targetPosY)\n\t\t\t\t\t\t\t\t.setPosZ(targetPosZ));\n\t\t\t\t\t\tclicked = false;\n\t\t\t\t\t\tclient.player.closeScreen();\n\t\t\t\t\t\tisOverlaySlotActive = false;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclicked = false;\n\t\t}\n\t}\n\n\tprivate boolean isMouseOverSlot(GuiContainer gui, Slot slot, int mouseX, int mouseY) {\n\t\treturn isPointInRegion(gui, slot.xPos, slot.yPos, 16, 16, mouseX, mouseY);\n\t}\n\n\tprivate boolean isPointInRegion(GuiContainer gui, int x, int y, int width, int height, int pointX, int pointY) {\n\t\tint x0 = gui.getGuiLeft();\n\t\tint y0 = gui.getGuiTop();\n\t\tpointX -= x0;\n\t\tpointY -= y0;\n\t\treturn pointX >= x - 1 && pointX < x + width + 1 && pointY >= y - 1 && pointY < y + height + 1;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/IIconProvider.java",
    "content": "package logisticspipes.renderer;\n\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic interface IIconProvider {\n\n\t@SideOnly(Side.CLIENT)\n\tTextureAtlasSprite getIcon(int iconIndex);\n\n\tvoid registerIcons(Object textureMap);\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/LogisticsHUDRenderer.java",
    "content": "package logisticspipes.renderer;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.EnumSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.ScaledResolution;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.RayTraceResult;\n\nimport net.minecraftforge.client.GuiIngameForge;\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.api.IHUDArmor;\nimport logisticspipes.config.Configs;\nimport logisticspipes.hud.HUDConfig;\nimport logisticspipes.interfaces.IDebugHUDProvider;\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.interfaces.IHeadUpDisplayBlockRendererProvider;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.LaserData;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\nimport logisticspipes.utils.math.Vector3d;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class LogisticsHUDRenderer {\n\n\tpublic IDebugHUDProvider debugHUD = null;\n\n\tprivate LinkedList<IHeadUpDisplayRendererProvider> list = new LinkedList<>();\n\tprivate double lastXPos = 0;\n\tprivate double lastYPos = 0;\n\tprivate double lastZPos = 0;\n\n\tprivate int progress = 0;\n\tprivate long last = 0;\n\n\tprivate ArrayList<IHeadUpDisplayBlockRendererProvider> providers = new ArrayList<>();\n\n\tprivate List<LaserData> lasers = new ArrayList<>();\n\n\tprivate static LogisticsHUDRenderer renderer = null;\n\n\tpublic void add(IHeadUpDisplayBlockRendererProvider provider) {\n\t\tIHeadUpDisplayBlockRendererProvider toRemove = null;\n\t\tfor (IHeadUpDisplayBlockRendererProvider listedProvider : providers) {\n\t\t\tif (listedProvider.getX() == provider.getX() && listedProvider.getY() == provider.getY() && listedProvider.getZ() == provider.getZ()) {\n\t\t\t\ttoRemove = listedProvider;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (toRemove != null) {\n\t\t\tproviders.remove(toRemove);\n\t\t}\n\t\tproviders.add(provider);\n\t}\n\n\tpublic void remove(IHeadUpDisplayBlockRendererProvider provider) {\n\t\tproviders.remove(provider);\n\t}\n\n\tpublic void clear() {\n\t\tproviders.clear();\n\t\tLogisticsHUDRenderer.instance().clearList(false);\n\t}\n\n\tprivate void clearList(boolean flag) {\n\t\tif (flag) {\n\t\t\tlist.forEach(IHeadUpDisplayRendererProvider::stopWatching);\n\t\t}\n\t\tlist.clear();\n\t}\n\n\tprivate void refreshList(double x, double y, double z) {\n\t\tArrayList<Pair<Double, IHeadUpDisplayRendererProvider>> newList = new ArrayList<>();\n\t\tfor (IRouter router : SimpleServiceLocator.routerManager.getRouters()) {\n\t\t\tif (router == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tCoreRoutedPipe pipe = router.getPipe();\n\t\t\tif (!(pipe instanceof IHeadUpDisplayRendererProvider)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (pipe.getWorld().provider.getDimension() == FMLClientHandler.instance().getClient().world.provider.getDimension()) {\n\t\t\t\tdouble dis = Math.hypot(pipe.getX() - x + 0.5, Math.hypot(pipe.getY() - y + 0.5, pipe.getZ() - z + 0.5));\n\t\t\t\tif (dis < Configs.LOGISTICS_HUD_RENDER_DISTANCE && dis > 0.75) {\n\t\t\t\t\tnewList.add(new Pair<>(dis, (IHeadUpDisplayRendererProvider) pipe));\n\t\t\t\t\tif (!list.contains(pipe)) {\n\t\t\t\t\t\t((IHeadUpDisplayRendererProvider) pipe).startWatching();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tList<IHeadUpDisplayBlockRendererProvider> remove = new ArrayList<>();\n\t\tproviders.stream().filter(provider -> provider.getWorldForHUD().provider.getDimension() == FMLClientHandler.instance().getClient().world.provider.getDimension())\n\t\t\t\t.forEach(provider -> {\n\t\t\t\t\tdouble dis = Math.hypot(provider.getX() - x + 0.5, Math.hypot(provider.getY() - y + 0.5, provider.getZ() - z + 0.5));\n\t\t\t\t\tif (dis < Configs.LOGISTICS_HUD_RENDER_DISTANCE && dis > 0.75 && !provider.isHUDInvalid() && provider.isHUDExistent()) {\n\t\t\t\t\t\tnewList.add(new Pair<>(dis, provider));\n\t\t\t\t\t\tif (!list.contains(provider)) {\n\t\t\t\t\t\t\tprovider.startWatching();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (provider.isHUDInvalid() || !provider.isHUDExistent()) {\n\t\t\t\t\t\tremove.add(provider);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\tfor (IHeadUpDisplayBlockRendererProvider provider : remove) {\n\t\t\tproviders.remove(provider);\n\t\t}\n\n\t\tif (newList.size() < 1) {\n\t\t\tclearList(true);\n\t\t\treturn;\n\t\t}\n\t\tnewList.sort(Comparator.comparing(Pair::getValue1));\n\t\tfor (IHeadUpDisplayRendererProvider part : list) {\n\t\t\tboolean contains = false;\n\t\t\tfor (Pair<Double, IHeadUpDisplayRendererProvider> inpart : newList) {\n\t\t\t\tif (inpart.getValue2().equals(part)) {\n\t\t\t\t\tcontains = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!contains) {\n\t\t\t\tpart.stopWatching();\n\t\t\t}\n\t\t}\n\t\tclearList(false);\n\t\tfor (Pair<Double, IHeadUpDisplayRendererProvider> part : newList) {\n\t\t\tlist.addLast(part.getValue2());\n\t\t}\n\t}\n\n\tprivate boolean playerWearsHUD() {\n\t\treturn FMLClientHandler.instance().getClient().player != null && FMLClientHandler.instance().getClient().player.inventory != null && FMLClientHandler.instance().getClient().player.inventory.armorInventory != null && !FMLClientHandler.instance().getClient().player.inventory.armorInventory.get(3).isEmpty()\n\t\t\t\t&& checkItemStackForHUD(FMLClientHandler.instance().getClient().player.inventory.armorInventory.get(3));\n\t}\n\n\tprivate boolean checkItemStackForHUD(@Nonnull ItemStack stack) {\n\t\tif (stack.getItem() instanceof IHUDArmor) {\n\t\t\treturn ((IHUDArmor) stack.getItem()).isEnabled(stack);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean displayCross = false;\n\n\t//TODO: only load this once, rather than twice\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"textures/gui/icons.png\");\n\n\tpublic void renderPlayerDisplay(long renderTicks) {\n\t\tif (!displayRenderer()) {\n\t\t\treturn;\n\t\t}\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tif (displayHUD() && displayCross) {\n\t\t\tScaledResolution res = new ScaledResolution(mc);\n\t\t\tint width = res.getScaledWidth();\n\t\t\tint height = res.getScaledHeight();\n\t\t\tif (GuiIngameForge.renderCrosshairs && mc.ingameGUI != null) {\n\t\t\t\tmc.renderEngine.bindTexture(LogisticsHUDRenderer.TEXTURE);\n\t\t\t\tGL11.glColor4d(0.0D, 0.0D, 0.0D, 1.0D);\n\t\t\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\t\t\tmc.ingameGUI.drawTexturedModalRect(width / 2 - 7, height / 2 - 7, 0, 0, 16, 16);\n\t\t\t}\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic void renderWorldRelative(long renderTicks, float partialTick) {\n\t\tif (!displayRenderer()) {\n\t\t\treturn;\n\t\t}\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tEntityPlayer player = mc.player;\n\t\tif (list.size() == 0 || Math.hypot(lastXPos - player.posX, Math.hypot(lastYPos - player.posY, lastZPos - player.posZ)) > 0.5 || (renderTicks % 10 == 0 && (lastXPos != player.posX || lastYPos != player.posY || lastZPos != player.posZ)) || renderTicks % 600 == 0) {\n\t\t\trefreshList(player.posX, player.posY, player.posZ);\n\t\t\tlastXPos = player.posX;\n\t\t\tlastYPos = player.posY;\n\t\t\tlastZPos = player.posZ;\n\t\t}\n\t\tboolean cursorHandled = false;\n\t\tdisplayCross = false;\n\t\tIHUDConfig config;\n\t\tif (debugHUD == null) {\n\t\t\tconfig = new HUDConfig(mc.player.inventory.armorInventory.get(3));\n\t\t} else {\n\t\t\tconfig = new IHUDConfig() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isHUDSatellite() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isHUDProvider() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isHUDPowerLevel() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isHUDInvSysCon() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isHUDCrafting() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean isChassisHUD() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void setChassisHUD(boolean state) {}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void setHUDCrafting(boolean state) {}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void setHUDInvSysCon(boolean state) {}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void setHUDPowerJunction(boolean state) {}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void setHUDProvider(boolean state) {}\n\n\t\t\t\t@Override\n\t\t\t\tpublic void setHUDSatellite(boolean state) {}\n\t\t\t};\n\t\t}\n\t\tIHeadUpDisplayRendererProvider thisIsLast = null;\n\t\tList<IHeadUpDisplayRendererProvider> toUse = list;\n\t\tif (debugHUD != null) {\n\t\t\ttoUse = debugHUD.getHUDs();\n\t\t}\n\n\t\tfor (IHeadUpDisplayRendererProvider renderer : toUse) {\n\t\t\tif (renderer.getRenderer() == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (renderer.getRenderer().display(config)) {\n\t\t\t\tGL11.glPushMatrix();\n\t\t\t\tif (!cursorHandled) {\n\t\t\t\t\tdouble x = renderer.getX() + 0.5 - player.posX;\n\t\t\t\t\tdouble y = renderer.getY() + 0.5 - player.posY;\n\t\t\t\t\tdouble z = renderer.getZ() + 0.5 - player.posZ;\n\t\t\t\t\tif (Math.hypot(x, Math.hypot(y, z)) < 0.75 || (renderer instanceof IHeadUpDisplayBlockRendererProvider && (((IHeadUpDisplayBlockRendererProvider) renderer).isHUDInvalid() || !((IHeadUpDisplayBlockRendererProvider) renderer).isHUDExistent()))) {\n\t\t\t\t\t\trefreshList(player.posX, player.posY, player.posZ);\n\t\t\t\t\t\tGL11.glPopMatrix();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tint[] pos = getCursor(renderer);\n\t\t\t\t\tif (pos.length == 2) {\n\t\t\t\t\t\tif (renderer.getRenderer().cursorOnWindow(pos[0], pos[1])) {\n\t\t\t\t\t\t\trenderer.getRenderer().handleCursor(pos[0], pos[1]);\n\t\t\t\t\t\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { //if(FMLClientHandler.instance().getClient().player.isSneaking()) {\n\t\t\t\t\t\t\t\tthisIsLast = renderer;\n\t\t\t\t\t\t\t\tdisplayCross = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcursorHandled = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\t\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\t\t\tif (thisIsLast != renderer) {\n\t\t\t\t\tdisplayOneView(renderer, config, partialTick, false);\n\t\t\t\t}\n\t\t\t\tGL11.glPopMatrix();\n\t\t\t}\n\t\t}\n\t\tif (thisIsLast != null) {\n\t\t\tGL11.glPushMatrix();\n\t\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\tdisplayOneView(thisIsLast, config, partialTick, true);\n\t\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\tGL11.glPopMatrix();\n\t\t}\n\n\t\tGL11.glPushMatrix();\n\t\tRayTraceResult box = mc.objectMouseOver;\n\t\tif (box != null && box.typeOfHit == RayTraceResult.Type.BLOCK) {\n\t\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {\n\t\t\t\tprogress = Math.min(progress + (2 * Math.max(1, (int) Math.floor((System.currentTimeMillis() - last) / 50.0D))), 100);\n\t\t\t} else {\n\t\t\t\tprogress = Math.max(progress - (2 * Math.max(1, (int) Math.floor((System.currentTimeMillis() - last) / 50.0D))), 0);\n\t\t\t}\n\t\t\tif (progress != 0) {\n\t\t\t\tList<String> textData = SimpleServiceLocator.neiProxy.getInfoForPosition(player.world, player, box);\n\n\t\t\t\t//TileEntity tile = new DoubleCoordinates(box.blockX, box.blockY, box.blockZ).getTileEntity(DimensionManager.getWorld(0));\n\t\t\t\t//Insert debug code here\n\n\t\t\t\tif (!textData.isEmpty()) {\n\t\t\t\t\tdouble xCoord = box.getBlockPos().getX() + 0.5D;\n\t\t\t\t\tdouble yCoord = box.getBlockPos().getY() + 0.5D;\n\t\t\t\t\tdouble zCoord = box.getBlockPos().getZ() + 0.5D;\n\n\t\t\t\t\tdouble x = xCoord - player.prevPosX - ((player.posX - player.prevPosX) * partialTick);\n\t\t\t\t\tdouble y = yCoord - player.prevPosY - ((player.posY - player.prevPosY) * partialTick);\n\t\t\t\t\tdouble z = zCoord - player.prevPosZ - ((player.posZ - player.prevPosZ) * partialTick);\n\n\t\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\n\t\t\t\t\tGL11.glTranslatef((float) x, (float) y, (float) z);\n\t\t\t\t\tGL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);\n\t\t\t\t\tGL11.glRotatef(getAngle(z, x) + 110F, 0.0F, 0.0F, 1.0F);\n\t\t\t\t\tGL11.glRotatef((-1) * getAngle(Math.hypot(x + 0.8, z + 0.8), y + 0.5) + 180, 1.0F, 0.0F, 0.0F);\n\n\t\t\t\t\tdouble dProgress = progress / 100D;\n\n\t\t\t\t\tGL11.glTranslated(0.4D * dProgress + 0.6D, -0.2D * dProgress - 0.6D, -0.0D);\n\n\t\t\t\t\tGL11.glScalef(0.01F, 0.01F, 1F);\n\n\t\t\t\t\tint heigth = Math.max(32, 10 * textData.size() + 15);\n\t\t\t\t\tint width = 0;\n\t\t\t\t\tfor (String s : textData) {\n\t\t\t\t\t\twidth = Math.max(width, mc.fontRenderer.getStringWidth(s) + 22);\n\t\t\t\t\t}\n\t\t\t\t\twidth = Math.max(32, width + 15);\n\n\t\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 96);\n\t\t\t\t\tGuiGraphics.drawGuiBackGround(mc, (int) ((-0.5 * (width - 32)) * dProgress) - 16, (int) ((-0.5 * (heigth - 32)) * dProgress) - 16, (int) ((0.5 * (width - 32)) * dProgress) + 16, (int) ((0.5 * (heigth - 32)) * dProgress) + 16, 0, false);\n\t\t\t\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 127);\n\n\t\t\t\t\tif (progress == 100) {\n\t\t\t\t\t\tGL11.glTranslated((int) ((-0.5 * (width - 32)) * dProgress) - 16, (int) ((-0.5 * (heigth - 32)) * dProgress) - 16, -0.0001D);\n\t\t\t\t\t\tfor (int i = 0; i < textData.size(); i++) {\n\t\t\t\t\t\t\tmc.fontRenderer.drawString(textData.get(i), 28, 8 + i * 10, 0x000000);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tItemStack stack = SimpleServiceLocator.neiProxy.getItemForPosition(player.world, player, box);\n\n\t\t\t\t\t\tif (!stack.isEmpty()) {\n\t\t\t\t\t\t\tfloat scaleX = 1.5F * 0.8F;\n\t\t\t\t\t\t\tfloat scaleY = 1.5F * 0.8F;\n\t\t\t\t\t\t\tfloat scaleZ = -0.0001F;\n\n\t\t\t\t\t\t\tGL11.glScalef(scaleX, scaleY, scaleZ);\n\n\t\t\t\t\t\t\tItemStackRenderer itemStackRenderer = new ItemStackRenderer(5, 6, 0.0F, true, true);\n\t\t\t\t\t\t\titemStackRenderer.setItemstack(stack).setDisplayAmount(DisplayAmount.NEVER);\n\t\t\t\t\t\t\titemStackRenderer.setScaleX(scaleX).setScaleY(scaleY).setScaleZ(scaleZ);\n\n\t\t\t\t\t\t\titemStackRenderer.renderInGui();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {\n\t\t\tprogress = 0;\n\t\t}\n\t\tGL11.glPopMatrix();\n\n\t\t//Render Laser\n\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\tGL11.glDisable(GL11.GL_TEXTURE_2D);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\t//GL11.glEnable(GL11.GL_LIGHTING);\n\t\tfor (LaserData data : lasers) {\n\t\t\tGL11.glPushMatrix();\n\n\t\t\tdouble x = data.getPosX() + 0.5 - player.prevPosX - ((player.posX - player.prevPosX) * partialTick);\n\t\t\tdouble y = data.getPosY() + 0.5 - player.prevPosY - ((player.posY - player.prevPosY) * partialTick);\n\t\t\tdouble z = data.getPosZ() + 0.5 - player.prevPosZ - ((player.posZ - player.prevPosZ) * partialTick);\n\t\t\tGL11.glTranslatef((float) x, (float) y, (float) z);\n\n\t\t\tswitch (data.getDir()) {\n\t\t\t\tcase NORTH:\n\t\t\t\t\tGL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SOUTH:\n\t\t\t\t\tGL11.glRotatef(-90.0F, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\tbreak;\n\t\t\t\tcase EAST:\n\t\t\t\t\tbreak;\n\t\t\t\tcase WEST:\n\t\t\t\t\tGL11.glRotatef(180.0F, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\tbreak;\n\t\t\t\tcase UP:\n\t\t\t\t\tGL11.glRotatef(90.0F, 0.0F, 0.0F, 1.0F);\n\t\t\t\t\tbreak;\n\t\t\t\tcase DOWN:\n\t\t\t\t\tGL11.glRotatef(-90.0F, 0.0F, 0.0F, 1.0F);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tGL11.glScalef(0.01F, 0.01F, 0.01F);\n\n\t\t\tTessellator tessellator = Tessellator.getInstance();\n\n\t\t\tfor (float i = 0; i < 6 * data.getLength(); i++) {\n\t\t\t\tsetColor(i, data.getConnectionType());\n\n\t\t\t\tfloat shift = 100f * i / 6f;\n\t\t\t\tfloat start = 0.0f;\n\t\t\t\tif (data.isStartPipe() && i == 0) {\n\t\t\t\t\tstart = -6.0f;\n\t\t\t\t}\n\n\t\t\t\tBufferBuilder buffer = tessellator.getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\t\t\tbuffer.pos(19.7f + shift, 3.0f, -3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, 3.0f, -3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, 3.0f, 3.0f);\n\t\t\t\tbuffer.pos(19.7f + shift, 3.0f, 3.0f);\n\t\t\t\ttessellator.draw();\n\n\t\t\t\tbuffer = tessellator.getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\t\t\tbuffer.pos(19.7f + shift, -3.0f, 3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, -3.0f, 3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, -3.0f, -3.0f);\n\t\t\t\tbuffer.pos(19.7f + shift, -3.0f, -3.0f);\n\t\t\t\ttessellator.draw();\n\n\t\t\t\tbuffer = tessellator.getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\t\t\tbuffer.pos(19.7f + shift, 3.0f, 3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, 3.0f, 3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, -3.0f, 3.0f);\n\t\t\t\tbuffer.pos(19.7f + shift, -3.0f, 3.0f);\n\t\t\t\ttessellator.draw();\n\n\t\t\t\tbuffer = tessellator.getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\t\t\tbuffer.pos(19.7f + shift, -3.0f, -3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, -3.0f, -3.0f);\n\t\t\t\tbuffer.pos(3.0f + shift + start, 3.0f, -3.0f);\n\t\t\t\tbuffer.pos(19.7f + shift, 3.0f, -3.0f);\n\t\t\t\ttessellator.draw();\n\t\t\t}\n\n\t\t\tif (data.isStartPipe()) {\n\t\t\t\tsetColor(0, data.getConnectionType());\n\t\t\t\tBufferBuilder buffer = tessellator.getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\t\t\tbuffer.pos(-3.0f, 3.0f, 3.0f);\n\t\t\t\tbuffer.pos(-3.0f, 3.0f, -3.0f);\n\t\t\t\tbuffer.pos(-3.0f, -3.0f, -3.0f);\n\t\t\t\tbuffer.pos(-3.0f, -3.0f, 3.0f);\n\t\t\t\ttessellator.draw();\n\t\t\t}\n\n\t\t\tif (data.isFinalPipe()) {\n\t\t\t\tsetColor(6 * data.getLength() - 1, data.getConnectionType());\n\t\t\t\tBufferBuilder buffer = tessellator.getBuffer();\n\t\t\t\tbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\t\t\tbuffer.pos(100.0f * data.getLength() + 3f, 3.0f, -3.0f);\n\t\t\t\tbuffer.pos(100.0f * data.getLength() + 3f, 3.0f, 3.0f);\n\t\t\t\tbuffer.pos(100.0f * data.getLength() + 3f, -3.0f, 3.0f);\n\t\t\t\tbuffer.pos(100.0f * data.getLength() + 3f, -3.0f, -3.0f);\n\t\t\t\ttessellator.draw();\n\t\t\t}\n\n\t\t\tGL11.glPopMatrix();\n\t\t}\n\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\tlast = System.currentTimeMillis();\n\t}\n\n\tprivate void setColor(float i, EnumSet<PipeRoutingConnectionType> flags) {\n\t\tGL11.glColor4f(1.0f, 1.0f, 1.0f, 0.5f);\n\t\tif (!flags.isEmpty()) {\n\t\t\tint k = 0;\n\t\t\tfor (PipeRoutingConnectionType type : PipeRoutingConnectionType.values) {\n\t\t\t\tif (flags.contains(type)) {\n\t\t\t\t\tk++;\n\t\t\t\t}\n\t\t\t\tif (k - 1 == (int) i % flags.size()) {\n\t\t\t\t\tsetColor(type);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void setColor(PipeRoutingConnectionType type) {\n\t\tswitch (type) {\n\t\t\tcase canRouteTo:\n\t\t\t\tGL11.glColor4f(1.0f, 1.0f, 0.0f, 0.5f);\n\t\t\t\tbreak;\n\t\t\tcase canRequestFrom:\n\t\t\t\tGL11.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);\n\t\t\t\tbreak;\n\t\t\tcase canPowerFrom:\n\t\t\t\tGL11.glColor4f(0.0f, 0.0f, 1.0f, 0.5f);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t}\n\t}\n\n\tprivate void displayOneView(IHeadUpDisplayRendererProvider renderer, IHUDConfig config, float partialTick, boolean shifted) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tEntityPlayer player = mc.player;\n\t\tdouble x = renderer.getX() + 0.5 - player.prevPosX - ((player.posX - player.prevPosX) * partialTick);\n\t\tdouble y = renderer.getY() + 0.5 - player.prevPosY - ((player.posY - player.prevPosY) * partialTick);\n\t\tdouble z = renderer.getZ() + 0.5 - player.prevPosZ - ((player.posZ - player.prevPosZ) * partialTick);\n\t\tGL11.glTranslatef((float) x, (float) y, (float) z);\n\t\tGL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);\n\t\tGL11.glRotatef(getAngle(z, x) + 90, 0.0F, 0.0F, 1.0F);\n\t\tGL11.glRotatef((-1) * getAngle(Math.hypot(x, z), y - player.getEyeHeight()) + 180, 1.0F, 0.0F, 0.0F);\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.4F);\n\n\t\tGL11.glScalef(0.01F, 0.01F, 1F);\n\n\t\trenderer.getRenderer().renderHeadUpDisplay(Math.hypot(x, Math.hypot(y, z)), false, shifted, mc, config);\n\t}\n\n\tprivate float getAngle(double x, double y) {\n\t\treturn (float) (Math.atan2(x, y) * 360 / (2 * Math.PI));\n\t}\n\n\tpublic double up(double input) {\n\t\tinput %= 360.0D;\n\t\twhile (input < 0 && !Double.isNaN(input) && !Double.isInfinite(input)) {\n\t\t\tinput += 360;\n\t\t}\n\t\treturn input;\n\t}\n\n\tprivate int[] getCursor(IHeadUpDisplayRendererProvider renderer) {\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tEntityPlayer player = mc.player;\n\n\t\tVector3d playerView = Vector3d.getFromAngles((270 - player.rotationYaw) / 360 * -2 * Math.PI, (player.rotationPitch) / 360 * -2 * Math.PI);\n\t\tVector3d playerPos = new Vector3d();\n\t\tplayerPos.x = player.posX;\n\t\tplayerPos.y = player.posY + player.getEyeHeight();\n\t\tplayerPos.z = player.posZ;\n\n\t\tVector3d panelPos = new Vector3d();\n\t\tpanelPos.x = renderer.getX() + 0.5;\n\t\tpanelPos.y = renderer.getY() + 0.5;\n\t\tpanelPos.z = renderer.getZ() + 0.5;\n\n\t\tVector3d panelView = new Vector3d();\n\t\tpanelView.x = playerPos.x - panelPos.x;\n\t\tpanelView.y = playerPos.y - panelPos.y;\n\t\tpanelView.z = playerPos.z - panelPos.z;\n\n\t\tpanelPos.add(panelView, 0.44D);\n\n\t\tdouble d = panelPos.x * panelView.x + panelPos.y * panelView.y + panelPos.z * panelView.z;\n\t\tdouble c = panelView.x * playerPos.x + panelView.y * playerPos.y + panelView.z * playerPos.z;\n\t\tdouble b = panelView.x * playerView.x + panelView.y * playerView.y + panelView.z * playerView.z;\n\t\tdouble a = (d - c) / b;\n\n\t\tVector3d viewPos = new Vector3d();\n\t\tviewPos.x = playerPos.x + a * playerView.x - panelPos.x;\n\t\tviewPos.y = playerPos.y + a * playerView.y - panelPos.y;\n\t\tviewPos.z = playerPos.z + a * playerView.z - panelPos.z;\n\n\t\tVector3d panelScalVector1 = new Vector3d();\n\n\t\tif (panelView.y == 0) {\n\t\t\tpanelScalVector1.x = 0;\n\t\t\tpanelScalVector1.y = 1;\n\t\t\tpanelScalVector1.z = 0;\n\t\t} else {\n\t\t\tpanelScalVector1 = panelView.getOrtogonal(-panelView.x, null, -panelView.z).makeVectorLength(1.0D);\n\t\t}\n\n\t\tVector3d panelScalVector2 = new Vector3d();\n\n\t\tif (panelView.z == 0) {\n\t\t\tpanelScalVector2.x = 0;\n\t\t\tpanelScalVector2.y = 0;\n\t\t\tpanelScalVector2.z = 1;\n\t\t} else {\n\t\t\tpanelScalVector2 = panelView.getOrtogonal(1.0D, 0.0D, null).makeVectorLength(1.0D);\n\t\t}\n\n\t\tif (panelScalVector1.y == 0) {\n\t\t\treturn new int[] {};\n\t\t}\n\n\t\tdouble cursorY = -viewPos.y / panelScalVector1.y;\n\n\t\tVector3d restViewPos = viewPos.clone();\n\t\trestViewPos.x += cursorY * panelScalVector1.x;\n\t\trestViewPos.y = 0;\n\t\trestViewPos.z += cursorY * panelScalVector1.z;\n\n\t\tdouble cursorX;\n\n\t\tif (panelScalVector2.x == 0) {\n\t\t\tcursorX = restViewPos.z / panelScalVector2.z;\n\t\t} else {\n\t\t\tcursorX = restViewPos.x / panelScalVector2.x;\n\t\t}\n\n\t\tcursorX *= 50 / 0.47D;\n\t\tcursorY *= 50 / 0.47D;\n\t\tif (panelView.z < 0) {\n\t\t\tcursorX *= -1;\n\t\t}\n\t\tif (panelView.y < 0) {\n\t\t\tcursorY *= -1;\n\t\t}\n\n\t\treturn new int[] { (int) cursorX, (int) cursorY };\n\t}\n\n\tpublic boolean displayRenderer() {\n\t\tif (!displayHUD()) {\n\t\t\tif (list.size() != 0) {\n\t\t\t\tclearList(true);\n\t\t\t}\n\t\t}\n\t\treturn displayHUD();\n\t}\n\n\tprivate boolean displayHUD() {\n\t\treturn (playerWearsHUD() || debugHUD != null) && FMLClientHandler.instance().getClient().currentScreen == null && FMLClientHandler.instance().getClient().gameSettings.thirdPersonView == 0 && !FMLClientHandler.instance().getClient().gameSettings.hideGUI;\n\t}\n\n\tpublic void resetLasers() {\n\t\tlasers.clear();\n\t}\n\n\tpublic void setLasers(List<LaserData> newLasers) {\n\t\tlasers.clear();\n\t\tlasers.addAll(newLasers);\n\t}\n\n\tpublic boolean hasLasers() {\n\t\treturn !lasers.isEmpty();\n\t}\n\n\tpublic static LogisticsHUDRenderer instance() {\n\t\tif (LogisticsHUDRenderer.renderer == null) {\n\t\t\tLogisticsHUDRenderer.renderer = new LogisticsHUDRenderer();\n\t\t}\n\t\treturn LogisticsHUDRenderer.renderer;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/LogisticsPipeItemRenderer.java",
    "content": "/*\npackage logisticspipes.renderer;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.newpipe.LogisticsNewPipeItemRenderer;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.RenderBlocks;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\nimport net.minecraftforge.client.IItemRenderer;\n\nimport org.lwjgl.opengl.GL11;\n\npublic class LogisticsPipeItemRenderer implements IItemRenderer {\n\n\tprivate ClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\tprivate LogisticsNewPipeItemRenderer newRenderer;\n\n\tprivate final boolean renderAsBlock;\n\n\tprivate static final float PIPE_MIN_POS = 0.25F;\n\tprivate static final float PIPE_MAX_POS = 0.75F;\n\n\tpublic LogisticsPipeItemRenderer(boolean targeted) {\n\t\tnewRenderer = new LogisticsNewPipeItemRenderer(targeted);\n\t\trenderAsBlock = targeted;\n\t}\n\n\tprivate void renderPipeItem(RenderBlocks render, ItemStack item, float translateX, float translateY, float translateZ) {\n\t\tGL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT); //don't break other mods' guis when holding a pipe\n\t\t//force transparency\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\t// GL11.glBindTexture(GL11.GL_TEXTURE_2D, 10);\n\t\tTessellator tessellator = Tessellator.instance;\n\n\t\tBlock block = LogisticsPipes.LogisticsPipeBlock;\n\t\tTextureAtlasSprite icon = item.getItem().getIconFromDamage(0);\n\n\t\tif (icon == null) {\n\t\t\ticon = ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite(\"missingno\");\n\t\t}\n\n\t\tblock.setBlockBounds(LogisticsPipeItemRenderer.PIPE_MIN_POS, 0.0F, LogisticsPipeItemRenderer.PIPE_MIN_POS, LogisticsPipeItemRenderer.PIPE_MAX_POS, 1.0F, LogisticsPipeItemRenderer.PIPE_MAX_POS);\n\t\t//block.setBlockBounds(PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MIN_POS, PIPE_MAX_POS, PIPE_MAX_POS, PIPE_MAX_POS);\n\t\tblock.setBlockBoundsForItemRender();\n\t\trender.setRenderBoundsFromBlock(block);\n\n\t\tGL11.glTranslatef(translateX, translateY, translateZ);\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, -1F, 0.0F);\n\t\trender.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, icon);\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, 1.0F, 0.0F);\n\t\trender.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, icon);\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, 0.0F, -1F);\n\t\trender.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, icon);\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, 0.0F, 1.0F);\n\t\trender.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, icon);\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(-1F, 0.0F, 0.0F);\n\t\trender.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, icon);\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(1.0F, 0.0F, 0.0F);\n\t\trender.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, icon);\n\t\ttessellator.draw();\n\t\tGL11.glTranslatef(0.5F, 0.5F, 0.5F);\n\t\tblock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tGL11.glPopAttrib(); // nicely leave the rendering how it was\n\t}\n\n\tprivate void renderBlockItem(RenderBlocks render, ItemStack item, float translateX, float translateY, float translateZ) {\n\t\tTessellator tessellator = Tessellator.instance;\n\n\t\tBlock block = LogisticsPipes.LogisticsPipeBlock;\n\n\t\tblock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\t\tblock.setBlockBoundsForItemRender();\n\t\trender.setRenderBoundsFromBlock(block);\n\n\t\tGL11.glTranslatef(translateX, translateY, translateZ);\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, -1F, 0.0F);\n\t\trender.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, LogisticsBlockGenericPipe.getRequestTableTextureFromSide(0));\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, 1.0F, 0.0F);\n\t\trender.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, LogisticsBlockGenericPipe.getRequestTableTextureFromSide(1));\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, 0.0F, -1F);\n\t\trender.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, LogisticsBlockGenericPipe.getRequestTableTextureFromSide(2));\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(0.0F, 0.0F, 1.0F);\n\t\trender.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, LogisticsBlockGenericPipe.getRequestTableTextureFromSide(3));\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(-1F, 0.0F, 0.0F);\n\t\trender.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, LogisticsBlockGenericPipe.getRequestTableTextureFromSide(4));\n\t\ttessellator.draw();\n\t\ttessellator.startDrawingQuads();\n\t\ttessellator.setNormal(1.0F, 0.0F, 0.0F);\n\t\trender.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, LogisticsBlockGenericPipe.getRequestTableTextureFromSide(5));\n\t\ttessellator.draw();\n\t\tGL11.glTranslatef(0.5F, 0.5F, 0.5F);\n\t\tblock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\t}\n\n\tprivate void renderItem(RenderBlocks render, ItemStack item, float translateX, float translateY, float translateZ) {\n\t\tif (renderAsBlock) {\n\t\t\trenderBlockItem(render, item, translateX, translateY, translateZ);\n\t\t} else {\n\t\t\trenderPipeItem(render, item, translateX, translateY, translateZ);\n\t\t}\n\t}\n\n\t/** IItemRenderer implementation **\n\t/\n\n\t@Override\n\tpublic boolean handleRenderType(ItemStack item, ItemRenderType type) {\n\t\tif (config.isUseNewRenderer()) {\n\t\t\treturn newRenderer.handleRenderType(item, type);\n\t\t}\n\t\tswitch (type) {\n\t\t\tcase ENTITY:\n\t\t\t\treturn true;\n\t\t\tcase EQUIPPED:\n\t\t\t\treturn true;\n\t\t\tcase EQUIPPED_FIRST_PERSON:\n\t\t\t\treturn true;\n\t\t\tcase INVENTORY:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {\n\t\treturn config.isUseNewRenderer() ? newRenderer.shouldUseRenderHelper(type, item, helper) : true;\n\t}\n\n\t@Override\n\tpublic void renderItem(ItemRenderType type, ItemStack item, Object... data) {\n\t\tif (config.isUseNewRenderer() && SimpleServiceLocator.cclProxy.isActivated()) {\n\t\t\tnewRenderer.renderItem(type, item, data);\n\t\t\treturn;\n\t\t}\n\t\tswitch (type) {\n\t\t\tcase ENTITY:\n\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.5f, -0.5f, -0.5f);\n\t\t\t\tbreak;\n\t\t\tcase EQUIPPED:\n\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.4f, 0.50f, 0.35f);\n\t\t\t\tbreak;\n\t\t\tcase EQUIPPED_FIRST_PERSON:\n\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.4f, 0.50f, 0.35f);\n\t\t\t\tbreak;\n\t\t\tcase INVENTORY:\n\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.5f, -0.5f, -0.5f);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t}\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/LogisticsPipeWorldRenderer.java",
    "content": "/*\npackage logisticspipes.renderer;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.buildcraft.subproxies.IBCPipePluggable;\nimport logisticspipes.renderer.newpipe.LogisticsNewPipeWorldRenderer;\nimport logisticspipes.renderer.state.PipeRenderState;\nimport logisticspipes.textures.Textures;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.renderer.RenderBlocks;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.world.IBlockAccess;\n\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.client.registry.ISimpleBlockRenderingHandler;\n\npublic class LogisticsPipeWorldRenderer implements ISimpleBlockRenderingHandler {\n\n\tpublic static int renderPass = -1;\n\n\tprivate ClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\tprivate LogisticsNewPipeWorldRenderer newRenderer = new LogisticsNewPipeWorldRenderer();\n\n\tpublic static boolean renderPipe(RenderBlocks renderblocks, IBlockAccess iblockaccess, LogisticsBlockGenericPipe block, LogisticsTileGenericPipe pipe, int x, int y, int z) {\n\t\tif (pipe.pipe instanceof PipeBlockRequestTable) {\n\t\t\tif (LogisticsPipeWorldRenderer.renderPass != 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tPipeRenderState state = pipe.renderState;\n\t\t\tIIconProvider icons = pipe.getPipeIcons();\n\t\t\tif (icons == null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tstate.currentTexture = icons.getIcon(state.textureMatrix.getTextureIndex(null));\n\t\t\tblock.setRenderAllSides();\n\t\t\tblock.setBlockBounds(0, 0, 0, 1, 1, 1);\n\t\t\trenderblocks.setRenderBoundsFromBlock(block);\n\t\t\trenderblocks.renderStandardBlock(block, x, y, z);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Here to prevent Minecraft from crashing when nothing renders on render pass zero\n\t\t// This is likely a bug, and has been submitted as an issue to the Forge team\n\t\trenderblocks.setRenderBounds(0, 0, 0, 0, 0, 0);\n\t\trenderblocks.renderStandardBlock(Blocks.stone, x, y, z);\n\t\trenderblocks.setRenderBoundsFromBlock(block);\n\n\t\tPipeRenderState state = pipe.renderState;\n\t\tIIconProvider icons = pipe.getPipeIcons();\n\n\t\tif (icons == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (LogisticsPipeWorldRenderer.renderPass == 0) {\n\t\t\tint connectivity = state.pipeConnectionMatrix.getMask();\n\t\t\tfloat[] dim = new float[6];\n\n\t\t\tif (!pipe.isOpaque()) {\n\t\t\t\t// render the unconnected pipe faces of the center block (if any)\n\t\t\t\tif (connectivity != 0x3f) { // note: 0x3f = 0x111111 = all sides\n\t\t\t\t\tLogisticsPipeWorldRenderer.resetToCenterDimensions(dim);\n\t\t\t\t\tstate.currentTexture = icons.getIcon(state.textureMatrix.getTextureIndex(null));\n\t\t\t\t\tLogisticsPipeWorldRenderer.renderTwoWayBlock(renderblocks, block, x, y, z, dim, connectivity ^ 0x3f);\n\t\t\t\t}\n\n\t\t\t\t// render the connecting pipe faces\n\t\t\t\tfor (int dir = 0; dir < 6; dir++) {\n\t\t\t\t\tint mask = 1 << dir;\n\t\t\t\t\tif ((connectivity & mask) == 0) {\n\t\t\t\t\t\tcontinue; // no connection towards dir\n\t\t\t\t\t}\n\n\t\t\t\t\t// center piece offsets\n\t\t\t\t\tLogisticsPipeWorldRenderer.resetToCenterDimensions(dim);\n\n\t\t\t\t\t// extend block towards dir as it's connected to there\n\t\t\t\t\tdim[dir / 2] = dir % 2 == 0 ? 0 : LPConstants.BC_PIPE_MAX_POS;\n\t\t\t\t\tdim[dir / 2 + 3] = dir % 2 == 0 ? LPConstants.BC_PIPE_MIN_POS : 1;\n\n\t\t\t\t\t// the mask points to all faces perpendicular to dir, i.e. dirs 0+1 -> mask 111100, 1+2 -> 110011, 3+5 -> 001111\n\t\t\t\t\tint renderMask = (3 << (dir / 2 * 2)) ^ 0x3f;\n\n\t\t\t\t\t//workaround for 1.6 texture weirdness, rotate texture for N/S/E/W connections\n\t\t\t\t\trenderblocks.uvRotateEast = renderblocks.uvRotateNorth = renderblocks.uvRotateWest = renderblocks.uvRotateSouth = (dir < 2) ? 0 : 1;\n\n\t\t\t\t\t// render sub block\n\t\t\t\t\tstate.currentTexture = icons.getIcon(state.textureMatrix.getTextureIndex(EnumFacing.VALUES[dir]));\n\n\t\t\t\t\tLogisticsPipeWorldRenderer.renderTwoWayBlock(renderblocks, block, x, y, z, dim, renderMask);\n\t\t\t\t\trenderblocks.uvRotateEast = renderblocks.uvRotateNorth = renderblocks.uvRotateWest = renderblocks.uvRotateSouth = 0;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// render the unconnected pipe faces of the center block (if any)\n\t\t\t\tif (connectivity != 0x3f) { // note: 0x3f = 0x111111 = all sides\n\t\t\t\t\tLogisticsPipeWorldRenderer.resetToCenterDimensions(dim);\n\n\t\t\t\t\t//Render opaque Layer\n\t\t\t\t\tstate.currentTexture = icons.getIcon(Textures.LOGISTICSPIPE_OPAQUE_TEXTURE.normal);\n\t\t\t\t\tLogisticsPipeWorldRenderer.renderOneWayBlock(renderblocks, block, x, y, z, dim, connectivity ^ 0x3f);\n\n\t\t\t\t\t//Render Pipe Texture\n\t\t\t\t\tstate.currentTexture = icons.getIcon(state.textureMatrix.getTextureIndex(null));\n\t\t\t\t\tLogisticsPipeWorldRenderer.renderOneWayBlock(renderblocks, block, x, y, z, dim, connectivity ^ 0x3f);\n\t\t\t\t}\n\n\t\t\t\t// render the connecting pipe faces\n\t\t\t\tfor (int dir = 0; dir < 6; dir++) {\n\t\t\t\t\tint mask = 1 << dir;\n\t\t\t\t\tif ((connectivity & mask) == 0) {\n\t\t\t\t\t\tcontinue; // no connection towards dir\n\t\t\t\t\t}\n\n\t\t\t\t\t// center piece offsets\n\t\t\t\t\tLogisticsPipeWorldRenderer.resetToCenterDimensions(dim);\n\n\t\t\t\t\t// extend block towards dir as it's connected to there\n\t\t\t\t\tdim[dir / 2] = dir % 2 == 0 ? 0 : LPConstants.BC_PIPE_MAX_POS;\n\t\t\t\t\tdim[dir / 2 + 3] = dir % 2 == 0 ? LPConstants.BC_PIPE_MIN_POS : 1;\n\n\t\t\t\t\t// the mask points to all faces perpendicular to dir, i.e. dirs 0+1 -> mask 111100, 1+2 -> 110011, 3+5 -> 001111\n\t\t\t\t\tint renderMask = (3 << (dir / 2 * 2)) ^ 0x3f;\n\n\t\t\t\t\t//workaround for 1.6 texture weirdness, rotate texture for N/S/E/W connections\n\t\t\t\t\trenderblocks.uvRotateEast = renderblocks.uvRotateNorth = renderblocks.uvRotateWest = renderblocks.uvRotateSouth = (dir < 2) ? 0 : 1;\n\n\t\t\t\t\t//Render opaque Layer\n\t\t\t\t\tstate.currentTexture = icons.getIcon(Textures.LOGISTICSPIPE_OPAQUE_TEXTURE.normal);\n\t\t\t\t\tLogisticsPipeWorldRenderer.renderOneWayBlock(renderblocks, block, x, y, z, dim, 0x3f);\n\n\t\t\t\t\t// render sub block\n\t\t\t\t\tstate.currentTexture = icons.getIcon(state.textureMatrix.getTextureIndex(EnumFacing.VALUES[dir]));\n\t\t\t\t\tLogisticsPipeWorldRenderer.renderOneWayBlock(renderblocks, block, x, y, z, dim, renderMask);\n\t\t\t\t\trenderblocks.uvRotateEast = renderblocks.uvRotateNorth = renderblocks.uvRotateWest = renderblocks.uvRotateSouth = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trenderblocks.setRenderBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (pipe.tilePart.hasPipePluggable(dir)) {\n\t\t\t\tIBCPipePluggable p = pipe.tilePart.getBCPipePluggable(dir);\n\t\t\t\tp.renderPluggable(renderblocks, dir, LogisticsPipeWorldRenderer.renderPass, x, y, z);\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tprivate static void resetToCenterDimensions(float[] dim) {\n\t\tfor (int i = 0; i < 3; i++) {\n\t\t\tdim[i] = LPConstants.BC_PIPE_MIN_POS;\n\t\t}\n\t\tfor (int i = 3; i < 6; i++) {\n\t\t\tdim[i] = LPConstants.BC_PIPE_MAX_POS;\n\t\t}\n\t}\n\n\t/**\n\t * Render a block with normal and inverted vertex order so back face culling\n\t * doesn't have any effect.\n\t * /\n\tprivate static void renderOneWayBlock(RenderBlocks renderblocks, LogisticsBlockGenericPipe block, int x, int y, int z, float[] dim, int mask) {\n\t\tassert mask != 0;\n\n\t\tblock.setRenderMask(mask);\n\t\trenderblocks.setRenderBounds(dim[2], dim[0], dim[1], dim[5], dim[3], dim[4]);\n\t\trenderblocks.renderStandardBlock(block, x, y, z);\n\t}\n\n\t/**\n\t * Render a block with normal and inverted vertex order so back face culling\n\t * doesn't have any effect.\n\t * /\n\tprivate static void renderTwoWayBlock(RenderBlocks renderblocks, LogisticsBlockGenericPipe block, int x, int y, int z, float[] dim, int mask) {\n\t\tassert mask != 0;\n\n\t\tblock.setRenderMask(mask);\n\t\trenderblocks.setRenderBounds(dim[2], dim[0], dim[1], dim[5], dim[3], dim[4]);\n\t\trenderblocks.renderStandardBlock(block, x, y, z);\n\t\t//flip back side texture\n\t\trenderblocks.flipTexture = true;\n\t\tblock.setRenderMask((mask & 0x15) << 1 | (mask & 0x2a) >> 1); // pairwise swapped mask\n\t\trenderblocks.setRenderBounds(dim[5], dim[3], dim[4], dim[2], dim[0], dim[1]);\n\t\trenderblocks.renderStandardBlock(block, x, y, z);\n\t\trenderblocks.flipTexture = false;\n\t}\n\n\t@Override\n\tpublic void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer) {}\n\n\t@Override\n\tpublic boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {\n\t\tTileEntity tile = world.getTileEntity(x, y, z);\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tLogisticsTileGenericPipe pipeTile = (LogisticsTileGenericPipe) tile;\n\t\t\tSimpleServiceLocator.thermalDynamicsProxy.renderPipeConnections(pipeTile, renderer);\n\t\t\tif (config.isUseNewRenderer() && !pipeTile.renderState.forceRenderOldPipe) {\n\t\t\t\treturn newRenderer.renderWorldBlock(world, x, y, z, block, modelId, renderer);\n\t\t\t}\n\t\t\treturn LogisticsPipeWorldRenderer.renderPipe(renderer, world, (LogisticsBlockGenericPipe) block, pipeTile, x, y, z);\n\t\t} else if (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\trenderer.setRenderBounds(0, 0, 0, 0, 0, 0);\n\t\t\trenderer.renderStandardBlock(Blocks.stone, x, y, z);\n\t\t\trenderer.setRenderBoundsFromBlock(block);\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getRenderId() {\n\t\treturn LPConstants.pipeModel;\n\t}\n\n\t@Override\n\tpublic boolean shouldRender3DInInventory(int modelId) {\n\t\treturn false;\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/LogisticsRenderPipe.java",
    "content": "package logisticspipes.renderer;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.model.ModelSign;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.ItemModelMesher;\nimport net.minecraft.client.renderer.RenderItem;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.block.model.IBakedModel;\nimport net.minecraft.client.renderer.block.model.ItemCameraTransforms;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.client.shader.Framebuffer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.ForgeHooksClient;\n\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL12;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.signs.IPipeSign;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.newpipe.LogisticsNewPipeItemBoxRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.transport.PipeFluidTransportLogistics;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsRenderPipe extends TileEntitySpecialRenderer<LogisticsTileGenericPipe> {\n\n\tprivate static final ExecutorService pool = Executors.newFixedThreadPool(1);\n\tprivate static final int LIQUID_STAGES = 40;\n\tprivate static final int MAX_ITEMS_TO_RENDER = 10;\n\tprivate static final ResourceLocation SIGN = new ResourceLocation(\"textures/entity/sign.png\");\n\tpublic static LogisticsNewRenderPipe secondRenderer = new LogisticsNewRenderPipe();\n\tpublic static LogisticsNewPipeItemBoxRenderer boxRenderer = new LogisticsNewPipeItemBoxRenderer();\n\tpublic static ClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\tprivate static final ItemStackRenderer itemRenderer = new ItemStackRenderer(0, 0, 0, false, false);\n\tprivate final ModelSign modelSign = new ModelSign();\n\n\tpublic LogisticsRenderPipe() {\n\t\tsuper();\n\t\tmodelSign.signStick.showModel = false;\n\t}\n\n\t@Override\n\tpublic void render(@Nullable LogisticsTileGenericPipe tileentity, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {\n\t\tboolean inHand = (tileentity == null || (x == 0 && y == 0 && z == 0));\n\t\tif (!inHand && tileentity.pipe == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tGlStateManager.enableDepth();\n\t\tGlStateManager.depthFunc(515);\n\t\tGlStateManager.depthMask(true);\n\n\t\tif (destroyStage >= 0) {\n\t\t\tthis.bindTexture(DESTROY_STAGES[destroyStage]);\n\t\t\tGlStateManager.matrixMode(GL11.GL_TEXTURE);\n\t\t\tGlStateManager.pushMatrix();\n\t\t\tGlStateManager.scale(4.0F, 4.0F, 1.0F);\n\t\t\t//GlStateManager.translate(0.0625F, 0.0625F, 0.0625F);\n\t\t\tGlStateManager.matrixMode(GL11.GL_MODELVIEW);\n\t\t}\n\n\t\tGlStateManager.pushMatrix();\n\t\tGlStateManager.enableRescaleNormal();\n\n\t\tif (destroyStage < 0) {\n\t\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, alpha);\n\t\t}\n\n\t\tif (!inHand) {\n\t\t\tif (tileentity.pipe instanceof CoreRoutedPipe) {\n\t\t\t\trenderPipeSigns((CoreRoutedPipe) tileentity.pipe, x, y, z, partialTicks);\n\t\t\t}\n\t\t}\n\n\t\tdouble distance = !inHand ? new DoubleCoordinates((TileEntity) tileentity).distanceTo(new DoubleCoordinates(Minecraft.getMinecraft().player)) : 0;\n\n\t\tLogisticsRenderPipe.secondRenderer.renderTileEntityAt(tileentity, x, y, z, partialTicks, distance);\n\n\t\tif (!inHand && !tileentity.isOpaque()) {\n\t\t\tif (tileentity.pipe.transport instanceof PipeFluidTransportLogistics) {\n\t\t\t\t//renderFluids(pipe.pipe, x, y, z);\n\t\t\t}\n\t\t\tif (tileentity.pipe.transport != null) {\n\t\t\t\trenderSolids(tileentity.pipe, x, y, z, partialTicks);\n\t\t\t}\n\t\t}\n\n\t\tGlStateManager.disableRescaleNormal();\n\t\tGlStateManager.popMatrix();\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tif (destroyStage >= 0) {\n\t\t\tGlStateManager.matrixMode(GL11.GL_TEXTURE);\n\t\t\tGlStateManager.popMatrix();\n\t\t\tGlStateManager.matrixMode(GL11.GL_MODELVIEW);\n\t\t}\n\n\t\tif (!inHand) {\n\t\t\tSimpleServiceLocator.mcmpProxy.renderTileEntitySpecialRenderer(tileentity, x, y, z, partialTicks, destroyStage, alpha);\n\t\t}\n\t}\n\n\tprivate void renderSolids(CoreUnroutedPipe pipe, double x, double y, double z, float partialTickTime) {\n\t\tGL11.glPushMatrix();\n\n\t\tfloat light = pipe.container.getWorld().getLightBrightness(pipe.container.getPos());\n\n\t\tint count = 0;\n\t\tfor (LPTravelingItem item : pipe.transport.items) {\n\t\t\tCoreUnroutedPipe lPipe = pipe;\n\t\t\tdouble lX = x;\n\t\t\tdouble lY = y;\n\t\t\tdouble lZ = z;\n\t\t\tfloat lItemYaw = item.getYaw();\n\t\t\tif (count >= LogisticsRenderPipe.MAX_ITEMS_TO_RENDER) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (item.getItemIdentifierStack() == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!item.getContainer().getPos().equals(lPipe.container.getPos())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (item.getPosition() > lPipe.transport.getPipeLength() || item.getPosition() < 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfloat fPos = item.getPosition() + item.getSpeed() * partialTickTime;\n\t\t\tif (fPos > lPipe.transport.getPipeLength() && item.output != null) {\n\t\t\t\tCoreUnroutedPipe nPipe = lPipe.transport.getNextPipe(item.output);\n\t\t\t\tif (nPipe != null) {\n\t\t\t\t\tfPos -= lPipe.transport.getPipeLength();\n\t\t\t\t\tlX -= lPipe.getX() - nPipe.getX();\n\t\t\t\t\tlY -= lPipe.getY() - nPipe.getY();\n\t\t\t\t\tlZ -= lPipe.getZ() - nPipe.getZ();\n\t\t\t\t\tlItemYaw += lPipe.transport.getYawDiff(item);\n\t\t\t\t\tlPipe = nPipe;\n\t\t\t\t\titem = item.renderCopy();\n\t\t\t\t\titem.input = item.output;\n\t\t\t\t\titem.output = null;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tDoubleCoordinates pos = lPipe.getItemRenderPos(fPos, item);\n\t\t\tif (pos == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tdouble boxScale = lPipe.getBoxRenderScale(fPos, item);\n\t\t\tdouble itemYaw = (lPipe.getItemRenderYaw(fPos, item) - lPipe.getItemRenderYaw(0, item) + lItemYaw) % 360;\n\t\t\tdouble itemPitch = lPipe.getItemRenderPitch(fPos, item);\n\t\t\tdouble itemYawForPitch = lPipe.getItemRenderYaw(fPos, item);\n\n\t\t\tItemStack stack = item.getItemIdentifierStack().makeNormalStack();\n\t\t\tdoRenderItem(stack, pipe.container.getWorld(), lX + pos.getXCoord(), lY + pos.getYCoord(), lZ + pos.getZCoord(), light, 0.75F, boxScale, itemYaw, itemPitch, itemYawForPitch, partialTickTime);\n\t\t\tcount++;\n\t\t}\n\n\t\tcount = 0;\n\t\tdouble dist = 0.135;\n\t\tDoubleCoordinates pos = new DoubleCoordinates(0.5, 0.5, 0.5);\n\t\tCoordinateUtils.add(pos, EnumFacing.SOUTH, dist);\n\t\tCoordinateUtils.add(pos, EnumFacing.EAST, dist);\n\t\tCoordinateUtils.add(pos, EnumFacing.UP, dist);\n\t\tfor (Pair<ItemIdentifierStack, Pair<Integer, Integer>> item : pipe.transport._itemBuffer) {\n\t\t\tif (item == null || item.getValue1() == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack stack = item.getValue1().makeNormalStack();\n\t\t\tdoRenderItem(stack, pipe.container.getWorld(), x + pos.getXCoord(), y + pos.getYCoord(), z + pos.getZCoord(), light, 0.25F, 0, 0, 0, 0, partialTickTime);\n\t\t\tcount++;\n\t\t\tif (count >= 27) {\n\t\t\t\tbreak;\n\t\t\t} else if (count % 9 == 0) {\n\t\t\t\tCoordinateUtils.add(pos, EnumFacing.SOUTH, dist * 2.0);\n\t\t\t\tCoordinateUtils.add(pos, EnumFacing.EAST, dist * 2.0);\n\t\t\t\tCoordinateUtils.add(pos, EnumFacing.DOWN, dist);\n\t\t\t} else if (count % 3 == 0) {\n\t\t\t\tCoordinateUtils.add(pos, EnumFacing.SOUTH, dist * 2.0);\n\t\t\t\tCoordinateUtils.add(pos, EnumFacing.WEST, dist);\n\t\t\t} else {\n\t\t\t\tCoordinateUtils.add(pos, EnumFacing.NORTH, dist);\n\t\t\t}\n\t\t}\n\n\t\tGL11.glPopMatrix();\n\t}\n\n\tpublic void doRenderItem(@Nonnull ItemStack itemstack, World world, double x, double y, double z, float light, float renderScale, double boxScale, double yaw, double pitch, double yawForPitch, float partialTickTime) {\n\t\tLogisticsRenderPipe.boxRenderer.doRenderItem(itemstack, light, x, y, z, boxScale, yaw, pitch, yawForPitch);\n\n\t\tGL11.glPushMatrix();\n\t\tGL11.glTranslated(x, y, z);\n\t\tGL11.glScalef(renderScale, renderScale, renderScale);\n\t\tGL11.glRotated(yawForPitch, 0, 1, 0);\n\t\tGL11.glRotated(pitch, 1, 0, 0);\n\t\tGL11.glRotated(-yawForPitch, 0, 1, 0);\n\t\tGL11.glRotated(yaw, 0, 1, 0);\n\t\tGL11.glTranslatef(0.0F, -0.35F, 0.0F);\n\t\titemRenderer.setItemstack(itemstack).setWorld(world).setPartialTickTime(partialTickTime);\n\t\titemRenderer.renderInWorld();\n\t\tGL11.glPopMatrix();\n\t}\n\n\tprivate boolean needDistance(List<Pair<EnumFacing, IPipeSign>> list) {\n\t\tList<Pair<EnumFacing, IPipeSign>> copy = new ArrayList<>(list);\n\t\tIterator<Pair<EnumFacing, IPipeSign>> iter = copy.iterator();\n\t\tboolean north = false, south = false, east = false, west = false;\n\t\twhile (iter.hasNext()) {\n\t\t\tPair<EnumFacing, IPipeSign> pair = iter.next();\n\t\t\tif (pair.getValue1() == EnumFacing.UP || pair.getValue1() == EnumFacing.DOWN || pair.getValue1() == null) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t\tif (pair.getValue1() == EnumFacing.NORTH) {\n\t\t\t\tnorth = true;\n\t\t\t}\n\t\t\tif (pair.getValue1() == EnumFacing.SOUTH) {\n\t\t\t\tsouth = true;\n\t\t\t}\n\t\t\tif (pair.getValue1() == EnumFacing.EAST) {\n\t\t\t\teast = true;\n\t\t\t}\n\t\t\tif (pair.getValue1() == EnumFacing.WEST) {\n\t\t\t\twest = true;\n\t\t\t}\n\t\t}\n\t\tboolean result = copy.size() > 1;\n\t\tif (copy.size() == 2) {\n\t\t\tif (north && south) {\n\t\t\t\tresult = false;\n\t\t\t}\n\t\t\tif (east && west) {\n\t\t\t\tresult = false;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate void renderPipeSigns(CoreRoutedPipe pipe, double x, double y, double z, float partialTickTime) {\n\t\tList<Pair<EnumFacing, IPipeSign>> pipeSigns = pipe.getPipeSigns();\n\t\tif (pipe.container != null && !pipeSigns.isEmpty()) {\n\t\t\tfor (Pair<EnumFacing, IPipeSign> pair : pipeSigns) {\n\t\t\t\tif (pipe.container.renderState.pipeConnectionMatrix.isConnected(pair.getValue1())) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tGL11.glPushMatrix();\n\t\t\t\tGL11.glTranslatef((float) x + 0.5F, (float) y + 0.5F, (float) z + 0.5F);\n\t\t\t\tswitch (pair.getValue1()) {\n\t\t\t\t\tcase UP:\n\t\t\t\t\t\tGL11.glRotatef(90, 1.0F, 0.0F, 0.0F);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase DOWN:\n\t\t\t\t\t\tGL11.glRotatef(-90, 1.0F, 0.0F, 0.0F);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase NORTH:\n\t\t\t\t\t\tGL11.glRotatef(0, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\t\tif (needDistance(pipeSigns)) {\n\t\t\t\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.15F);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SOUTH:\n\t\t\t\t\t\tGL11.glRotatef(-180, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\t\tif (needDistance(pipeSigns)) {\n\t\t\t\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.15F);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase EAST:\n\t\t\t\t\t\tGL11.glRotatef(-90, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\t\tif (needDistance(pipeSigns)) {\n\t\t\t\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.15F);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase WEST:\n\t\t\t\t\t\tGL11.glRotatef(90, 0.0F, 1.0F, 0.0F);\n\t\t\t\t\t\tif (needDistance(pipeSigns)) {\n\t\t\t\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.15F);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t}\n\t\t\t\trenderSign(pipe, pair.getValue2(), partialTickTime);\n\t\t\t\tGL11.glPopMatrix();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void renderSign(CoreRoutedPipe pipe, IPipeSign type, float partialTickTime) {\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tGL11.glDisable(GL12.GL_RESCALE_NORMAL);\n\n\t\tfloat signScale = 2 / 3.0F;\n\t\tGL11.glTranslatef(0.0F, -0.3125F, -0.36F);\n\t\tGL11.glRotatef(180, 0.0f, 1.0f, 0.0f);\n\t\tMinecraft.getMinecraft().renderEngine.bindTexture(LogisticsRenderPipe.SIGN);\n\n\t\tGL11.glPushMatrix();\n\t\tGL11.glScalef(signScale, -signScale, -signScale);\n\t\tmodelSign.renderSign();\n\t\tGL11.glPopMatrix();\n\n\n\t\tboolean needsUpdating = type.doesFrameBufferNeedUpdating(pipe, this);\n\t\tFramebuffer fbo = type.getMCFrameBufferForSign();\n\n\t\tif(fbo != null) {\n\t\t\tif(needsUpdating) {\n\t\t\t\tpool.submit(() -> {\n\t\t\t\t\tMinecraft.getMinecraft().addScheduledTask(() -> {\n\t\t\t\t\t\tfbo.framebufferClear();\n\t\t\t\t\t\tGL11.glPushAttrib(GL11.GL_ENABLE_BIT);\n\t\t\t\t\t\tGL11.glMatrixMode(GL11.GL_MODELVIEW);\n\t\t\t\t\t\tGL11.glPushMatrix();\n\t\t\t\t\t\tGL11.glMatrixMode(GL11.GL_PROJECTION);\n\t\t\t\t\t\tGL11.glPushMatrix();\n\n\t\t\t\t\t\t// setup modelview matrix\n\t\t\t\t\t\tGlStateManager.clearColor(1.0f, 1.0f, 1.0f, 0.5f);\n\t\t\t\t\t\tGlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\t\t\t\tGL11.glMatrixMode(GL11.GL_MODELVIEW);\n\t\t\t\t\t\tGL11.glLoadIdentity();\n\t\t\t\t\t\tGL11.glMatrixMode(GL11.GL_PROJECTION);\n\t\t\t\t\t\tGL11.glLoadIdentity();\n\t\t\t\t\t\tGL11.glDepthFunc(GL11.GL_LESS);\n\n\t\t\t\t\t\tGL11.glOrtho(0.0D, 1.0, 1.0, 0.0, -1, 1);\n\t\t\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\n\t\t\t\t\t\tfbo.bindFramebuffer(true);\n\t\t\t\t\t\tresetStateManager();\n\n\t\t\t\t\t\tGL11.glRotatef(-180.0F, 1.0F, 0.0F, 0.0F);\n\t\t\t\t\t\tGL11.glTranslatef(0.16F, -0.41F, 0.0F);\n\t\t\t\t\t\tGL11.glScalef(1.0F, 1.0F, -1/0.001F);\n\n\t\t\t\t\t\ttype.render(pipe, LogisticsRenderPipe.this);\n\t\t\t\t\t\tfbo.unbindFramebuffer();\n\n\t\t\t\t\t\tGL11.glMatrixMode(GL11.GL_PROJECTION);\n\t\t\t\t\t\tGL11.glPopMatrix();\n\t\t\t\t\t\tGL11.glMatrixMode(GL11.GL_MODELVIEW);\n\t\t\t\t\t\tGL11.glPopMatrix();\n\t\t\t\t\t\tGL11.glPopAttrib();\n\n\t\t\t\t\t\tresetStateManager();\n\t\t\t\t\t\tGL11.glDepthFunc(GL11.GL_LEQUAL);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t\tGL11.glTranslatef(-0.5F, -0.19F, 0.07F * signScale);\n\t\t\tTessellator tessellator = Tessellator.getInstance();\n\t\t\tBufferBuilder bufferbuilder = tessellator.getBuffer();\n\t\t\tGlStateManager.enableTexture2D();\n\t\t\tfbo.bindFramebufferTexture();\n\t\t\tbufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX);\n\t\t\tbufferbuilder.pos(0, 0, 0.001).tex(0, 0).endVertex();\n\t\t\tbufferbuilder.pos(1, 0, 0.001).tex(1, 0).endVertex();\n\t\t\tbufferbuilder.pos(1, 1, 0.001).tex(1, 1).endVertex();\n\t\t\tbufferbuilder.pos(0, 1, 0.001).tex(0, 1).endVertex();\n\t\t\ttessellator.draw();\n\t\t\tfbo.unbindFramebufferTexture();\n\t\t} else {\n\t\t\tGL11.glTranslatef(-0.32F, 0.5F * signScale + 0.08F, 0.07F * signScale);\n\t\t\ttype.render(pipe, this);\n\t\t}\n\t}\n\n\tprivate void resetStateManager() {\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tGlStateManager.color(0.0F, 0.0F, 0.0F, 1.0F);\n\t\tGlStateManager.depthMask(false);\n\t\tGlStateManager.depthMask(true);\n\t\tGlStateManager.disableDepth();\n\t\tGlStateManager.enableDepth();\n\t}\n\n\tpublic void renderItemStackOnSign(@Nonnull ItemStack itemstack) {\n\t\tif (itemstack.isEmpty()) {\n\t\t\treturn; // Only happens on false configuration\n\t\t}\n\n\t\tMinecraft mc = Minecraft.getMinecraft();\n\t\tRenderItem itemRender = mc.getRenderItem();\n\n\t\tGlStateManager.disableLighting();\n\t\tGlStateManager.color(1F, 1F, 1F); //Forge: Reset color in case Items change it.\n\t\tGlStateManager.enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.\n\t\titemRender.zLevel = 100.0F;\n\t\tGlStateManager.enableRescaleNormal();\n\n\t\t// itemRender.renderItemAndEffectIntoGUI(itemstack, 0, 0);\n\t\t// item render code\n\t\tGlStateManager.pushMatrix();\n\t\tmc.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\tmc.renderEngine.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).setBlurMipmap(false, false);\n\t\tGlStateManager.enableRescaleNormal();\n\t\tGlStateManager.enableAlpha();\n\t\tGlStateManager.alphaFunc(516, 0.1F);\n\t\tGlStateManager.enableBlend();\n\t\tGlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\n\t\t// mezz.jei.render.ItemStackFastRenderer#getBakedModel\n\t\tItemModelMesher itemModelMesher = Minecraft.getMinecraft().getRenderItem().getItemModelMesher();\n\t\tIBakedModel bakedModel = itemModelMesher.getItemModel(itemstack);\n\t\tbakedModel = bakedModel.getOverrides().handleItemState(bakedModel, itemstack, null, null);\n\n\t\t// make item/block flat and position it\n\t\tGlStateManager.translate(0.05F, 0F, 0F);\n\t\tGlStateManager.scale(0.8F, 0.8F, 0.001F);\n\n\t\t// model rotation\n\t\tbakedModel = ForgeHooksClient.handleCameraTransforms(bakedModel, ItemCameraTransforms.TransformType.GUI, false);\n\n\t\t// model scaling to fit on sign\n\t\tGlStateManager.scale(0.4F, 0.4F, 0.4F);\n\n\t\titemRender.renderItem(itemstack, bakedModel);\n\n\t\tGlStateManager.disableRescaleNormal();\n\t\tGlStateManager.disableAlpha();\n\t\tGlStateManager.popMatrix();\n\t\tmc.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\tmc.renderEngine.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap();\n\t\t// item render code end\n\n\t\t// not needed?\n\t\t//itemRender.renderItemOverlays(mc.fontRenderer, itemstack, 0, 0);\n\t\titemRender.zLevel = 0.0F;\n\t}\n\n\tpublic String cut(String name, FontRenderer renderer) {\n\t\tif (renderer.getStringWidth(name) < 90) {\n\t\t\treturn name;\n\t\t}\n\t\tStringBuilder sum = new StringBuilder();\n\t\tfor (int i = 0; i < name.length(); i++) {\n\t\t\tif (renderer.getStringWidth(sum.toString() + name.charAt(i) + \"...\") < 90) {\n\t\t\t\tsum.append(name.charAt(i));\n\t\t\t} else {\n\t\t\t\treturn sum + \"...\";\n\t\t\t}\n\t\t}\n\t\treturn sum.toString();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/LogisticsSolidBlockWorldRenderer.java",
    "content": "/*\npackage logisticspipes.renderer;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.renderer.RenderBlocks;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.world.IBlockAccess;\n\nimport net.minecraftforge.fml.client.registry.ISimpleBlockRenderingHandler;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.blocks.LogisticsSolidBlock;\nimport logisticspipes.blocks.LogisticsSolidTileEntity;\nimport logisticspipes.renderer.newpipe.LogisticsNewSolidBlockWorldRenderer;\n\npublic class LogisticsSolidBlockWorldRenderer implements ISimpleBlockRenderingHandler {\n\n\tpublic ClientConfiguration config;\n\tLogisticsNewSolidBlockWorldRenderer newRenderer = new LogisticsNewSolidBlockWorldRenderer();\n\n\tpublic LogisticsSolidBlockWorldRenderer() {\n\t\tconfig = LogisticsPipes.getClientPlayerConfig();\n\t}\n\n\t@Override\n\tpublic void renderInventoryBlock(Block block, int metadata, int modelId, RenderBlocks renderer) {\n\t\tint tmpID = LPConstants.solidBlockModel;\n\t\tif (config.isUseNewRenderer()) {\n\t\t\tnewRenderer.renderInventoryBlock(block, metadata);\n\t\t} else {\n\t\t\tLPConstants.solidBlockModel = 0;\n\t\t\trenderer.renderBlockAsItem(block, metadata, 1.0F);\n\t\t\tLPConstants.solidBlockModel = tmpID;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {\n\t\tTileEntity tile = world.getTileEntity(x, y, z);\n\t\tif (tile instanceof LogisticsSolidTileEntity) {\n\t\t\tif (config.isUseNewRenderer()) {\n\t\t\t\tnewRenderer.renderWorldBlock(world, (LogisticsSolidTileEntity) tile, renderer, x, y, z);\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\tblock.setBlockBounds(0, 0, 0, 1, 1, 1);\n\t\t\t\trenderer.setRenderBoundsFromBlock(block);\n\t\t\t\tswitch (((LogisticsSolidTileEntity) tile).getRotation()) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\trenderer.uvRotateTop = 2;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\trenderer.uvRotateTop = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\trenderer.uvRotateTop = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\trenderer.uvRotateTop = 3;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\trenderer.renderStandardBlock(block, x, y, z);\n\t\t\t\trenderer.uvRotateTop = 0;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if(world.getBlockMetadata(x, y, z) == LogisticsSolidBlock.LOGISTICS_BLOCK_FRAME) {\n\t\t\tif (config.isUseNewRenderer()) {\n\t\t\t\tnewRenderer.renderWorldBlock(world, null, renderer, x, y, z);\n\t\t\t\treturn true;\n\t\t\t} else {\n\t\t\t\tblock.setBlockBounds(0, 0, 0, 1, 1, 1);\n\t\t\t\trenderer.setRenderBoundsFromBlock(block);\n\t\t\t\trenderer.renderStandardBlock(block, x, y, z);\n\t\t\t\trenderer.uvRotateTop = 0;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean shouldRender3DInInventory(int modelId) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int getRenderId() {\n\t\treturn LPConstants.solidBlockModel;\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/LogisticsTileRenderController.java",
    "content": "package logisticspipes.renderer;\n\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.Map;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.Getter;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.PowerPacketLaser;\nimport logisticspipes.pipefxhandlers.PipeFXLaserPowerBall;\nimport logisticspipes.pipefxhandlers.PipeFXLaserPowerBeam;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsTileRenderController {\n\n\tprivate static final int LASER_TIMEOUT_TICKS = 4;\n\n\tprivate final LogisticsTileGenericPipe pipe;\n\tprivate final Map<LaserKey, LaserBeamData> powerLasersBeam = new HashMap<>();\n\tprivate final Map<Integer, LaserBallData> powerLasersBall = new HashMap<>();\n\n\t@Data\n\t@AllArgsConstructor\n\tprivate static class LaserKey {\n\n\t\tfinal EnumFacing dir;\n\t\tfinal int color;\n\t}\n\n\t@Data\n\t@AllArgsConstructor\n\tprivate static class LaserBeamData {\n\n\t\tfinal float length;\n\t\tint timeout;\n\t\tfinal boolean reverse;\n\n\t\tboolean isDeadEntity() {\n\t\t\treturn false;\n\t\t}\n\n\t\tvoid setDead() {}\n\n\t\tboolean sendPacket() {\n\t\t\treturn true;\n\t\t}\n\n\t\tvoid tick() {\n\t\t\ttimeout--;\n\t\t}\n\t}\n\n\tprivate class LaserBeamDataClient extends LaserBeamData {\n\n\t\tpublic LaserBeamDataClient(float length, int timeout, boolean reverse, EnumFacing dir, int color) {\n\t\t\tsuper(length, timeout, reverse);\n\t\t\tentity = new PipeFXLaserPowerBeam(pipe.getWorld(), new DoubleCoordinates((TileEntity) pipe), length, dir, color, pipe).setReverse(reverse);\n\t\t\tMinecraft.getMinecraft().effectRenderer.addEffect(entity);\n\n\t\t}\n\n\t\t@Getter\n\t\t@SideOnly(Side.CLIENT)\n\t\tfinal PipeFXLaserPowerBeam entity;\n\n\t\t@Override\n\t\tboolean isDeadEntity() {\n\t\t\treturn entity == null || !entity.isAlive();\n\t\t}\n\n\t\t@Override\n\t\tvoid setDead() {\n\t\t\tif (entity != null) {\n\t\t\t\tentity.setExpired();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tboolean sendPacket() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tvoid tick() {}\n\t}\n\n\t@Data\n\t@AllArgsConstructor\n\tprivate static class LaserBallData {\n\n\t\tfinal float length;\n\t\tint timeout;\n\n\t\tboolean isDeadEntity() {\n\t\t\treturn false;\n\t\t}\n\n\t\tvoid setDead() {}\n\n\t\tboolean sendPacket() {\n\t\t\treturn true;\n\t\t}\n\n\t\tvoid tick() {\n\t\t\ttimeout--;\n\t\t}\n\t}\n\n\tprivate class LaserBallDataClient extends LaserBallData {\n\n\t\tpublic LaserBallDataClient(float length, int timeout, int color) {\n\t\t\tsuper(length, timeout);\n\t\t\tentity = new PipeFXLaserPowerBall(pipe.getWorld(), new DoubleCoordinates((TileEntity) pipe), color, pipe);\n\t\t\tMinecraft.getMinecraft().effectRenderer.addEffect(entity);\n\t\t}\n\n\t\t@Getter\n\t\t@SideOnly(Side.CLIENT)\n\t\tfinal PipeFXLaserPowerBall entity;\n\n\t\t@Override\n\t\tboolean isDeadEntity() {\n\t\t\treturn entity == null || !entity.isAlive();\n\t\t}\n\n\t\t@Override\n\t\tvoid setDead() {\n\t\t\tif (entity != null) {\n\t\t\t\tentity.setExpired();\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tboolean sendPacket() {\n\t\t\treturn false;\n\t\t}\n\n\t\t@Override\n\t\tvoid tick() {}\n\t}\n\n\tpublic LogisticsTileRenderController(LogisticsTileGenericPipe pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\tpublic void onUpdate() {\n\t\t{\n\t\t\tIterator<LaserKey> iter = powerLasersBeam.keySet().iterator();\n\t\t\twhile (iter.hasNext()) {\n\t\t\t\tLaserKey key = iter.next();\n\t\t\t\tLaserBeamData data = powerLasersBeam.get(key);\n\t\t\t\tdata.tick();\n\t\t\t\tif (data.timeout < 0 || data.isDeadEntity()) {\n\t\t\t\t\tdata.setDead();\n\t\t\t\t\tif (data.sendPacket()) {\n\t\t\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(pipe, PacketHandler.getPacket(PowerPacketLaser.class).setColor(key.color).setRenderBall(false).setDir(key.dir).setRemove(true).setTilePos(pipe));\n\t\t\t\t\t}\n\t\t\t\t\titer.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t{\n\t\t\tIterator<Integer> iter = powerLasersBall.keySet().iterator();\n\t\t\twhile (iter.hasNext()) {\n\t\t\t\tInteger key = iter.next();\n\t\t\t\tLaserBallData data = powerLasersBall.get(key);\n\t\t\t\tdata.tick();\n\t\t\t\tif (data.timeout < 0 || data.isDeadEntity()) {\n\t\t\t\t\tdata.setDead();\n\t\t\t\t\tif (data.sendPacket()) {\n\t\t\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(pipe, PacketHandler.getPacket(PowerPacketLaser.class).setColor(key).setRenderBall(true).setDir(null).setRemove(true).setTilePos(pipe));\n\t\t\t\t\t}\n\t\t\t\t\titer.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void addLaser(EnumFacing dir, float length, int color, boolean reverse, boolean renderBall) {\n\t\tif (!Configs.ENABLE_PARTICLE_FX) {\n\t\t\treturn;\n\t\t}\n\t\tboolean sendPacket = false;\n\t\tif (powerLasersBeam.containsKey(new LaserKey(dir, color))) {\n\t\t\tpowerLasersBeam.get(new LaserKey(dir, color)).timeout = LASER_TIMEOUT_TICKS;\n\t\t} else {\n\t\t\tif (MainProxy.isClient(pipe.getWorld())) {\n\t\t\t\tpowerLasersBeam.put(new LaserKey(dir, color), new LaserBeamDataClient(length, LASER_TIMEOUT_TICKS, reverse, dir, color));\n\t\t\t} else {\n\t\t\t\tpowerLasersBeam.put(new LaserKey(dir, color), new LaserBeamData(length, LASER_TIMEOUT_TICKS, reverse));\n\t\t\t\tsendPacket = true;\n\t\t\t}\n\t\t}\n\t\tif (renderBall) {\n\t\t\tif (powerLasersBall.containsKey(color)) {\n\t\t\t\tpowerLasersBall.get(color).timeout = LASER_TIMEOUT_TICKS;\n\t\t\t} else {\n\t\t\t\tif (MainProxy.isClient(pipe.getWorld())) {\n\t\t\t\t\tpowerLasersBall.put(color, new LaserBallDataClient(length, LASER_TIMEOUT_TICKS, color));\n\t\t\t\t} else {\n\t\t\t\t\tpowerLasersBall.put(color, new LaserBallData(length, LASER_TIMEOUT_TICKS));\n\t\t\t\t\tsendPacket = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (sendPacket) {\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(pipe, PacketHandler.getPacket(PowerPacketLaser.class).setColor(color).setRenderBall(renderBall).setDir(dir).setLength(length).setReverse(reverse).setTilePos(pipe));\n\t\t}\n\t}\n\n\tpublic void removeLaser(EnumFacing dir, int color, boolean isBall) {\n\t\tif (!MainProxy.isClient(pipe.getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tif (!isBall) {\n\t\t\tLaserKey key = new LaserKey(dir, color);\n\t\t\tLaserBeamData beam = powerLasersBeam.get(key);\n\t\t\tif (beam != null) {\n\t\t\t\tbeam.timeout = -1;\n\t\t\t\tif (MainProxy.isClient(pipe.getWorld())) {\n\t\t\t\t\t((LaserBeamDataClient) beam).entity.setExpired();\n\t\t\t\t}\n\t\t\t\tpowerLasersBeam.remove(key);\n\t\t\t}\n\t\t} else {\n\t\t\tLaserBallData ball = powerLasersBall.get(color);\n\t\t\tif (ball != null) {\n\t\t\t\tball.timeout = -1;\n\t\t\t\tif (MainProxy.isClient(pipe.getWorld())) {\n\t\t\t\t\t((LaserBallDataClient) ball).entity.setExpired();\n\t\t\t\t}\n\t\t\t\tpowerLasersBall.remove(color);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void sendInit() {\n\t\tfor (LaserKey key : powerLasersBeam.keySet()) {\n\t\t\tLaserBeamData data = powerLasersBeam.get(key);\n\t\t\tboolean isBall = powerLasersBall.containsKey(key.color);\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(pipe, PacketHandler.getPacket(PowerPacketLaser.class)\n\t\t\t\t\t.setColor(key.color).setRenderBall(isBall).setDir(key.dir).setLength(data.length).setReverse(data.reverse).setTilePos(pipe));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/GLRenderList.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport net.minecraft.client.renderer.GLAllocation;\n\nimport org.lwjgl.opengl.GL11;\n\npublic class GLRenderList {\n\n\tprivate final int listID = GLAllocation.generateDisplayLists(1);\n\tpublic boolean isValid = true;\n\tprivate long lastUsed = System.currentTimeMillis();\n\tprivate boolean isFilled = false;\n\n\tpublic int getID() {\n\t\treturn listID;\n\t}\n\n\tpublic void startListCompile() {\n\t\tif (!isValid) {\n\t\t\tthrow new UnsupportedOperationException(\"Can't use a removed list\");\n\t\t}\n\t\tGL11.glNewList(listID, GL11.GL_COMPILE);\n\t}\n\n\tpublic void stopCompile() {\n\t\tif (!isValid) {\n\t\t\tthrow new UnsupportedOperationException(\"Can't use a removed list\");\n\t\t}\n\t\tGL11.glEndList();\n\t\tisFilled = true;\n\t}\n\n\tpublic void render() {\n\t\tif (!isValid) {\n\t\t\tthrow new UnsupportedOperationException(\"Can't use a removed list\");\n\t\t}\n\t\tGL11.glCallList(listID);\n\t\tlastUsed = System.currentTimeMillis();\n\t}\n\n\tpublic boolean check() {\n\t\tif (!isValid) {\n\t\t\treturn true;\n\t\t}\n\t\tif (lastUsed + 1000 * 60 * 1 < System.currentTimeMillis()) {\n\t\t\tisValid = false;\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic boolean isInvalid() {\n\t\treturn !isValid;\n\t}\n\n\tpublic boolean isFilled() {\n\t\treturn isFilled;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/GLRenderListHandler.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.renderer.GLAllocation;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic class GLRenderListHandler {\n\n\tprivate List<GLRenderList> collection = new ArrayList<>();\n\tprivate final Object lockCollection = new Object();\n\n\tpublic GLRenderList getNewRenderList() {\n\t\tGLRenderList list = new GLRenderList();\n\t\tsynchronized (lockCollection) {\n\t\t\tcollection.add(list);\n\t\t}\n\t\treturn list;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic void tick() {\n\t\tsynchronized (lockCollection) {\n\t\t\tList<GLRenderList> newCollection = new ArrayList<>(collection);\n\t\t\tcollection.stream().filter(ref -> !ref.check()).forEach(ref -> {\n\t\t\t\tGLAllocation.deleteDisplayLists(ref.getID());\n\t\t\t\tnewCollection.remove(ref);\n\t\t\t});\n\t\t\tif (newCollection.size() != collection.size()) {\n\t\t\t\tcollection = newCollection;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/IHighlightPlacementRenderer.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport logisticspipes.interfaces.ITubeOrientation;\n\npublic interface IHighlightPlacementRenderer {\n\n\tvoid renderHighlight(ITubeOrientation orientation);\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/ISpecialPipeRenderer.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPUVTransformationList;\nimport logisticspipes.proxy.object3d.operation.LPUVTranslation;\n\npublic interface ISpecialPipeRenderer {\n\n\tdefault void modelsToRenderList(@Nonnull final ArrayList<RenderEntry> objectsToRender, final List<IModel3D> models) {\n\t\tobjectsToRender.ensureCapacity(objectsToRender.size() + models.size());\n\t\tmodels.stream()\n\t\t\t\t.map(model -> new RenderEntry(model, new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(0, 0)) }, getTexture()))\n\t\t\t\t.forEach(objectsToRender::add);\n\t}\n\n\tdefault void renderToList(@Nullable CoreUnroutedPipe pipe, @Nonnull ArrayList<RenderEntry> objectsToRender) {\n\t\tif (pipe == null) {\n\t\t\tmodelsToRenderList(objectsToRender, getModelsWithoutPipe());\n\t\t} else {\n\t\t\tmodelsToRenderList(objectsToRender, getModelsFromPipe(pipe));\n\t\t}\n\t}\n\n\t@Nonnull\n\tList<IModel3D> getModelsWithoutPipe();\n\n\t@Nonnull\n\tList<IModel3D> getModelsFromPipe(@Nonnull CoreUnroutedPipe pipe);\n\n\t@Nonnull\n\tResourceLocation getTexture();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsBlockModel.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport javax.vecmath.Matrix4f;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.IBakedModel;\nimport net.minecraft.client.renderer.block.model.ItemCameraTransforms;\nimport net.minecraft.client.renderer.block.model.ItemOverrideList;\nimport net.minecraft.client.renderer.block.model.ModelResourceLocation;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.client.resources.IResourceManager;\nimport net.minecraft.item.Item;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.client.model.ICustomModelLoader;\nimport net.minecraftforge.client.model.IModel;\nimport net.minecraftforge.client.model.PerspectiveMapWrapper;\nimport net.minecraftforge.common.model.IModelState;\nimport net.minecraftforge.fml.common.registry.ForgeRegistries;\n\nimport com.google.common.collect.Lists;\nimport org.apache.commons.lang3.tuple.Pair;\n\nimport logisticspipes.blocks.LogisticsSolidBlock;\nimport logisticspipes.blocks.LogisticsSolidBlock.Type;\nimport logisticspipes.items.LogisticsSolidBlockItem;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.renderer.LogisticsRenderPipe;\n\npublic class LogisticsBlockModel implements IModel {\n\n\tpublic static class Loader implements ICustomModelLoader {\n\n\t\t@Override\n\t\tpublic boolean accepts(@Nonnull ResourceLocation modelLocation) {\n\t\t\treturn getType(modelLocation) != null;\n\t\t}\n\n\t\t@Override\n\t\t@Nonnull\n\t\tpublic IModel loadModel(@Nonnull ResourceLocation modelLocation) {\n\t\t\tResourceLocation baseTex = new ResourceLocation(modelLocation.getNamespace(), \"solid_block/\" + modelLocation.getPath());\n\t\t\treturn new LogisticsBlockModel(baseTex, Objects.requireNonNull(getType(modelLocation)));\n\t\t}\n\n\t\t@Nullable\n\t\tprivate Type getType(ResourceLocation modelLocation) {\n\t\t\tif (!(modelLocation instanceof ModelResourceLocation)) return null;\n\t\t\tResourceLocation clean = new ResourceLocation(modelLocation.getNamespace(), modelLocation.getPath());\n\t\t\tString variant = ((ModelResourceLocation) modelLocation).getVariant();\n\n\t\t\tif (variant.equals(\"inventory\")) {\n\t\t\t\t// TODO split placement item into seperate items\n\t\t\t\tItem item = ForgeRegistries.ITEMS.getValue(clean);\n\t\t\t\tif (item instanceof LogisticsSolidBlockItem) {\n\t\t\t\t\treturn ((LogisticsSolidBlockItem) item).getType();\n\t\t\t\t} else return null;\n\t\t\t} else {\n\t\t\t\tBlock block = ForgeRegistries.BLOCKS.getValue(clean);\n\t\t\t\tif (block instanceof LogisticsSolidBlock) {\n\t\t\t\t\treturn ((LogisticsSolidBlock) block).getType();\n\t\t\t\t} else return null;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onResourceManagerReload(@Nonnull IResourceManager resourceManager) {}\n\t}\n\n\tprivate final ResourceLocation inactive;\n\tprivate final ResourceLocation active;\n\n\tpublic LogisticsBlockModel(ResourceLocation texture, Type type) {\n\t\tthis.inactive = texture;\n\t\tif (type.isHasActiveTexture()) {\n\t\t\tthis.active = new ResourceLocation(texture.getNamespace(), texture.getPath() + \"_active\");\n\t\t} else {\n\t\t\tthis.active = texture;\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Collection<ResourceLocation> getTextures() {\n\t\treturn Arrays.asList(inactive, active);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic IBakedModel bake(@Nonnull IModelState state, @Nonnull VertexFormat format, @Nonnull Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {\n\t\tfinal List<BakedQuad> quads = Lists.newArrayList();\n\n\t\tTextureAtlasSprite inactiveT = bakedTextureGetter.apply(inactive);\n\t\tTextureAtlasSprite activeT = bakedTextureGetter.apply(active);\n\n\t\treturn new IBakedModel() {\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic List<BakedQuad> getQuads(@Nullable IBlockState state, @Nullable EnumFacing side, long rand) {\n\t\t\t\tif (side == null) {\n\t\t\t\t\tsynchronized (quads) {\n\t\t\t\t\t\tif (quads.isEmpty()) {\n\t\t\t\t\t\t\tquads.addAll(LogisticsRenderPipe.secondRenderer.getQuadsFromRenderList(generateBlockRenderList(state, inactiveT, activeT), format, true));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn quads;\n\t\t\t\t} else {\n\t\t\t\t\treturn Collections.emptyList();//LogisticsRenderPipe.secondRenderer.getQuadsFromRenderList(generateBlockRenderList(state), format);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isAmbientOcclusion() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isGui3d() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isBuiltInRenderer() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic TextureAtlasSprite getParticleTexture() {\n\t\t\t\treturn inactiveT;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic ItemOverrideList getOverrides() {\n\t\t\t\treturn ItemOverrideList.NONE;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic Pair<? extends IBakedModel, Matrix4f> handlePerspective(@Nonnull ItemCameraTransforms.TransformType cameraTransformType) {\n\t\t\t\tIModelState defaultBlockState = SimpleServiceLocator.cclProxy.getDefaultBlockState();\n\t\t\t\tif (defaultBlockState == null) {\n\t\t\t\t\t// no special camera transform is better than crashing\n\t\t\t\t\treturn net.minecraftforge.client.ForgeHooksClient.handlePerspective(this, cameraTransformType);\n\t\t\t\t} else {\n\n\t\t\t\t\treturn PerspectiveMapWrapper.handlePerspective(this, defaultBlockState, cameraTransformType);\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate List<RenderEntry> generateBlockRenderList(@Nullable IBlockState state, @Nonnull TextureAtlasSprite inactive, @Nonnull TextureAtlasSprite active) {\n\t\tList<RenderEntry> objectsToRender = new ArrayList<>();\n\n\t\tLogisticsNewSolidBlockWorldRenderer.BlockRotation rotation = LogisticsNewSolidBlockWorldRenderer.BlockRotation.ZERO;\n\t\tTextureTransformation icon;\n\t\tif (state != null) {\n\t\t\trotation = LogisticsNewSolidBlockWorldRenderer.BlockRotation.getRotation(state.getValue(LogisticsSolidBlock.rotationProperty));\n\t\t\ticon = SimpleServiceLocator.cclProxy.createIconTransformer(state.getValue(LogisticsSolidBlock.active) ? active : inactive);\n\t\t} else {\n\t\t\ticon = SimpleServiceLocator.cclProxy.createIconTransformer(inactive);\n\t\t}\n\n\t\t// Draw\n\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.block.get(rotation), icon));\n\t\tfor (LogisticsNewSolidBlockWorldRenderer.CoverSides side : LogisticsNewSolidBlockWorldRenderer.CoverSides.values()) {\n\t\t\tboolean render = true;\n\t\t\tif (state != null) {\n\t\t\t\tif (!state.getValue(LogisticsSolidBlock.connectionPropertys.get(side.getDir(rotation)))) {\n\t\t\t\t\trender = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (render) {\n\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation), icon));\n\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.texturePlate_Inner.get(side).get(rotation), icon));\n\t\t\t}\n\t\t}\n\n\t\treturn objectsToRender;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsNewPipeItemBoxRenderer.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.GLAllocation;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class LogisticsNewPipeItemBoxRenderer {\n\n\tprivate static final int RENDER_SIZE = 40;\n\n\tprivate int renderList = -1;\n\tprivate static final ResourceLocation BLOCKS = new ResourceLocation(\"textures/atlas/blocks.png\");\n\tprivate static final Map<FluidIdentifier, int[]> renderLists = new HashMap<>();\n\n\t@SideOnly(Side.CLIENT)\n\tpublic void doRenderItem(@Nonnull ItemStack itemstack, float light, double x, double y, double z, double boxScale, double yaw, double pitch, double yawForPitch) {\n\t\tif (LogisticsNewRenderPipe.innerTransportBox == null) return;\n\t\tGL11.glPushMatrix();\n\n\t\tif (renderList == -1) {\n\t\t\trenderList = GLAllocation.generateDisplayLists(1);\n\t\t\tGL11.glNewList(renderList, GL11.GL_COMPILE);\n\n\t\t\tSimpleServiceLocator.cclProxy.getRenderState().reset();\n\t\t\tSimpleServiceLocator.cclProxy.getRenderState().startDrawing(GL11.GL_QUADS, DefaultVertexFormats.OLDMODEL_POSITION_TEX_NORMAL);\n\n\t\t\tLogisticsNewRenderPipe.innerTransportBox.render(LogisticsNewRenderPipe.innerBoxTexture);\n\n\t\t\tSimpleServiceLocator.cclProxy.getRenderState().draw();\n\t\t\tGL11.glEndList();\n\t\t}\n\n\t\tGL11.glTranslated(x, y, z);\n\t\tMinecraft.getMinecraft().getTextureManager().bindTexture(LogisticsNewPipeItemBoxRenderer.BLOCKS);\n\t\tGL11.glScaled(boxScale, boxScale, boxScale);\n\t\tGL11.glRotated(yawForPitch, 0, 1, 0);\n\t\tGL11.glRotated(pitch, 1, 0, 0);\n\t\tGL11.glRotated(-yawForPitch, 0, 1, 0);\n\t\tGL11.glRotated(yaw, 0, 1, 0);\n\t\tGL11.glTranslated(-0.5, -0.5, -0.5);\n\t\tGL11.glCallList(renderList);\n\t\tGL11.glTranslated(0.5, 0.5, 0.5);\n\t\tGL11.glRotated(-pitch, 1, 0, 0);\n\t\tGL11.glRotated(-yaw, 0, 1, 0);\n\t\tGL11.glScaled(1 / boxScale, 1 / boxScale, 1 / boxScale);\n\t\tGL11.glTranslated(-0.5, -0.5, -0.5);\n\n\t\tif (!itemstack.isEmpty() && itemstack.getItem() instanceof LogisticsFluidContainer) {\n\t\t\tFluidIdentifierStack f = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(ItemIdentifierStack.getFromStack(itemstack));\n\t\t\tif (f != null) {\n\t\t\t\t/*\n\t\t\t\tFluidContainerRenderer.skipNext = true;\n\t\t\t\tint list = getRenderListFor(f);\n\t\t\t\tGL11.glPushAttrib(GL11.GL_ENABLE_BIT);\n\t\t\t\tGL11.glEnable(GL11.GL_CULL_FACE);\n\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\t\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\n\t\t\t\tGL11.glCallList(list);\n\t\t\t\tGL11.glPopAttrib();\n\t\t\t\t*/\n\t\t\t}\n\t\t}\n\n\t\tGL11.glPopMatrix();\n\t}\n/*\n\tprivate int getRenderListFor(FluidStack fluid) {\n\t\tFluidIdentifier ident = FluidIdentifier.get(fluid);\n\t\tint[] array = LogisticsNewPipeItemBoxRenderer.renderLists.get(fluid);\n\t\tif (array == null) {\n\t\t\tarray = new int[LogisticsNewPipeItemBoxRenderer.RENDER_SIZE];\n\t\t\tLogisticsNewPipeItemBoxRenderer.renderLists.put(ident, array);\n\t\t}\n\t\tint pos = Math.min((int) (((Math.min(fluid.amount, 5000) * 1.0F) * LogisticsNewPipeItemBoxRenderer.RENDER_SIZE) / 5000), LogisticsNewPipeItemBoxRenderer.RENDER_SIZE - 1);\n\t\tif (array[pos] != 0) {\n\t\t\treturn array[pos];\n\t\t}\n\t\tRenderInfo block = new RenderInfo();\n\n\t\tblock.baseBlock = fluid.getFluid().getBlock();\n\t\tblock.texture = fluid.getFluid().getStillIcon();\n\n\t\tfloat ratio = pos * 1.0F / (LogisticsNewPipeItemBoxRenderer.RENDER_SIZE - 1);\n\n\t\t// CENTER HORIZONTAL\n\n\t\tarray[pos] = GLAllocation.generateDisplayLists(1);\n\t\tGL11.glNewList(array[pos], 4864 /* GL_COMPILE * /);\n\n\t\tblock.minX = 0.32;\n\t\tblock.maxX = 0.68;\n\n\t\tblock.minY = 0.32;\n\t\tblock.maxY = 0.32 + (0.68 - 0.32) * ratio;\n\n\t\tblock.minZ = 0.32;\n\t\tblock.maxZ = 0.68;\n\n\t\tCustomBlockRenderer.INSTANCE.renderBlock(block, Minecraft.getMinecraft().theWorld, 0, 0, 0, false, true);\n\n\t\tGL11.glEndList();\n\t\treturn array[pos];\n\t}*/\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsNewPipeItemRenderer.java",
    "content": "/*\npackage logisticspipes.renderer.newpipe;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe.Corner;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe.Edge;\nimport logisticspipes.renderer.newpipe.LogisticsNewSolidBlockWorldRenderer.BlockRotation;\nimport logisticspipes.renderer.newpipe.LogisticsNewSolidBlockWorldRenderer.CoverSides;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.utils.tuples.Pair;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.renderer.RenderBlocks;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.client.IItemRenderer;\nimport net.minecraft.util.EnumFacing;\n\nimport org.lwjgl.opengl.GL11;\n\npublic class LogisticsNewPipeItemRenderer implements IItemRenderer {\n\n\tprivate final boolean renderAsBlock;\n\n\tpublic LogisticsNewPipeItemRenderer(boolean targeted) {\n\t\trenderAsBlock = targeted;\n\t}\n\n\tprivate void renderPipeItem(RenderBlocks render, ItemStack item, float translateX, float translateY, float translateZ) {\n\t\tGL11.glPushMatrix();\n\n\t\tGL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT); // don't break other mods' guis when holding a pipe\n\n\t\t// force transparency\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\t// GL11.glBindTexture(GL11.GL_TEXTURE_2D, 10);\n\t\tTessellator tessellator = Tessellator.instance;\n\n\t\tGL11.glTranslatef(translateX, translateY, translateZ);\n\t\tBlock block = LogisticsPipes.LogisticsPipeBlock;\n\t\tif (item.getItem() instanceof ItemLogisticsPipe) {\n\t\t\tItemLogisticsPipe lItem = (ItemLogisticsPipe) item.getItem();\n\t\t\tint renderList = lItem.getNewPipeRenderList();\n\n\t\t\tif (renderList == -1) {\n\t\t\t\tlItem.setNewPipeRenderList(GL11.glGenLists(1));\n\t\t\t\trenderList = lItem.getNewPipeRenderList();\n\t\t\t\tGL11.glNewList(renderList, GL11.GL_COMPILE);\n\t\t\t\ttessellator.startDrawingQuads();\n\t\t\t\tgeneratePipeRenderList(lItem.getNewPipeIconIndex());\n\t\t\t\ttessellator.draw();\n\t\t\t\tGL11.glEndList();\n\t\t\t}\n\t\t\tGL11.glCallList(renderList);\n\t\t}\n\t\tGL11.glTranslatef(0.5F, 0.5F, 0.5F);\n\t\tblock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tGL11.glPopAttrib();\n\t\tGL11.glPopMatrix();\n\t}\n\n\tprivate void generatePipeRenderList(int texture) {\n\t\tList<Pair<IModel3D, TextureTransformation>> objectsToRender = new ArrayList<>();\n\n\t\tfor (Corner corner : Corner.values()) {\n\t\t\tobjectsToRender.addAll(LogisticsNewRenderPipe.corners_M.get(corner).stream()\n\t\t\t\t\t.map(model -> new Pair<>(model, LogisticsNewRenderPipe.basicPipeTexture))\n\t\t\t\t\t.collect(Collectors.toList()));\n\t\t}\n\n\t\tfor (Edge edge : Edge.values()) {\n\t\t\tobjectsToRender.add(new Pair<>(LogisticsNewRenderPipe.edges\n\t\t\t\t\t.get(edge), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t}\n\n\t\t//ArrayList<Pair<CCModel, IconTransformation>> objectsToRender2 = new ArrayList<Pair<CCModel, IconTransformation>>();\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.texturePlate_Outer.get(dir)) {\n\t\t\t\tTextureTransformation icon = Textures.LPnewPipeIconProvider.getIcon(texture);\n\t\t\t\tif (icon != null) {\n\t\t\t\t\tobjectsToRender.add(new Pair<>(model, icon));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (Pair<IModel3D, TextureTransformation> part : objectsToRender) {\n\t\t\tpart.getValue1().render(part.getValue2());\n\t\t}\n\n\t}\n\n\tprivate void renderBlockItem(RenderBlocks render, ItemStack item, float translateX, float translateY, float translateZ) {\n\t\tGL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT); //don't break other mods' guis when holding a pipe\n\t\t//force transparency\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\tGL11.glTranslatef(translateX, translateY, translateZ);\n\t\tBlock block = LogisticsPipes.LogisticsPipeBlock;\n\t\tTessellator tess = Tessellator.instance;\n\n\t\tBlockRotation rotation = BlockRotation.ZERO;\n\n\t\ttess.startDrawingQuads();\n\n\t\tTextureTransformation icon = SimpleServiceLocator.cclProxy.createIconTransformer(Textures.LOGISTICS_REQUEST_TABLE_NEW);\n\n\t\t//Draw\n\t\tLogisticsNewSolidBlockWorldRenderer.block.get(rotation).render(new I3DOperation[] { icon });\n\t\tfor (CoverSides side : CoverSides.values()) {\n\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation).render(new I3DOperation[] { icon });\n\t\t}\n\t\ttess.draw();\n\t\tblock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tGL11.glPopAttrib(); // nicely leave the rendering how it was\n\t}\n\n\tprivate void renderItem(RenderBlocks render, ItemStack item, float translateX, float translateY, float translateZ) {\n\t\tif (renderAsBlock) {\n\t\t\trenderBlockItem(render, item, translateX, translateY, translateZ);\n\t\t} else {\n\t\t\trenderPipeItem(render, item, translateX, translateY, translateZ);\n\t\t}\n\t}\n\n\t/**\n\t * IItemRenderer implementation\n\t ** /\n\n\t@Override\n\tpublic boolean handleRenderType(ItemStack item, ItemRenderType type) {\n\t\tswitch (type) {\n\t\t\tcase ENTITY:\n\t\t\t\treturn true;\n\t\t\tcase EQUIPPED:\n\t\t\t\treturn true;\n\t\t\tcase EQUIPPED_FIRST_PERSON:\n\t\t\t\treturn true;\n\t\t\tcase INVENTORY:\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void renderItem(ItemRenderType type, ItemStack item, Object... data) {\n\t\tswitch (type) {\n\t\t\tcase ENTITY:\n\t\t\t\tif (renderAsBlock) {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.5f, -0.5f, -0.5f);\n\t\t\t\t} else {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.5f, -0.5f, -0.5f);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EQUIPPED:\n\t\t\t\tif (renderAsBlock) {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, 0f, 0f, 0f);\n\t\t\t\t} else {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.4f, 0.50f, 0.35f);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase EQUIPPED_FIRST_PERSON:\n\t\t\t\tif (renderAsBlock) {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, 0f, 0.0f, 0.0f);\n\t\t\t\t} else {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.4f, 0.50f, 0.35f);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase INVENTORY:\n\t\t\t\tif (renderAsBlock) {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.5f, -0.5f, -0.5f);\n\t\t\t\t} else {\n\t\t\t\t\trenderItem((RenderBlocks) data[0], item, -0.5f, -0.5f, -0.5f);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t}\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsNewPipeModel.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.function.Function;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\nimport javax.vecmath.Matrix4f;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.block.model.IBakedModel;\nimport net.minecraft.client.renderer.block.model.ItemCameraTransforms;\nimport net.minecraft.client.renderer.block.model.ItemOverrideList;\nimport net.minecraft.client.renderer.block.model.ModelResourceLocation;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.client.resources.IResourceManager;\nimport net.minecraft.item.Item;\nimport net.minecraft.util.BlockRenderLayer;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport net.minecraftforge.client.MinecraftForgeClient;\nimport net.minecraftforge.client.model.ICustomModelLoader;\nimport net.minecraftforge.client.model.IModel;\nimport net.minecraftforge.client.model.PerspectiveMapWrapper;\nimport net.minecraftforge.common.model.IModelState;\nimport net.minecraftforge.common.property.IExtendedBlockState;\nimport net.minecraftforge.fml.common.registry.ForgeRegistries;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport com.google.common.cache.Cache;\nimport com.google.common.collect.Lists;\nimport com.google.common.collect.Maps;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.proxy.object3d.operation.LPUVScale;\nimport logisticspipes.proxy.object3d.operation.LPUVTransformationList;\nimport logisticspipes.renderer.LogisticsRenderPipe;\nimport logisticspipes.renderer.state.PipeRenderState;\nimport logisticspipes.textures.Textures;\n\npublic class LogisticsNewPipeModel implements IModel {\n\n\tprivate static final ResourceLocation BASE_TEXTURE = new ResourceLocation(\"logisticspipes\", \"blocks/blank_pipe\");\n\tpublic static TextureAtlasSprite BASE_TEXTURE_SPRITE;\n\tpublic static TextureTransformation BASE_TEXTURE_TRANSFORM;\n\n\tpublic static void registerTextures(TextureMap iconRegister) {\n\t\tBASE_TEXTURE_SPRITE = iconRegister.registerSprite(BASE_TEXTURE);\n\t\tif (BASE_TEXTURE_TRANSFORM == null) {\n\t\t\tBASE_TEXTURE_TRANSFORM = SimpleServiceLocator.cclProxy.createIconTransformer(BASE_TEXTURE_SPRITE);\n\t\t} else {\n\t\t\tBASE_TEXTURE_TRANSFORM.update(BASE_TEXTURE_SPRITE);\n\t\t}\n\t}\n\n\tpublic static class LogisticsNewPipeModelLoader implements ICustomModelLoader {\n\n\t\t@Override\n\t\tpublic boolean accepts(ResourceLocation modelLocation) {\n\t\t\tif (modelLocation.getNamespace().equals(\"logisticspipes\")) {\n\t\t\t\tif (modelLocation instanceof ModelResourceLocation) {\n\t\t\t\t\tResourceLocation rl = new ResourceLocation(modelLocation.getNamespace(), modelLocation.getPath());\n\t\t\t\t\tif (((ModelResourceLocation) modelLocation).getVariant().equals(\"inventory\")) {\n\t\t\t\t\t\tItem item = ForgeRegistries.ITEMS.getValue(rl);\n\t\t\t\t\t\tif (item instanceof ItemLogisticsPipe) {\n\t\t\t\t\t\t\tCoreUnroutedPipe pipe = ((ItemLogisticsPipe) item).getDummyPipe();\n\t\t\t\t\t\t\tnameTextureIdMap.put((ModelResourceLocation) modelLocation, pipe);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (rl.equals(LPBlocks.pipe.getRegistryName())) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic IModel loadModel(@Nonnull ResourceLocation modelLocation) {\n\t\t\treturn new LogisticsNewPipeModel((ModelResourceLocation) modelLocation);\n\t\t}\n\n\t\t@Override\n\t\tpublic void onResourceManagerReload(@Nonnull IResourceManager resourceManager) {\n\n\t\t}\n\t}\n\n\tpublic static Map<ModelResourceLocation, CoreUnroutedPipe> nameTextureIdMap = Maps.newLinkedHashMap();\n\tprivate ModelResourceLocation key;\n\n\tpublic LogisticsNewPipeModel(ModelResourceLocation resource) {\n\t\tkey = resource;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Collection<ResourceLocation> getDependencies() {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Collection<ResourceLocation> getTextures() {\n\t\treturn Collections.emptyList();\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\t@Nonnull\n\tpublic IBakedModel bake(@Nonnull IModelState state, @Nonnull VertexFormat format, @Nonnull Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) {\n\t\treturn new IBakedModel() {\n\t\t\tprivate ArrayList<BakedQuad> quads = null;\n\n\t\t\t@Override\n\t\t\t@SideOnly(Side.CLIENT)\n\t\t\t@Nonnull\n\t\t\tpublic List<BakedQuad> getQuads(@Nullable IBlockState blockstate, @Nullable EnumFacing side, long rand) {\n\t\t\t\tBlockRenderLayer layer = MinecraftForgeClient.getRenderLayer();\n\t\t\t\tArrayList<BakedQuad> result;\n\t\t\t\tif (layer == BlockRenderLayer.CUTOUT || layer == null || blockstate == null) {\n\t\t\t\t\tresult = getLPQuads(blockstate, side);\n\t\t\t\t} else {\n\t\t\t\t\tresult = Lists.newArrayList();\n\t\t\t\t}\n\t\t\t\taddOtherQuads(result, blockstate, side, rand);\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tprivate void addOtherQuads(@Nonnull List<BakedQuad> list, IBlockState blockstate, EnumFacing side, long rand) {\n\t\t\t\tif (blockstate != null) {\n\t\t\t\t\tSimpleServiceLocator.mcmpProxy.addQuads(list, blockstate, side, rand);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tprivate ArrayList<BakedQuad> getLPQuads(@Nullable IBlockState blockstate, @Nullable EnumFacing side) {\n\t\t\t\tif (blockstate != null) {\n\t\t\t\t\tif (side == null) {\n\t\t\t\t\t\tIExtendedBlockState eState = (IExtendedBlockState) blockstate;\n\t\t\t\t\t\tCache<PipeRenderState.LocalCacheType, Object> objectCache = eState.getValue(LogisticsBlockGenericPipe.propertyCache);\n\t\t\t\t\t\tif (objectCache != null) {\n\t\t\t\t\t\t\tObject pipeQuads = objectCache.getIfPresent(PipeRenderState.LocalCacheType.QUADS);\n\t\t\t\t\t\t\tif (pipeQuads instanceof Collection) {\n\t\t\t\t\t\t\t\t//noinspection unchecked\n\t\t\t\t\t\t\t\treturn new ArrayList<>((Collection<? extends BakedQuad>) pipeQuads);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfinal ArrayList<BakedQuad> pipeQuads = LogisticsRenderPipe.secondRenderer.getQuadsFromRenderList(generatePipeRenderList(blockstate), format, true);\n\n\t\t\t\t\t\tif (objectCache != null) {\n\t\t\t\t\t\t\tobjectCache.put(PipeRenderState.LocalCacheType.QUADS, new ArrayList<>(pipeQuads));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn pipeQuads;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (quads == null) {\n\t\t\t\t\t\tquads = LogisticsRenderPipe.secondRenderer.getQuadsFromRenderList(generatePipeRenderList(), format, true);\n\t\t\t\t\t}\n\t\t\t\t\treturn new ArrayList<>(quads);\n\t\t\t\t}\n\t\t\t\treturn Lists.newArrayList();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isAmbientOcclusion() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isGui3d() {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean isBuiltInRenderer() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic TextureAtlasSprite getParticleTexture() {\n\t\t\t\treturn BASE_TEXTURE_SPRITE;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic ItemOverrideList getOverrides() {\n\t\t\t\treturn ItemOverrideList.NONE;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\t@Nonnull\n\t\t\tpublic org.apache.commons.lang3.tuple.Pair<? extends IBakedModel, Matrix4f> handlePerspective(@Nonnull ItemCameraTransforms.TransformType cameraTransformType) {\n\t\t\t\tIModelState defaultBlockState = SimpleServiceLocator.cclProxy.getDefaultBlockState();\n\t\t\t\tif (defaultBlockState == null) {\n\t\t\t\t\t// no special camera transform is better than crashing\n\t\t\t\t\treturn net.minecraftforge.client.ForgeHooksClient.handlePerspective(this, cameraTransformType);\n\t\t\t\t} else {\n\t\t\t\t\treturn PerspectiveMapWrapper.handlePerspective(this, defaultBlockState, cameraTransformType);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\tprivate List<RenderEntry> generatePipeRenderList(IBlockState blockstate) {\n\t\tList<RenderEntry> objectsToRender = new ArrayList<>();\n\n\t\tif (blockstate.getValue(LogisticsBlockGenericPipe.modelTypeProperty) == LogisticsBlockGenericPipe.PipeRenderModel.REQUEST_TABLE) {\n\t\t\tTextureTransformation icon = SimpleServiceLocator.cclProxy.createIconTransformer((TextureAtlasSprite) Textures.LOGISTICS_REQUEST_TABLE_NEW);\n\n\t\t\tLogisticsNewSolidBlockWorldRenderer.BlockRotation rotation = LogisticsNewSolidBlockWorldRenderer.BlockRotation.getRotation(blockstate.getValue(LogisticsBlockGenericPipe.rotationProperty));\n\n\t\t\t//Draw\n\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.block.get(rotation), icon));\n\t\t\tfor (LogisticsNewSolidBlockWorldRenderer.CoverSides side : LogisticsNewSolidBlockWorldRenderer.CoverSides.values()) {\n\t\t\t\tif (!blockstate.getValue(LogisticsBlockGenericPipe.connectionPropertys.get(side.getDir(rotation)))) {\n\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation), icon));\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (blockstate instanceof IExtendedBlockState) {\n\t\t\tIExtendedBlockState lpState = (IExtendedBlockState) blockstate;\n\t\t\tobjectsToRender = lpState.getValue(LogisticsBlockGenericPipe.propertyRenderList);\n\t\t}\n\n\t\tif (objectsToRender != null) {\n\t\t\treturn objectsToRender;\n\t\t} else {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t}\n\n\tprivate CoreUnroutedPipe getPipe() {\n\t\treturn nameTextureIdMap.get(key);\n\t}\n\n\tprivate List<RenderEntry> generatePipeRenderList() {\n\t\tArrayList<RenderEntry> objectsToRender = new ArrayList<>();\n\n\t\tif (getPipe() == null) {\n\n\t\t\tSystem.out.println(\"'\" + key + \"' does not result in pipe\");\n\t\t} else if (getPipe() instanceof PipeBlockRequestTable) {\n\t\t\tTextureTransformation icon = SimpleServiceLocator.cclProxy.createIconTransformer((TextureAtlasSprite) Textures.LOGISTICS_REQUEST_TABLE_NEW);\n\n\t\t\tLogisticsNewSolidBlockWorldRenderer.BlockRotation rotation = LogisticsNewSolidBlockWorldRenderer.BlockRotation.ZERO;\n\n\t\t\t//Draw\n\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.block.get(rotation), icon));\n\t\t\tfor (LogisticsNewSolidBlockWorldRenderer.CoverSides side : LogisticsNewSolidBlockWorldRenderer.CoverSides.values()) {\n\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation), icon));\n\t\t\t}\n\t\t} else if (getPipe().getSpecialRenderer() != null) {\n\t\t\tgetPipe().getSpecialRenderer().renderToList(null, objectsToRender);\n\t\t\tAxisAlignedBB[] bb = new AxisAlignedBB[1];\n\t\t\tbb[0] = new AxisAlignedBB(0.5, 0.5, 0.5, 0.5, 0.5, 0.5);\n\t\t\tobjectsToRender.forEach(it -> bb[0] = bb[0].union(it.getModel().bounds().toAABB()));\n\n\t\t\tdouble size = Math.max(Math.max(bb[0].maxX - bb[0].minX, bb[0].maxY - bb[0].minY), bb[0].maxZ - bb[0].minZ);\n\t\t\tobjectsToRender.replaceAll(it -> {\n\t\t\t\tRenderEntry content = it.clone(new I3DOperation[] { new LPUVTransformationList(BASE_TEXTURE_TRANSFORM) });\n\t\t\t\tcontent.getModel().apply(new LPScale(0.95 / size));\n\t\t\t\treturn content;\n\t\t\t});\n\n\t\t\tbb[0] = new AxisAlignedBB(0.5, 0.5, 0.5, 0.5, 0.5, 0.5);\n\t\t\tobjectsToRender.forEach(it -> bb[0] = bb[0].union(it.getModel().bounds().toAABB()));\n\t\t\tobjectsToRender.forEach(it -> it.getModel().apply(new LPTranslation(0.5 - (bb[0].maxX + bb[0].minX) / 2, 0.5 - (bb[0].maxY + bb[0].minY) / 2, 0.5 - (bb[0].maxZ + bb[0].minZ) / 2)));\n\n\t\t} else {\n\t\t\tif (getPipe() instanceof CoreRoutedPipe) {\n\t\t\t\tint red = 0;\n\t\t\t\tboolean toggle = Math.random() < 0.5;\n\t\t\t\tfor (LogisticsNewRenderPipe.Corner corner : LogisticsNewRenderPipe.Corner.values()) {\n\t\t\t\t\tfinal int fred = red;\n\t\t\t\t\tfinal boolean ftoggle = toggle;\n\t\t\t\t\tLogisticsNewRenderPipe.corners_M.get(corner).stream()\n\t\t\t\t\t\t\t.map(model -> new RenderEntry(model, ftoggle && (fred % 4 == 0 || fred % 4 == 3) || !ftoggle && (fred % 4 == 1 || fred % 4 == 2) ?\n\t\t\t\t\t\t\t\t\tLogisticsNewRenderPipe.inactiveTexture :\n\t\t\t\t\t\t\t\t\tLogisticsNewRenderPipe.basicPipeTexture))\n\t\t\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t\t\t\tred++;\n\t\t\t\t\tif (red > 3) {\n\t\t\t\t\t\tred -= 4;\n\t\t\t\t\t\ttoggle = !toggle;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tArrays.stream(LogisticsNewRenderPipe.Corner.values())\n\t\t\t\t\t\t.flatMap(corner -> LogisticsNewRenderPipe.corners_M.get(corner).stream().map(model -> new RenderEntry(model, LogisticsNewRenderPipe.basicPipeTexture)))\n\t\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t\t}\n\n\t\t\tfor (LogisticsNewRenderPipe.Edge edge : LogisticsNewRenderPipe.Edge.values()) {\n\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.edges\n\t\t\t\t\t\t.get(edge), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t}\n\n\t\t\t//ArrayList<Pair<CCModel, IconTransformation>> objectsToRender2 = new ArrayList<Pair<CCModel, IconTransformation>>();\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.texturePlate_Outer.get(dir)) {\n\t\t\t\t\tTextureTransformation icon = Textures.LPnewPipeIconProvider.getIcon(getPipe().getTextureIndex());\n\t\t\t\t\tif (icon != null) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(model, new LPUVTransformationList(new LPUVScale(12f / 16, 12f / 16), icon)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn objectsToRender;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsNewPipeWorldRenderer.java",
    "content": "/*\npackage logisticspipes.renderer.newpipe;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.renderer.RenderBlocks;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.IBlockAccess;\n\nimport net.minecraftforge.fml.client.registry.ISimpleBlockRenderingHandler;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.pipes.PipeBlockRequestTable;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.buildcraft.subproxies.IBCPipePluggable;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.renderer.IIconProvider;\nimport logisticspipes.renderer.LogisticsPipeWorldRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewSolidBlockWorldRenderer.BlockRotation;\nimport logisticspipes.renderer.newpipe.LogisticsNewSolidBlockWorldRenderer.CoverSides;\nimport logisticspipes.renderer.state.PipeRenderState;\nimport logisticspipes.textures.Textures;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsNewPipeWorldRenderer implements ISimpleBlockRenderingHandler {\n\n\tprivate Map<BlockRotation, IModel3D> requestBlock = null;\n\n\t@Override\n\tpublic void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer) {}\n\n\t@Override\n\tpublic boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {\n\t\tTessellator tess = Tessellator.instance;\n\t\tTileEntity tile = world.getTileEntity(x, y, z);\n\t\tLogisticsTileGenericPipe pipeTile = (LogisticsTileGenericPipe) tile;\n\t\tPipeRenderState renderState = pipeTile.renderState;\n\n\t\tif (pipeTile.pipe instanceof PipeBlockRequestTable) {\n\t\t\tif (LogisticsPipeWorldRenderer.renderPass != 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tIIconProvider icons = pipeTile.getPipeIcons();\n\t\t\tif (icons == null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (requestBlock == null || true) {\n\t\t\t\trequestBlock = new HashMap<>();\n\t\t\t\tfor (BlockRotation rot : BlockRotation.values()) {\n\t\t\t\t\trequestBlock.put(rot, LogisticsNewSolidBlockWorldRenderer.block.get(rot).copy().apply(new LPScale(0.999)).apply(new LPTranslation(0.0005, 0.0005, 0.0005)));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tSimpleServiceLocator.cclProxy.getRenderState().reset();\n\t\t\tSimpleServiceLocator.cclProxy.getRenderState().setUseNormals(true);\n\t\t\tSimpleServiceLocator.cclProxy.getRenderState().setAlphaOverride(0xff);\n\n\t\t\tBlockRotation rotation = BlockRotation.getRotation(((PipeBlockRequestTable) pipeTile.pipe).getRotation());\n\n\t\t\tint brightness = new DoubleCoordinates(x, y, z).getBlock(world).getMixedBrightnessForBlock(world, x, y, z);\n\n\t\t\ttess.setColorOpaque_F(1F, 1F, 1F);\n\t\t\ttess.setBrightness(brightness);\n\n\t\t\tTextureTransformation icon = SimpleServiceLocator.cclProxy.createIconTransformer(Textures.LOGISTICS_REQUEST_TABLE_NEW);\n\n\t\t\trequestBlock.get(rotation).render(new LPTranslation(x, y, z), icon);\n\n\t\t\tfor (CoverSides side : CoverSides.values()) {\n\t\t\t\tif (!pipeTile.renderState.pipeConnectionMatrix.isConnected(side.getDir(rotation))) {\n\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation).render(new LPTranslation(x, y, z), icon);\n\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Inner.get(side).get(rotation).render(new LPTranslation(x, y, z), icon);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\tboolean hasRendered = false;\n\n\t\ttess.addTranslation(0.00002F, 0.00002F, 0.00002F);\n\t\trenderer.setRenderBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (pipeTile.tilePart.hasPipePluggable(dir)) {\n\t\t\t\tIBCPipePluggable p = pipeTile.tilePart.getBCPipePluggable(dir);\n\t\t\t\tp.renderPluggable(renderer, dir, LogisticsPipeWorldRenderer.renderPass, x, y, z);\n\t\t\t\thasRendered = true;\n\t\t\t}\n\t\t}\n\t\ttess.addTranslation(-0.00002F, -0.00002F, -0.00002F);\n\n\t\tboolean[] solidSides = new boolean[6];\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tDoubleCoordinates pos = CoordinateUtils.add(new DoubleCoordinates((TileEntity) pipeTile), dir);\n\t\t\tBlock blockSide = pos.getBlock(pipeTile.getWorld());\n\t\t\tif (blockSide != null && blockSide.isSideSolid(pipeTile.getWorld(), pos.getXInt(), pos.getYInt(), pos.getZInt(), dir.getOpposite())\n\t\t\t\t\t&& !renderState.pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\tsolidSides[dir.ordinal()] = true;\n\t\t\t}\n\t\t}\n\t\tif (!Arrays.equals(solidSides, renderState.solidSidesCache)) {\n\t\t\trenderState.solidSidesCache = solidSides.clone();\n\t\t\trenderState.cachedRenderer = null;\n\t\t}\n\n\t\tif(hasRendered) {\n\t\t\tblock.setBlockBounds(0, 0, 0, 0, 0, 0);\n\t\t\trenderer.setRenderBoundsFromBlock(block);\n\t\t\trenderer.renderStandardBlock(block, x, y, z);\n\n\t\t\tblock.setBlockBounds(0, 0, 0, 1, 1, 1);\n\t\t}\n\t\treturn hasRendered;\n\t}\n\n\t@Override\n\tpublic int getRenderId() {\n\t\treturn LPConstants.pipeModel;\n\t}\n\n\t@Override\n\tpublic boolean shouldRender3DInInventory(int modelId) {\n\t\treturn false;\n\t}\n}\n*/"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsNewRenderPipe.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.particle.ParticleManager;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport com.google.common.collect.Lists;\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.pipefxhandlers.EntityModelFX;\nimport logisticspipes.pipes.PipeItemsBasicLogistics;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IBounds;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.interfaces.IVec3;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\nimport logisticspipes.proxy.object3d.operation.LPColourMultiplier;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.proxy.object3d.operation.LPUVScale;\nimport logisticspipes.proxy.object3d.operation.LPUVTransformationList;\nimport logisticspipes.proxy.object3d.operation.LPUVTranslation;\nimport logisticspipes.renderer.state.PipeRenderState;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.utils.tuples.Quartet;\nimport network.rs485.logisticspipes.config.ClientConfiguration;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LogisticsNewRenderPipe implements IHighlightPlacementRenderer {\n\n\tenum Edge {\n\t\tUpper_North(EnumFacing.UP, EnumFacing.NORTH),\n\t\tUpper_South(EnumFacing.UP, EnumFacing.SOUTH),\n\t\tUpper_East(EnumFacing.UP, EnumFacing.EAST),\n\t\tUpper_West(EnumFacing.UP, EnumFacing.WEST),\n\t\tLower_North(EnumFacing.DOWN, EnumFacing.NORTH),\n\t\tLower_South(EnumFacing.DOWN, EnumFacing.SOUTH),\n\t\tLower_East(EnumFacing.DOWN, EnumFacing.EAST),\n\t\tLower_West(EnumFacing.DOWN, EnumFacing.WEST),\n\t\tMiddle_North_West(EnumFacing.NORTH, EnumFacing.WEST),\n\t\tMiddle_North_East(EnumFacing.NORTH, EnumFacing.EAST),\n\t\tLower_South_East(EnumFacing.SOUTH, EnumFacing.EAST),\n\t\tLower_South_West(EnumFacing.SOUTH, EnumFacing.WEST);\n\n\t\tfinal EnumFacing part1;\n\t\tfinal EnumFacing part2;\n\n\t\tEdge(EnumFacing part1, EnumFacing part2) {\n\t\t\tthis.part1 = part1;\n\t\t\tthis.part2 = part2;\n\t\t}\n\t}\n\n\tenum UpDown {\n\t\tUP(\"U\", EnumFacing.UP),\n\t\tDOWN(\"D\", EnumFacing.DOWN);\n\n\t\tfinal String s;\n\t\tfinal EnumFacing dir;\n\n\t\tUpDown(String s, EnumFacing dir) {\n\t\t\tthis.s = s;\n\t\t\tthis.dir = dir;\n\t\t}\n\t}\n\n\tenum NorthSouth {\n\t\tNORTH(\"N\", EnumFacing.NORTH),\n\t\tSOUTH(\"S\", EnumFacing.SOUTH);\n\n\t\tfinal String s;\n\t\tfinal EnumFacing dir;\n\n\t\tNorthSouth(String s, EnumFacing dir) {\n\t\t\tthis.s = s;\n\t\t\tthis.dir = dir;\n\t\t}\n\t}\n\n\tenum EastWest {\n\t\tEAST(\"E\", EnumFacing.EAST),\n\t\tWEST(\"W\", EnumFacing.WEST);\n\n\t\tfinal String s;\n\t\tfinal EnumFacing dir;\n\n\t\tEastWest(String s, EnumFacing dir) {\n\t\t\tthis.s = s;\n\t\t\tthis.dir = dir;\n\t\t}\n\t}\n\n\tenum Corner {\n\t\tUP_NORTH_WEST(UpDown.UP, NorthSouth.NORTH, EastWest.WEST),\n\t\tUP_NORTH_EAST(UpDown.UP, NorthSouth.NORTH, EastWest.EAST),\n\t\tUP_SOUTH_WEST(UpDown.UP, NorthSouth.SOUTH, EastWest.WEST),\n\t\tUP_SOUTH_EAST(UpDown.UP, NorthSouth.SOUTH, EastWest.EAST),\n\t\tDOWN_NORTH_WEST(UpDown.DOWN, NorthSouth.NORTH, EastWest.WEST),\n\t\tDOWN_NORTH_EAST(UpDown.DOWN, NorthSouth.NORTH, EastWest.EAST),\n\t\tDOWN_SOUTH_WEST(UpDown.DOWN, NorthSouth.SOUTH, EastWest.WEST),\n\t\tDOWN_SOUTH_EAST(UpDown.DOWN, NorthSouth.SOUTH, EastWest.EAST);\n\n\t\tfinal UpDown ud;\n\t\tfinal NorthSouth ns;\n\t\tfinal EastWest ew;\n\n\t\tCorner(UpDown ud, NorthSouth ns, EastWest ew) {\n\t\t\tthis.ud = ud;\n\t\t\tthis.ns = ns;\n\t\t\tthis.ew = ew;\n\t\t}\n\t}\n\n\tenum Turn {\n\t\tNORTH_SOUTH(EnumFacing.NORTH, EnumFacing.SOUTH),\n\t\tEAST_WEST(EnumFacing.EAST, EnumFacing.WEST),\n\t\tUP_DOWN(EnumFacing.UP, EnumFacing.DOWN);\n\n\t\tfinal EnumFacing dir1;\n\t\tfinal EnumFacing dir2;\n\n\t\tTurn(EnumFacing dir1, EnumFacing dir2) {\n\t\t\tthis.dir1 = dir1;\n\t\t\tthis.dir2 = dir2;\n\t\t}\n\t}\n\n\tenum PipeTurnCorner {\n\t\tUP_NORTH_WEST_TURN_NORTH_SOUTH(Corner.UP_NORTH_WEST, Turn.NORTH_SOUTH, 1),\n\t\tUP_NORTH_WEST_TURN_EAST_WEST(Corner.UP_NORTH_WEST, Turn.EAST_WEST, 14),\n\t\tUP_NORTH_WEST_TURN_UP_DOWN(Corner.UP_NORTH_WEST, Turn.UP_DOWN, 23),\n\t\tUP_NORTH_EAST_TURN_NORTH_SOUTH(Corner.UP_NORTH_EAST, Turn.NORTH_SOUTH, 2),\n\t\tUP_NORTH_EAST_TURN_EAST_WEST(Corner.UP_NORTH_EAST, Turn.EAST_WEST, 9),\n\t\tUP_NORTH_EAST_TURN_UP_DOWN(Corner.UP_NORTH_EAST, Turn.UP_DOWN, 22),\n\t\tUP_SOUTH_WEST_TURN_NORTH_SOUTH(Corner.UP_SOUTH_WEST, Turn.NORTH_SOUTH, 6),\n\t\tUP_SOUTH_WEST_TURN_EAST_WEST(Corner.UP_SOUTH_WEST, Turn.EAST_WEST, 13),\n\t\tUP_SOUTH_WEST_TURN_UP_DOWN(Corner.UP_SOUTH_WEST, Turn.UP_DOWN, 24),\n\t\tUP_SOUTH_EAST_TURN_NORTH_SOUTH(Corner.UP_SOUTH_EAST, Turn.NORTH_SOUTH, 5),\n\t\tUP_SOUTH_EAST_TURN_EAST_WEST(Corner.UP_SOUTH_EAST, Turn.EAST_WEST, 10),\n\t\tUP_SOUTH_EAST_TURN_UP_DOWN(Corner.UP_SOUTH_EAST, Turn.UP_DOWN, 21),\n\t\tDOWN_NORTH_WEST_TURN_NORTH_SOUTH(Corner.DOWN_NORTH_WEST, Turn.NORTH_SOUTH, 4),\n\t\tDOWN_NORTH_WEST_TURN_EAST_WEST(Corner.DOWN_NORTH_WEST, Turn.EAST_WEST, 15),\n\t\tDOWN_NORTH_WEST_TURN_UP_DOWN(Corner.DOWN_NORTH_WEST, Turn.UP_DOWN, 20),\n\t\tDOWN_NORTH_EAST_TURN_NORTH_SOUTH(Corner.DOWN_NORTH_EAST, Turn.NORTH_SOUTH, 3),\n\t\tDOWN_NORTH_EAST_TURN_EAST_WEST(Corner.DOWN_NORTH_EAST, Turn.EAST_WEST, 12),\n\t\tDOWN_NORTH_EAST_TURN_UP_DOWN(Corner.DOWN_NORTH_EAST, Turn.UP_DOWN, 17),\n\t\tDOWN_SOUTH_WEST_TURN_NORTH_SOUTH(Corner.DOWN_SOUTH_WEST, Turn.NORTH_SOUTH, 7),\n\t\tDOWN_SOUTH_WEST_TURN_EAST_WEST(Corner.DOWN_SOUTH_WEST, Turn.EAST_WEST, 16),\n\t\tDOWN_SOUTH_WEST_TURN_UP_DOWN(Corner.DOWN_SOUTH_WEST, Turn.UP_DOWN, 19),\n\t\tDOWN_SOUTH_EAST_TURN_NORTH_SOUTH(Corner.DOWN_SOUTH_EAST, Turn.NORTH_SOUTH, 8),\n\t\tDOWN_SOUTH_EAST_TURN_EAST_WEST(Corner.DOWN_SOUTH_EAST, Turn.EAST_WEST, 11),\n\t\tDOWN_SOUTH_EAST_TURN_UP_DOWN(Corner.DOWN_SOUTH_EAST, Turn.UP_DOWN, 18);\n\n\t\tfinal Corner corner;\n\t\tfinal Turn turn;\n\t\tfinal int number;\n\n\t\tPipeTurnCorner(Corner corner, Turn turn, int number) {\n\t\t\tthis.corner = corner;\n\t\t\tthis.turn = turn;\n\t\t\tthis.number = number;\n\t\t}\n\n\t\tpublic EnumFacing getPointer() {\n\t\t\tList<EnumFacing> canidates = new ArrayList<>();\n\t\t\tcanidates.add(corner.ew.dir);\n\t\t\tcanidates.add(corner.ns.dir);\n\t\t\tcanidates.add(corner.ud.dir);\n\t\t\tif (canidates.contains(turn.dir1)) {\n\t\t\t\treturn turn.dir1;\n\t\t\t} else if (canidates.contains(turn.dir2)) {\n\t\t\t\treturn turn.dir2;\n\t\t\t} else {\n\t\t\t\tthrow new UnsupportedOperationException(name());\n\t\t\t}\n\t\t}\n\t}\n\n\tenum PipeSupportOri {\n\t\tUP_DOWN(\"U\"),\n\t\tSIDE(\"S\");\n\n\t\tfinal String s;\n\n\t\tPipeSupportOri(String s) {\n\t\t\tthis.s = s;\n\t\t}\n\t}\n\n\tenum PipeSupport {\n\t\tUP_UP(EnumFacing.UP, PipeSupportOri.UP_DOWN),\n\t\tUP_SIDE(EnumFacing.UP, PipeSupportOri.SIDE),\n\t\tDOWN_UP(EnumFacing.DOWN, PipeSupportOri.UP_DOWN),\n\t\tDOWN_SIDE(EnumFacing.DOWN, PipeSupportOri.SIDE),\n\t\tNORTH_UP(EnumFacing.NORTH, PipeSupportOri.UP_DOWN),\n\t\tNORTH_SIDE(EnumFacing.NORTH, PipeSupportOri.SIDE),\n\t\tSOUTH_UP(EnumFacing.SOUTH, PipeSupportOri.UP_DOWN),\n\t\tSOUTH_SIDE(EnumFacing.SOUTH, PipeSupportOri.SIDE),\n\t\tEAST_UP(EnumFacing.EAST, PipeSupportOri.UP_DOWN),\n\t\tEAST_SIDE(EnumFacing.EAST, PipeSupportOri.SIDE),\n\t\tWEST_UP(EnumFacing.WEST, PipeSupportOri.UP_DOWN),\n\t\tWEST_SIDE(EnumFacing.WEST, PipeSupportOri.SIDE);\n\n\t\tPipeSupport(EnumFacing dir, PipeSupportOri ori) {\n\t\t\tthis.dir = dir;\n\t\t\tthis.ori = ori;\n\t\t}\n\n\t\tfinal EnumFacing dir;\n\t\tfinal PipeSupportOri ori;\n\t}\n\n\tenum PipeMount {\n\t\tUP_NORTH(EnumFacing.UP, EnumFacing.NORTH),\n\t\tUP_SOUTH(EnumFacing.UP, EnumFacing.SOUTH),\n\t\tUP_EAST(EnumFacing.UP, EnumFacing.EAST),\n\t\tUP_WEST(EnumFacing.UP, EnumFacing.WEST),\n\t\tDOWN_NORTH(EnumFacing.DOWN, EnumFacing.NORTH),\n\t\tDOWN_SOUTH(EnumFacing.DOWN, EnumFacing.SOUTH),\n\t\tDOWN_EAST(EnumFacing.DOWN, EnumFacing.EAST),\n\t\tDOWN_WEST(EnumFacing.DOWN, EnumFacing.WEST),\n\t\tNORTH_UP(EnumFacing.NORTH, EnumFacing.UP),\n\t\tNORTH_DOWN(EnumFacing.NORTH, EnumFacing.DOWN),\n\t\tNORTH_EAST(EnumFacing.NORTH, EnumFacing.EAST),\n\t\tNORTH_WEST(EnumFacing.NORTH, EnumFacing.WEST),\n\t\tSOUTH_UP(EnumFacing.SOUTH, EnumFacing.UP),\n\t\tSOUTH_DOWN(EnumFacing.SOUTH, EnumFacing.DOWN),\n\t\tSOUTH_EAST(EnumFacing.SOUTH, EnumFacing.EAST),\n\t\tSOUTH_WEST(EnumFacing.SOUTH, EnumFacing.WEST),\n\t\tEAST_UP(EnumFacing.EAST, EnumFacing.UP),\n\t\tEAST_DOWN(EnumFacing.EAST, EnumFacing.DOWN),\n\t\tEAST_NORTH(EnumFacing.EAST, EnumFacing.NORTH),\n\t\tEAST_SOUTH(EnumFacing.EAST, EnumFacing.SOUTH),\n\t\tWEST_UP(EnumFacing.WEST, EnumFacing.UP),\n\t\tWEST_DOWN(EnumFacing.WEST, EnumFacing.DOWN),\n\t\tWEST_NORTH(EnumFacing.WEST, EnumFacing.NORTH),\n\t\tWEST_SOUTH(EnumFacing.WEST, EnumFacing.SOUTH);\n\n\t\tEnumFacing dir;\n\t\tEnumFacing side;\n\n\t\tPipeMount(EnumFacing dir, EnumFacing side) {\n\t\t\tthis.dir = dir;\n\t\t\tthis.side = side;\n\t\t}\n\t}\n\n\tstatic Map<EnumFacing, List<IModel3D>> sideNormal = new HashMap<>();\n\tstatic Map<EnumFacing, List<IModel3D>> sideBC = new HashMap<>();\n\tstatic Map<Edge, IModel3D> edges = new HashMap<>();\n\tstatic Map<Corner, List<IModel3D>> corners_M = new HashMap<>();\n\tstatic Map<Corner, List<IModel3D>> corners_I3 = new HashMap<>();\n\tstatic Map<PipeTurnCorner, IModel3D> corners_I = new HashMap<>();\n\tstatic Map<PipeSupport, IModel3D> supports = new HashMap<>();\n\tstatic Map<PipeTurnCorner, IModel3D> spacers = new HashMap<>();\n\tstatic Map<PipeMount, IModel3D> mounts = new HashMap<>();\n\n\tstatic Map<EnumFacing, List<IModel3D>> texturePlate_Inner = new HashMap<>();\n\tstatic Map<EnumFacing, List<IModel3D>> texturePlate_Outer = new HashMap<>();\n\tstatic Map<EnumFacing, Quartet<List<IModel3D>, List<IModel3D>, List<IModel3D>, List<IModel3D>>> sideTexturePlate = new HashMap<>();\n\tstatic Map<PipeMount, List<IModel3D>> textureConnectorPlate = new HashMap<>();\n\n\tstatic Map<ScaleObject, IModel3D> scaleMap = new HashMap<>();\n\n\t@Data\n\t@AllArgsConstructor\n\tprivate static class ScaleObject {\n\n\t\tprivate final IModel3D original;\n\t\tprivate final double scale;\n\t}\n\n\tstatic IModel3D innerTransportBox;\n\tpublic static IModel3D highlight;\n\n\tprivate static final List<RenderEntry> pipeFrameRenderList = new ArrayList<>();\n\n\tpublic static TextureTransformation basicPipeTexture;\n\tpublic static TextureTransformation inactiveTexture;\n\tpublic static TextureTransformation glassCenterTexture;\n\tpublic static TextureTransformation innerBoxTexture;\n\tpublic static TextureTransformation statusTexture;\n\tpublic static TextureTransformation statusBCTexture;\n\n\tpublic static void loadModels() {\n\t\tif (!SimpleServiceLocator.cclProxy.isActivated()) return;\n\t\ttry {\n\t\t\tMap<String, IModel3D> pipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/PipeModel_moved.obj\"), 7, new LPScale(1 / 100f));\n\t\t\tList<IModel3D> highlightList = new ArrayList<>();\n\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tLogisticsNewRenderPipe.sideNormal.put(dir, new ArrayList<>());\n\t\t\t\tString grp = \"Side_\" + LogisticsNewRenderPipe.getDirAsString_Type1(dir);\n\t\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t\t.filter(entry -> entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.sideNormal.get(dir).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)))));\n\t\t\t\tif (LogisticsNewRenderPipe.sideNormal.get(dir).size() != 4) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.sideNormal.get(dir).size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tLogisticsNewRenderPipe.sideBC.put(dir, new ArrayList<>());\n\t\t\t\tString grp = \"Side_BC_\" + LogisticsNewRenderPipe.getDirAsString_Type1(dir);\n\t\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t\t.filter(entry -> entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.sideBC.get(dir).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)))));\n\t\t\t\tif (LogisticsNewRenderPipe.sideBC.get(dir).size() != 8) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.sideBC.get(dir).size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (Edge edge : Edge.values()) {\n\t\t\t\tString grp;\n\t\t\t\tif (edge.part1 == EnumFacing.UP || edge.part1 == EnumFacing.DOWN) {\n\t\t\t\t\tgrp = \"Edge_M_\" + LogisticsNewRenderPipe.getDirAsString_Type1(edge.part1) + \"_\" + LogisticsNewRenderPipe.getDirAsString_Type1(edge.part2);\n\t\t\t\t} else {\n\t\t\t\t\tgrp = \"Edge_M_S_\" + LogisticsNewRenderPipe.getDirAsString_Type1(edge.part1) + LogisticsNewRenderPipe.getDirAsString_Type1(edge.part2);\n\t\t\t\t}\n\t\t\t\tfor (Entry<String, IModel3D> entry : pipePartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp)) {\n\t\t\t\t\t\tLogisticsNewRenderPipe.edges.put(edge, LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.edges.get(edge) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + edge.name() + \" (\" + grp + \")\");\n\t\t\t\t}\n\t\t\t\thighlightList.add(LogisticsNewRenderPipe.edges.get(edge));\n\t\t\t}\n\n\t\t\tfor (Corner corner : Corner.values()) {\n\t\t\t\tLogisticsNewRenderPipe.corners_M.put(corner, new ArrayList<>());\n\t\t\t\tString grp = \"Corner_M_\" + corner.ud.s + \"_\" + corner.ns.s + corner.ew.s;\n\t\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t\t.filter(entry -> entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.corners_M.get(corner).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)))));\n\t\t\t\tif (LogisticsNewRenderPipe.corners_M.get(corner).size() != 2) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + corner.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.corners_M.get(corner).size());\n\t\t\t\t}\n\t\t\t\thighlightList.addAll(LogisticsNewRenderPipe.corners_M.get(corner));\n\t\t\t}\n\n\t\t\tfor (Corner corner : Corner.values()) {\n\t\t\t\tLogisticsNewRenderPipe.corners_I3.put(corner, new ArrayList<>());\n\t\t\t\tString grp = \"Corner_I3_\" + corner.ud.s + \"_\" + corner.ns.s + corner.ew.s;\n\t\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t\t.filter(entry -> entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.corners_I3.get(corner).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)))));\n\t\t\t\tif (LogisticsNewRenderPipe.corners_I3.get(corner).size() != 2) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + corner.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.corners_I3.get(corner).size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (PipeSupport support : PipeSupport.values()) {\n\t\t\t\tString grp = \"Support_\" + LogisticsNewRenderPipe.getDirAsString_Type1(support.dir) + \"_\" + support.ori.s;\n\t\t\t\tfor (Entry<String, IModel3D> entry : pipePartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp)) {\n\t\t\t\t\t\tLogisticsNewRenderPipe.supports.put(support, LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.supports.get(support) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + support.name() + \" (\" + grp + \")\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (PipeTurnCorner corner : PipeTurnCorner.values()) {\n\t\t\t\tString grp = \"Corner_I_\" + corner.corner.ud.s + \"_\" + corner.corner.ns.s + corner.corner.ew.s;\n\t\t\t\tfor (Entry<String, IModel3D> entry : pipePartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp)) {\n\t\t\t\t\t\tchar c = ' ';\n\t\t\t\t\t\tif (!entry.getKey().endsWith(\" \" + grp)) {\n\t\t\t\t\t\t\tc = entry.getKey().charAt(entry.getKey().indexOf(\" \" + grp) + (\" \" + grp).length());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (Character.isDigit(c)) {\n\t\t\t\t\t\t\tif (c == '2') {\n\t\t\t\t\t\t\t\tif (corner.turn != Turn.NORTH_SOUTH) {\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (c == '1') {\n\t\t\t\t\t\t\t\tif (corner.turn != Turn.EAST_WEST) {\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (corner.turn != Turn.UP_DOWN) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tLogisticsNewRenderPipe.corners_I.put(corner, LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.corners_I.get(corner) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + corner.name() + \" (\" + grp + \")\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (PipeTurnCorner corner : PipeTurnCorner.values()) {\n\t\t\t\tString grp = \"Spacer\" + corner.number;\n\t\t\t\tfor (Entry<String, IModel3D> entry : pipePartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp)) {\n\t\t\t\t\t\tLogisticsNewRenderPipe.spacers.put(corner, LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.spacers.get(corner) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + corner.name() + \" (\" + grp + \")\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (PipeMount mount : PipeMount.values()) {\n\t\t\t\tString grp = \"Mount_\" + LogisticsNewRenderPipe.getDirAsString_Type1(mount.dir) + \"_\" + LogisticsNewRenderPipe.getDirAsString_Type1(mount.side);\n\t\t\t\tfor (Entry<String, IModel3D> entry : pipePartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp)) {\n\t\t\t\t\t\tLogisticsNewRenderPipe.mounts.put(mount, LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.mounts.get(mount) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + mount.name() + \" (\" + grp + \")\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tLogisticsNewRenderPipe.texturePlate_Inner.put(dir, new ArrayList<>());\n\t\t\t\tString grp = \"Inner_Plate_\" + LogisticsNewRenderPipe.getDirAsString_Type1(dir);\n\t\t\t\tpipePartModels.entrySet().stream().filter(entry -> entry.getKey().contains(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.texturePlate_Inner.get(dir).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)))));\n\t\t\t\tif (LogisticsNewRenderPipe.texturePlate_Inner.get(dir).size() != 2) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.texturePlate_Inner.get(dir).size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tLogisticsNewRenderPipe.texturePlate_Outer.put(dir, new ArrayList<>());\n\t\t\t\tString grp = \"Texture_Plate_\" + LogisticsNewRenderPipe.getDirAsString_Type1(dir);\n\t\t\t\tpipePartModels.entrySet().stream().filter(entry -> entry.getKey().contains(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.texturePlate_Outer.get(dir).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)).apply(new LPTranslation(-0.5, -0.5, -0.5)).apply(new LPScale(1.001D)).apply(new LPTranslation(0.5, 0.5, 0.5)))));\n\t\t\t\tif (LogisticsNewRenderPipe.texturePlate_Outer.get(dir).size() != 2) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.texturePlate_Outer.get(dir).size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tLogisticsNewRenderPipe.sideTexturePlate.put(dir, new Quartet<>(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()));\n\t\t\t\tString grp = \"Texture_Side_\" + LogisticsNewRenderPipe.getDirAsString_Type1(dir);\n\t\t\t\tfor (Entry<String, IModel3D> entry : pipePartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp)) {\n\t\t\t\t\t\tIModel3D model = LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)));\n\t\t\t\t\t\tdouble sizeA = (model.bounds().max().x() - model.bounds().min().x()) + (model.bounds().max().y() - model.bounds().min().y()) + (model.bounds().max().z() - model.bounds().min().z());\n\t\t\t\t\t\tdouble dis = Math.pow(model.bounds().min().x() - 0.5D, 2) + Math.pow(model.bounds().min().y() - 0.5D, 2) + Math.pow(model.bounds().min().z() - 0.5D, 2);\n\t\t\t\t\t\tif (sizeA < 0.5D) {\n\t\t\t\t\t\t\tif ((dis > 0.22 && dis < 0.24) || (dis > 0.38 && dis < 0.40)) {\n\t\t\t\t\t\t\t\tLogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue4().add(model);\n\t\t\t\t\t\t\t} else if ((dis < 0.2 && dis > 0.18) || (dis < 0.36 && dis > 0.34)) {\n\t\t\t\t\t\t\t\tLogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue2().add(model);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Dis: \" + dis);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ((dis > 0.22 && dis < 0.24) || (dis > 0.38 && dis < 0.40)) {\n\t\t\t\t\t\t\t\tLogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue3().add(model);\n\t\t\t\t\t\t\t} else if ((dis < 0.2 && dis > 0.18) || (dis < 0.36 && dis > 0.34)) {\n\t\t\t\t\t\t\t\tLogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue1().add(model);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new UnsupportedOperationException(\"Dis: \" + dis);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue1().size() != 8) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue1().size());\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue2().size() != 8) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue2().size());\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue3().size() != 8) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue3().size());\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue4().size() != 8) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + dir.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue4().size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (PipeMount mount : PipeMount.values()) {\n\t\t\t\tLogisticsNewRenderPipe.textureConnectorPlate.put(mount, new ArrayList<>());\n\t\t\t\tString grp = \"Texture_Connector_\" + LogisticsNewRenderPipe.getDirAsString_Type1(mount.dir) + \"_\" + LogisticsNewRenderPipe.getDirAsString_Type1(mount.side);\n\t\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t\t.filter(entry -> entry.getKey().contains(\" \" + grp + \" \") || entry.getKey().endsWith(\" \" + grp))\n\t\t\t\t\t\t.forEach(entry -> LogisticsNewRenderPipe.textureConnectorPlate.get(mount).add(LogisticsNewRenderPipe.compute(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)))));\n\t\t\t\tif (LogisticsNewRenderPipe.textureConnectorPlate.get(mount).size() != 4) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load \" + mount.name() + \" (\" + grp + \"). Only loaded \" + LogisticsNewRenderPipe.textureConnectorPlate.get(mount).size());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thighlight = SimpleServiceLocator.cclProxy.combine(highlightList);\n\n\t\t\tpipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/PipeModel_Transport_Box.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\tLogisticsNewRenderPipe.innerTransportBox = LogisticsNewRenderPipe.compute(pipePartModels.get(\"InnerTransportBox\").backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)).apply(new LPTranslation(-0.5, -0.5, -0.5)).apply(new LPScale(0.99D)).apply(new LPTranslation(0.5, 0.5, 0.5)));\n\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate static String getDirAsString_Type1(EnumFacing dir) {\n\t\tswitch (dir) {\n\t\t\tcase NORTH:\n\t\t\t\treturn \"N\";\n\t\t\tcase SOUTH:\n\t\t\t\treturn \"S\";\n\t\t\tcase EAST:\n\t\t\t\treturn \"E\";\n\t\t\tcase WEST:\n\t\t\t\treturn \"W\";\n\t\t\tcase UP:\n\t\t\t\treturn \"U\";\n\t\t\tcase DOWN:\n\t\t\t\treturn \"D\";\n\t\t\tdefault:\n\t\t\t\treturn \"UNKNWON\";\n\t\t}\n\t}\n\n\tpublic static IModel3D compute(IModel3D m) {\n\t\tm.computeNormals();\n\t\treturn m;\n\t}\n\n\tpublic static void registerTextures(TextureMap iconRegister) {\n\t\tif (LogisticsNewRenderPipe.basicPipeTexture == null) {\n\t\t\tLogisticsNewRenderPipe.basicPipeTexture = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel\")));\n\t\t\tLogisticsNewRenderPipe.inactiveTexture = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel-inactive\")));\n\t\t\tLogisticsNewRenderPipe.innerBoxTexture = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/InnerBox\")));\n\t\t\tLogisticsNewRenderPipe.glassCenterTexture = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/Glass_Texture_Center\")));\n\t\t\tLogisticsNewRenderPipe.statusTexture = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel-status\")));\n\t\t\tLogisticsNewRenderPipe.statusBCTexture = SimpleServiceLocator.cclProxy.createIconTransformer(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel-status-BC\")));\n\t\t} else {\n\t\t\tLogisticsNewRenderPipe.basicPipeTexture.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel\")));\n\t\t\tLogisticsNewRenderPipe.inactiveTexture.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel-inactive\")));\n\t\t\tLogisticsNewRenderPipe.innerBoxTexture.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/InnerBox\")));\n\t\t\tLogisticsNewRenderPipe.glassCenterTexture.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/Glass_Texture_Center\")));\n\t\t\tLogisticsNewRenderPipe.statusTexture.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel-status\")));\n\t\t\tLogisticsNewRenderPipe.statusBCTexture.update(iconRegister.registerSprite(new ResourceLocation(\"logisticspipes\", \"blocks/pipes/PipeModel-status-BC\")));\n\t\t}\n\t}\n\n\tprivate ClientConfiguration config = LogisticsPipes.getClientPlayerConfig();\n\n\tpublic void renderTileEntityAt(LogisticsTileGenericPipe pipeTile, double x, double y, double z, float partialTickTime, double distance) {\n\t\tboolean inHand = false;\n\t\tif (pipeTile == null) return;\n\t\tif (pipeTile.pipe == null) return;\n\t\tif (pipeTile.pipe.isPipeBlock()) return;\n\t\tPipeRenderState renderState = pipeTile.renderState;\n\n\t\tif (renderState.renderLists != null && renderState.renderLists.values().stream().anyMatch(GLRenderList::isInvalid)) {\n\t\t\trenderState.renderLists = null;\n\t\t}\n\n\t\tif (renderState.renderLists == null) {\n\t\t\trenderState.renderLists = new HashMap<>();\n\t\t}\n\n\t\tif (distance > config.getRenderPipeDistance() * config.getRenderPipeDistance()) {\n\t\t\t/*if (config.isUseFallbackRenderer()) {\n\t\t\t\trenderState.forceRenderOldPipe = true;\n\t\t\t}*/\n\t\t} else {\n\t\t\trenderState.forceRenderOldPipe = false;\n\t\t\tboolean recalculateList = checkAndCalculateRenderCache(pipeTile);\n\t\t\trenderList(x, y, z, renderState.renderLists, renderState.cachedRenderer, recalculateList);\n\t\t\tif (recalculateList) {\n\t\t\t\tpipeTile.getWorld().markBlockRangeForRenderUpdate(pipeTile.getPos(), pipeTile.getPos());\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static boolean checkAndCalculateRenderCache(LogisticsTileGenericPipe pipeTile) {\n\t\tPipeRenderState renderState = pipeTile.renderState;\n\n\t\tif (renderState.cachedRenderIndex != MainProxy.proxy.getRenderIndex()) {\n\t\t\trenderState.clearRenderCaches();\n\t\t}\n\n\t\tif (renderState.cachedRenderer == null) {\n\t\t\tArrayList<RenderEntry> objectsToRender = new ArrayList<>();\n\n\t\t\tif (pipeTile.pipe != null && pipeTile.pipe.actAsNormalPipe()) {\n\t\t\t\tfillObjectsToRenderList(objectsToRender, pipeTile, renderState);\n\t\t\t}\n\t\t\tif (pipeTile.pipe != null && pipeTile.pipe.getSpecialRenderer() != null) {\n\t\t\t\tpipeTile.pipe.getSpecialRenderer().renderToList(pipeTile.pipe, objectsToRender);\n\t\t\t}\n\n\t\t\trenderState.cachedRenderIndex = MainProxy.proxy.getRenderIndex();\n\t\t\trenderState.cachedRenderer = Collections.unmodifiableList(objectsToRender);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate static void renderList(double x, double y, double z, Map<ResourceLocation, GLRenderList> renderLists, List<RenderEntry> cachedRenderer, boolean recalculateList) {\n\t\tif (renderLists.isEmpty() || !renderLists.values().stream().allMatch(GLRenderList::isFilled) || recalculateList) {\n\t\t\tMap<ResourceLocation, List<RenderEntry>> sorted = new HashMap<>();\n\t\t\tfor (RenderEntry model : cachedRenderer) {\n\t\t\t\tif (!sorted.containsKey(model.getTexture())) {\n\t\t\t\t\tsorted.put(model.getTexture(), new LinkedList<>());\n\t\t\t\t}\n\t\t\t\tsorted.get(model.getTexture()).add(model);\n\t\t\t}\n\n\t\t\tfor (Entry<ResourceLocation, List<RenderEntry>> entries : sorted.entrySet()) {\n\t\t\t\tif (entries.getKey().equals(TextureMap.LOCATION_BLOCKS_TEXTURE)) continue;\n\t\t\t\tif (!renderLists.containsKey(entries.getKey())) {\n\t\t\t\t\trenderLists.put(entries.getKey(), SimpleServiceLocator.renderListHandler.getNewRenderList());\n\t\t\t\t}\n\t\t\t\tGLRenderList renderList = renderLists.get(entries.getKey());\n\t\t\t\tif (renderList.isFilled() && !recalculateList) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\trenderList.startListCompile();\n\n\t\t\t\tSimpleServiceLocator.cclProxy.getRenderState().reset();\n\t\t\t\tSimpleServiceLocator.cclProxy.getRenderState().startDrawing(GL11.GL_QUADS, DefaultVertexFormats.OLDMODEL_POSITION_TEX_NORMAL);\n\n\t\t\t\tfor (RenderEntry entry : entries.getValue()) {\n\t\t\t\t\tentry.getModel().render(entry.getOperations());\n\t\t\t\t}\n\n\t\t\t\tSimpleServiceLocator.cclProxy.getRenderState().draw();\n\t\t\t\trenderList.stopCompile();\n\t\t\t}\n\t\t}\n\t\tif (!renderLists.isEmpty()) {\n\t\t\tGL11.glPushMatrix();\n\t\t\tGL11.glTranslated(x, y, z);\n\t\t\tGL11.glEnable(GL11.GL_BLEND);\n\t\t\tGL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);\n\t\t\tfor (Entry<ResourceLocation, GLRenderList> entry : renderLists.entrySet()) {\n\t\t\t\tMinecraft.getMinecraft().getTextureManager().bindTexture(entry.getKey());\n\t\t\t\tentry.getValue().render();\n\t\t\t}\n\t\t\tGL11.glDisable(GL11.GL_BLEND);\n\t\t\tGL11.glPopMatrix();\n\t\t}\n\t}\n\n\tprivate static void fillObjectsToRenderList(List<RenderEntry> objectsToRender, LogisticsTileGenericPipe pipeTile, PipeRenderState renderState) {\n\t\tList<Edge> edgesToRender = new ArrayList<>(Arrays.asList(Edge.values()));\n\t\tMap<Corner, Integer> connectionAtCorner = new HashMap<>();\n\t\tList<PipeMount> mountCanidates = new ArrayList<>(Arrays.asList(PipeMount.values()));\n\n\t\tint connectionCount = 0;\n\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (renderState.pipeConnectionMatrix.isConnected(dir) || pipeTile.pipe.hasSpecialPipeEndAt(dir)) {\n\t\t\t\tconnectionCount++;\n\t\t\t\tif (renderState.pipeConnectionMatrix.isTDConnected(dir) || renderState.pipeConnectionMatrix.isBCConnected(dir)) {\n\t\t\t\t\tI3DOperation[] texture = new I3DOperation[] { LogisticsNewRenderPipe.basicPipeTexture };\n\t\t\t\t\tif (renderState.textureMatrix.isRouted()) {\n\t\t\t\t\t\tif (renderState.textureMatrix.isRoutedInDir(dir)) {\n\t\t\t\t\t\t\tif (renderState.textureMatrix.isSubPowerInDir(dir)) {\n\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(0, +23F / 100), LogisticsNewRenderPipe.statusBCTexture) };\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { LogisticsNewRenderPipe.statusBCTexture };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(0, -23F / 100), LogisticsNewRenderPipe.statusBCTexture) };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.sideBC.get(dir)) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(model, texture));\n\t\t\t\t\t}\n\t\t\t\t} else if (!pipeTile.pipe.hasSpecialPipeEndAt(dir)) {\n\t\t\t\t\tI3DOperation[] texture = new I3DOperation[] { LogisticsNewRenderPipe.basicPipeTexture };\n\t\t\t\t\tif (renderState.textureMatrix.isRouted()) {\n\t\t\t\t\t\tif (renderState.textureMatrix.isRoutedInDir(dir)) {\n\t\t\t\t\t\t\tif (renderState.textureMatrix.isSubPowerInDir(dir)) {\n\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(-2.5F / 10, 0), LogisticsNewRenderPipe.statusTexture) };\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { LogisticsNewRenderPipe.statusTexture };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (renderState.textureMatrix.isHasPowerUpgrade()) {\n\t\t\t\t\t\t\t\tif (renderState.textureMatrix.getPointedOrientation() == dir) {\n\t\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(+2.5F / 10, 0), LogisticsNewRenderPipe.statusTexture) };\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(-2.5F / 10, 37F / 100), LogisticsNewRenderPipe.statusTexture) };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (renderState.textureMatrix.getPointedOrientation() == dir) {\n\t\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(+2.5F / 10, 37F / 100), LogisticsNewRenderPipe.statusTexture) };\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttexture = new I3DOperation[] { new LPUVTransformationList(new LPUVTranslation(0, 37F / 100), LogisticsNewRenderPipe.statusTexture) };\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.sideNormal.get(dir)) {\n\t\t\t\t\t\tdouble[] bounds = { Block.FULL_BLOCK_AABB.minY, Block.FULL_BLOCK_AABB.minZ, Block.FULL_BLOCK_AABB.minX, Block.FULL_BLOCK_AABB.maxY, Block.FULL_BLOCK_AABB.maxZ, Block.FULL_BLOCK_AABB.maxX };\n\t\t\t\t\t\tif (pipeTile.getWorld() != null) { //This can be null in some cases now !!!\n\t\t\t\t\t\t\tDoubleCoordinates coords = CoordinateUtils.add(new DoubleCoordinates((TileEntity) pipeTile), dir);\n\t\t\t\t\t\t\tIBlockState blockState = coords.getBlockState(pipeTile.getWorld());\n\t\t\t\t\t\t\tAxisAlignedBB bb = blockState.getCollisionBoundingBox(pipeTile.getWorld(), coords.getBlockPos());\n\t\t\t\t\t\t\tif (bb == null) bb = Block.FULL_BLOCK_AABB;\n\t\t\t\t\t\t\tbounds = new double[] { bb.minY, bb.minZ, bb.minX, bb.maxY, bb.maxZ, bb.maxX };\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdouble bound = bounds[dir.ordinal() / 2 + (dir.ordinal() % 2 == 0 ? 3 : 0)];\n\t\t\t\t\t\tScaleObject key = new ScaleObject(model, bound);\n\t\t\t\t\t\tIModel3D model2 = LogisticsNewRenderPipe.scaleMap.get(key);\n\t\t\t\t\t\tif (model2 == null) {\n\t\t\t\t\t\t\tmodel2 = model.copy();\n\t\t\t\t\t\t\tIVec3 min = model2.bounds().min();\n\t\t\t\t\t\t\tmodel2.apply(new LPTranslation(min).inverse());\n\t\t\t\t\t\t\tdouble toAdd;\n\t\t\t\t\t\t\tif (dir.ordinal() % 2 == 1) {\n\t\t\t\t\t\t\t\ttoAdd = 1 + (bound / LPConstants.PIPE_MIN_POS);\n\t\t\t\t\t\t\t\tmodel2.apply(new LPScale(dir.getDirectionVec().getX() != 0 ? toAdd : 1, dir.getDirectionVec().getY() != 0 ? toAdd : 1, dir.getDirectionVec().getZ() != 0 ? toAdd : 1));\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tbound = 1 - bound;\n\t\t\t\t\t\t\t\ttoAdd = 1 + (bound / LPConstants.PIPE_MIN_POS);\n\t\t\t\t\t\t\t\tmodel2.apply(new LPScale(dir.getDirectionVec().getX() != 0 ? toAdd : 1, dir.getDirectionVec().getY() != 0 ? toAdd : 1, dir.getDirectionVec().getZ() != 0 ? toAdd : 1));\n\t\t\t\t\t\t\t\tmodel2.apply(new LPTranslation(dir.getDirectionVec().getX() * bound, dir.getDirectionVec().getY() * bound, dir.getDirectionVec().getZ() * bound));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmodel2.apply(new LPTranslation(min));\n\t\t\t\t\t\t\tLogisticsNewRenderPipe.scaleMap.put(key, model2);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(model2, texture));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (Edge edge : Edge.values()) {\n\t\t\t\t\tif (edge.part1 == dir || edge.part2 == dir) {\n\t\t\t\t\t\tedgesToRender.remove(edge);\n\t\t\t\t\t\tfor (PipeMount mount : PipeMount.values()) {\n\t\t\t\t\t\t\tif ((mount.dir == edge.part1 && mount.side == edge.part2) || (mount.dir == edge.part2 && mount.side == edge.part1)) {\n\t\t\t\t\t\t\t\tmountCanidates.remove(mount);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (Corner corner : Corner.values()) {\n\t\t\t\t\tif (corner.ew.dir == dir || corner.ns.dir == dir || corner.ud.dir == dir) {\n\t\t\t\t\t\tif (!connectionAtCorner.containsKey(corner)) {\n\t\t\t\t\t\t\tconnectionAtCorner.put(corner, 1);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconnectionAtCorner.put(corner, connectionAtCorner.get(corner) + 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (Corner corner : Corner.values()) {\n\t\t\tTextureTransformation cornerTexture = LogisticsNewRenderPipe.basicPipeTexture;\n\t\t\tif (!renderState.textureMatrix.isHasPower() && renderState.textureMatrix.isRouted()) {\n\t\t\t\tcornerTexture = LogisticsNewRenderPipe.inactiveTexture;\n\t\t\t} else if (!renderState.textureMatrix.isRouted() && connectionCount > 2) {\n\t\t\t\tcornerTexture = LogisticsNewRenderPipe.inactiveTexture;\n\t\t\t}\n\t\t\tint count = connectionAtCorner.containsKey(corner) ? connectionAtCorner.get(corner) : 0;\n\t\t\tif (count == 0) {\n\t\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.corners_M.get(corner)) {\n\t\t\t\t\tobjectsToRender.add(new RenderEntry(model, cornerTexture));\n\t\t\t\t}\n\t\t\t} else if (count == 1) {\n\t\t\t\tfor (PipeTurnCorner turn : PipeTurnCorner.values()) {\n\t\t\t\t\tif (turn.corner != corner) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (renderState.pipeConnectionMatrix.isConnected(turn.getPointer()) || pipeTile.pipe.hasSpecialPipeEndAt(turn.getPointer())) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.spacers.get(turn), cornerTexture));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (count == 2) {\n\t\t\t\tfor (PipeTurnCorner turn : PipeTurnCorner.values()) {\n\t\t\t\t\tif (turn.corner != corner) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!renderState.pipeConnectionMatrix.isConnected(turn.getPointer()) || pipeTile.pipe.hasSpecialPipeEndAt(turn.getPointer())) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.corners_I.get(turn), cornerTexture));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (count == 3) {\n\t\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.corners_I3.get(corner)) {\n\t\t\t\t\tobjectsToRender.add(new RenderEntry(model, cornerTexture));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tedgesToRender.stream()\n\t\t\t\t.map(edge -> new RenderEntry(LogisticsNewRenderPipe.edges.get(edge), LogisticsNewRenderPipe.basicPipeTexture))\n\t\t\t\t.forEach(objectsToRender::add);\n\n\t\tfor (int i = 0; i < 6; i += 2) {\n\t\t\tEnumFacing dir = EnumFacing.byIndex(i);\n\t\t\tList<EnumFacing> list = new ArrayList<>(Arrays.asList(EnumFacing.VALUES));\n\t\t\tlist.remove(dir);\n\t\t\tlist.remove(dir.getOpposite());\n\t\t\tif (renderState.pipeConnectionMatrix.isConnected(dir) && renderState.pipeConnectionMatrix.isConnected(dir.getOpposite())) {\n\t\t\t\tboolean found = false;\n\t\t\t\tfor (EnumFacing dir2 : list) {\n\t\t\t\t\tif (renderState.pipeConnectionMatrix.isConnected(dir2)) {\n\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!found) {\n\t\t\t\t\tswitch (dir) {\n\t\t\t\t\t\tcase DOWN:\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.EAST_SIDE), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.WEST_SIDE), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.NORTH_SIDE), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.SOUTH_SIDE), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase NORTH:\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.EAST_UP), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.WEST_UP), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.UP_SIDE), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.DOWN_SIDE), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase WEST:\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.UP_UP), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.DOWN_UP), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.NORTH_UP), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.supports.get(PipeSupport.SOUTH_UP), LogisticsNewRenderPipe.basicPipeTexture));\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tboolean[] solidSides = new boolean[6];\n\t\tif (pipeTile.getWorld() != null) { // This can be null in some cases now !!!\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tDoubleCoordinates pos = CoordinateUtils.add(new DoubleCoordinates((TileEntity) pipeTile), dir);\n\t\t\t\tIBlockState blockState = pos.getBlockState(pipeTile.getWorld());\n\t\t\t\tif (blockState.getBlock().isAir(blockState, pipeTile.getWorld(), pos.getBlockPos()) ||\n\t\t\t\t\t\t!blockState.isSideSolid(pipeTile.getWorld(), pos.getBlockPos(), dir.getOpposite()) ||\n\t\t\t\t\t\trenderState.pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\t\tmountCanidates.removeIf(mount -> mount.dir == dir);\n\t\t\t\t} else {\n\t\t\t\t\tsolidSides[dir.ordinal()] = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tmountCanidates.removeIf(mount -> SimpleServiceLocator.mcmpProxy.hasParts(pipeTile));\n\t\t} else {\n\t\t\tmountCanidates.clear();\n\t\t}\n\n\t\tif (!mountCanidates.isEmpty()) {\n\t\t\tif (solidSides[EnumFacing.DOWN.ordinal()]) {\n\t\t\t\tfindOponentOnSameSide(mountCanidates, EnumFacing.DOWN);\n\t\t\t} else if (solidSides[EnumFacing.UP.ordinal()]) {\n\t\t\t\tfindOponentOnSameSide(mountCanidates, EnumFacing.UP);\n\t\t\t} else {\n\t\t\t\tremoveFromSide(mountCanidates, EnumFacing.DOWN);\n\t\t\t\tremoveFromSide(mountCanidates, EnumFacing.UP);\n\t\t\t\tif (mountCanidates.size() > 2) {\n\t\t\t\t\tremoveIfHasOponentSide(mountCanidates);\n\t\t\t\t}\n\t\t\t\tif (mountCanidates.size() > 2) {\n\t\t\t\t\tremoveIfHasConnectedSide(mountCanidates);\n\t\t\t\t}\n\t\t\t\tif (mountCanidates.size() > 2) {\n\t\t\t\t\tfindOponentOnSameSide(mountCanidates, mountCanidates.get(0).dir);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (LogisticsPipes.isDEBUG() && mountCanidates.size() > 2) {\n\t\t\t\tnew RuntimeException(\"Trying to render \" + mountCanidates.size() + \" Mounts\").printStackTrace();\n\t\t\t}\n\n\t\t\tmountCanidates.stream()\n\t\t\t\t\t.map(mount -> new RenderEntry(LogisticsNewRenderPipe.mounts.get(mount), LogisticsNewRenderPipe.basicPipeTexture))\n\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t}\n\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tif (!renderState.pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\tfor (IModel3D model : LogisticsNewRenderPipe.texturePlate_Outer.get(dir)) {\n\t\t\t\t\tTextureTransformation icon = Textures.LPnewPipeIconProvider.getIcon(renderState.textureMatrix.getTextureIndex());\n\t\t\t\t\tif (icon != null) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(model, new LPUVTransformationList(new LPUVScale(12f / 16, 12f / 16), icon)));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (renderState.textureMatrix.isFluid()) {\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tif (!renderState.pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\t\tLogisticsNewRenderPipe.texturePlate_Inner.get(dir).stream()\n\t\t\t\t\t\t\t.map(model -> new RenderEntry(model, new I3DOperation[] { LogisticsNewRenderPipe.glassCenterTexture }))\n\t\t\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t\t\t} else {\n\t\t\t\t\tif (!renderState.textureMatrix.isRoutedInDir(dir)) {\n\t\t\t\t\t\tLogisticsNewRenderPipe.sideTexturePlate.get(dir).getValue1().stream()\n\t\t\t\t\t\t\t\t.map(model -> new RenderEntry(model, new I3DOperation[] { LogisticsNewRenderPipe.basicPipeTexture }))\n\t\t\t\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tSimpleServiceLocator.thermalDynamicsProxy.renderPipeConnections(pipeTile, objectsToRender);\n\t}\n\n\tprivate static void findOponentOnSameSide(List<PipeMount> mountCanidates, EnumFacing dir) {\n\t\tboolean[] sides = new boolean[6];\n\t\tIterator<PipeMount> iter = mountCanidates.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tPipeMount mount = iter.next();\n\t\t\tif (mount.dir != dir) {\n\t\t\t\titer.remove();\n\t\t\t} else {\n\t\t\t\tsides[mount.side.ordinal()] = true;\n\t\t\t}\n\t\t}\n\t\tif (mountCanidates.size() <= 2) {\n\t\t\treturn;\n\t\t}\n\t\tList<EnumFacing> keep = new ArrayList<>();\n\t\tif (sides[2] && sides[3]) {\n\t\t\tkeep.add(EnumFacing.NORTH);\n\t\t\tkeep.add(EnumFacing.SOUTH);\n\t\t} else if (sides[4] && sides[5]) {\n\t\t\tkeep.add(EnumFacing.EAST);\n\t\t\tkeep.add(EnumFacing.WEST);\n\t\t} else if (sides[0] && sides[1]) {\n\t\t\tkeep.add(EnumFacing.UP);\n\t\t\tkeep.add(EnumFacing.DOWN);\n\t\t}\n\t\titer = mountCanidates.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tPipeMount mount = iter.next();\n\t\t\tif (!keep.contains(mount.side)) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static void removeFromSide(List<PipeMount> mountCanidates, EnumFacing dir) {\n\t\tmountCanidates.removeIf(mount -> mount.dir == dir);\n\t}\n\n\tprivate static void reduceToOnePerSide(List<PipeMount> mountCanidates, EnumFacing dir, EnumFacing pref) {\n\t\tboolean found = false;\n\t\tfor (PipeMount mount : mountCanidates) {\n\t\t\tif (mount.dir != dir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (mount.side == pref) {\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found) {\n\t\t\treduceToOnePerSide(mountCanidates, dir);\n\t\t} else {\n\t\t\tIterator<PipeMount> iter = mountCanidates.iterator();\n\t\t\twhile (iter.hasNext()) {\n\t\t\t\tPipeMount mount = iter.next();\n\t\t\t\tif (mount.dir != dir) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mount.side != pref) {\n\t\t\t\t\titer.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static void reduceToOnePerSide(List<PipeMount> mountCanidates, EnumFacing dir) {\n\t\tboolean found = false;\n\t\tIterator<PipeMount> iter = mountCanidates.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tPipeMount mount = iter.next();\n\t\t\tif (mount.dir != dir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (found) {\n\t\t\t\titer.remove();\n\t\t\t} else {\n\t\t\t\tfound = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static void removeIfHasOponentSide(List<PipeMount> mountCanidates) {\n\t\tboolean[] sides = new boolean[6];\n\t\tfor (PipeMount mount : mountCanidates) {\n\t\t\tsides[mount.dir.ordinal()] = true;\n\t\t}\n\t\tif (sides[2] && sides[3]) {\n\t\t\tremoveFromSide(mountCanidates, EnumFacing.EAST);\n\t\t\tremoveFromSide(mountCanidates, EnumFacing.WEST);\n\t\t\treduceToOnePerSide(mountCanidates, EnumFacing.NORTH);\n\t\t\treduceToOnePerSide(mountCanidates, EnumFacing.SOUTH);\n\t\t} else if (sides[4] && sides[5]) {\n\t\t\tremoveFromSide(mountCanidates, EnumFacing.NORTH);\n\t\t\tremoveFromSide(mountCanidates, EnumFacing.SOUTH);\n\t\t\treduceToOnePerSide(mountCanidates, EnumFacing.EAST);\n\t\t\treduceToOnePerSide(mountCanidates, EnumFacing.WEST);\n\t\t}\n\t}\n\n\tprivate static void removeIfHasConnectedSide(List<PipeMount> mountCanidates) {\n\t\tboolean[] sides = new boolean[6];\n\t\tfor (PipeMount mount : mountCanidates) {\n\t\t\tsides[mount.dir.ordinal()] = true;\n\t\t}\n\t\tfor (int i = 2; i < 6; i++) {\n\t\t\tEnumFacing dir = EnumFacing.byIndex(i);\n\t\t\tEnumFacing rot = dir.rotateY();\n\t\t\tif (sides[dir.ordinal()] && sides[rot.ordinal()]) {\n\t\t\t\treduceToOnePerSide(mountCanidates, dir, dir.rotateYCCW());\n\t\t\t\treduceToOnePerSide(mountCanidates, rot, rot.rotateY());\n\t\t\t}\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic static void renderDestruction(CoreUnroutedPipe pipe, World world, int x, int y, int z, ParticleManager effectRenderer) {\n\t\tif (pipe.container != null && pipe.container.renderState != null && pipe.container.renderState.cachedRenderer != null) {\n\t\t\tfor (RenderEntry entry : pipe.container.renderState.cachedRenderer) {\n\t\t\t\tIModel3D model = entry.getModel().twoFacedCopy();\n\t\t\t\tIBounds bounds = model.bounds();\n\t\t\t\tdouble xMid = (bounds.min().x() + bounds.max().x()) / 2;\n\t\t\t\tdouble yMid = (bounds.min().y() + bounds.max().y()) / 2;\n\t\t\t\tdouble zMid = (bounds.min().z() + bounds.max().z()) / 2;\n\t\t\t\tmodel.apply(new LPTranslation(-xMid, -yMid, -zMid));\n\t\t\t\teffectRenderer.addEffect(new EntityModelFX(world, x + xMid, y + yMid, z + zMid, model, entry.getOperations(), entry.getTexture()));\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static void renderBoxWithDir(EnumFacing dir) {\n\t\tList<RenderEntry> objectsToRender = new ArrayList<>();\n\t\tList<Edge> edgesToRender = new ArrayList<>(Arrays.asList(Edge.values()));\n\t\tMap<Corner, Integer> connectionAtCorner = new HashMap<>();\n\n\t\tfor (Edge edge : Edge.values()) {\n\t\t\tif (edge.part1 == dir || edge.part2 == dir) {\n\t\t\t\tedgesToRender.remove(edge);\n\t\t\t}\n\t\t}\n\t\tfor (Corner corner : Corner.values()) {\n\t\t\tif (corner.ew.dir == dir || corner.ns.dir == dir || corner.ud.dir == dir) {\n\t\t\t\tif (!connectionAtCorner.containsKey(corner)) {\n\t\t\t\t\tconnectionAtCorner.put(corner, 1);\n\t\t\t\t} else {\n\t\t\t\t\tconnectionAtCorner.put(corner, connectionAtCorner.get(corner) + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (Corner corner : Corner.values()) {\n\t\t\tTextureTransformation cornerTexture = LogisticsNewRenderPipe.basicPipeTexture;\n\t\t\tint count = connectionAtCorner.getOrDefault(corner, 0);\n\t\t\tif (count == 0) {\n\t\t\t\tLogisticsNewRenderPipe.corners_M.get(corner).stream()\n\t\t\t\t\t\t.map(model -> new RenderEntry(model, new I3DOperation[] { cornerTexture }))\n\t\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t\t} else if (count == 1) {\n\t\t\t\tfor (PipeTurnCorner turn : PipeTurnCorner.values()) {\n\t\t\t\t\tif (turn.corner != corner) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (turn.getPointer() == dir) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.spacers.get(turn), cornerTexture));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (count == 2) {\n\t\t\t\tfor (PipeTurnCorner turn : PipeTurnCorner.values()) {\n\t\t\t\t\tif (turn.corner != corner) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (turn.getPointer() == dir) {\n\t\t\t\t\t\tobjectsToRender.add(new RenderEntry(LogisticsNewRenderPipe.corners_I.get(turn), cornerTexture));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (count == 3) {\n\t\t\t\tLogisticsNewRenderPipe.corners_I3.get(corner).stream()\n\t\t\t\t\t\t.map(model -> new RenderEntry(model, new I3DOperation[] { cornerTexture }))\n\t\t\t\t\t\t.forEach(objectsToRender::add);\n\t\t\t}\n\t\t}\n\n\t\tedgesToRender.stream()\n\t\t\t\t.map(edge -> new RenderEntry(LogisticsNewRenderPipe.edges.get(edge), LogisticsNewRenderPipe.basicPipeTexture))\n\t\t\t\t.forEach(objectsToRender::add);\n\t\tfor (RenderEntry model : objectsToRender) {\n\t\t\tmodel.getModel().render(model.getOperations());\n\t\t}\n\t}\n\n\t@Nonnull\n\tpublic ArrayList<BakedQuad> getQuadsFromRenderList(List<RenderEntry> renderEntryList, VertexFormat format, boolean skipNonBlockTextures) {\n\t\tArrayList<BakedQuad> quads = Lists.newArrayList();\n\t\tfor (RenderEntry model : renderEntryList) {\n\t\t\tResourceLocation texture = model.getTexture();\n\t\t\tif (texture == null) {\n\t\t\t\tthrow new NullPointerException();\n\t\t\t}\n\t\t\tif (texture.equals(TextureMap.LOCATION_BLOCKS_TEXTURE)) {\n\t\t\t\tquads.addAll(model.getModel().renderToQuads(format, model.getOperations()));\n\t\t\t}\n\t\t}\n\t\treturn quads;\n\t}\n\n\t@Override\n\tpublic void renderHighlight(ITubeOrientation orientation) {\n\t\thighlight.render(LPColourMultiplier.instance(0xFFFFFFFF));\n\t}\n\n\tpublic static List<RenderEntry> getBasicPipeFrameRenderList() {\n\t\tif (pipeFrameRenderList.isEmpty()) {\n\t\t\tLogisticsTileGenericPipe pipe = new LogisticsTileGenericPipe();\n\t\t\tpipe.pipe = new PipeItemsBasicLogistics(null);\n\t\t\tfillObjectsToRenderList(pipeFrameRenderList, pipe, pipe.renderState);\n\t\t}\n\t\treturn pipeFrameRenderList;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/LogisticsNewSolidBlockWorldRenderer.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Map.Entry;\n\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPRotation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.proxy.object3d.operation.LPUVScale;\n\npublic class LogisticsNewSolidBlockWorldRenderer {\n\n\tenum CoverSides {\n\t\tDOWN(EnumFacing.DOWN, \"D\"),\n\t\tNORTH(EnumFacing.NORTH, \"N\"),\n\t\tSOUTH(EnumFacing.SOUTH, \"S\"),\n\t\tWEST(EnumFacing.WEST, \"W\"),\n\t\tEAST(EnumFacing.EAST, \"E\");\n\n\t\tprivate EnumFacing dir;\n\t\t@Getter\n\t\tprivate String letter;\n\n\t\tCoverSides(EnumFacing dir, String letter) {\n\t\t\tthis.dir = dir;\n\t\t\tthis.letter = letter;\n\t\t}\n\n\t\tpublic EnumFacing getDir(BlockRotation rot) {\n\t\t\tEnumFacing result = dir;\n\t\t\tif (result != EnumFacing.DOWN) {\n\t\t\t\tswitch (rot.getInteger()) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tresult = result.rotateY();\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tresult = result.rotateY();\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tresult = result.rotateY();\n\t\t\t\t\tcase 2:\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tenum BlockRotation {\n\t\tZERO(0),\n\t\tONE(1),\n\t\tTWO(2),\n\t\tTHREE(3);\n\n\t\t@Getter\n\t\tprivate int integer;\n\n\t\tBlockRotation(int rot) {\n\t\t\tinteger = rot;\n\t\t}\n\n\t\tstatic BlockRotation getRotation(int from) {\n\t\t\tfor (BlockRotation rot : BlockRotation.values()) {\n\t\t\t\tif (rot.getInteger() == from) {\n\t\t\t\t\treturn rot;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tstatic Map<BlockRotation, IModel3D> block = new HashMap<>();\n\tstatic Map<CoverSides, Map<BlockRotation, IModel3D>> texturePlate_Inner = new HashMap<>();\n\tstatic Map<CoverSides, Map<BlockRotation, IModel3D>> texturePlate_Outer = new HashMap<>();\n\n\tpublic static void loadModels() {\n\t\tif (!SimpleServiceLocator.cclProxy.isActivated()) return;\n\t\ttry {\n\t\t\tMap<String, IModel3D> blockPartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/BlockModel_result.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\tLogisticsNewSolidBlockWorldRenderer.block = null;\n\t\t\tfor (Entry<String, IModel3D> entry : blockPartModels.entrySet()) {\n\t\t\t\tif (entry.getKey().contains(\" Block \")) {\n\t\t\t\t\tif (LogisticsNewSolidBlockWorldRenderer.block != null) {\n\t\t\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t\t\t}\n\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.block = LogisticsNewSolidBlockWorldRenderer.computeRotated(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0)));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.clear();\n\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Inner.clear();\n\t\t\tfor (CoverSides side : CoverSides.values()) {\n\t\t\t\tString grp_Outer = \"OutSide_\" + side.getLetter();\n\t\t\t\tString grp_Inside = \"Inside_\" + side.getLetter();\n\t\t\t\tfor (Entry<String, IModel3D> entry : blockPartModels.entrySet()) {\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp_Outer + \" \")) {\n\t\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.put(side, LogisticsNewSolidBlockWorldRenderer.computeRotated(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t}\n\t\t\t\t\tif (entry.getKey().contains(\" \" + grp_Inside + \" \")) {\n\t\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Inner.put(side, LogisticsNewSolidBlockWorldRenderer.computeRotated(entry.getValue().backfacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load OutSide \" + side.name() + \" (\" + grp_Outer + \").\");\n\t\t\t\t}\n\t\t\t\tif (LogisticsNewSolidBlockWorldRenderer.texturePlate_Inner.get(side) == null) {\n\t\t\t\t\tthrow new RuntimeException(\"Couldn't load OutSide \" + side.name() + \" (\" + grp_Outer + \").\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tprivate static Map<BlockRotation, IModel3D> computeRotated(IModel3D m) {\n\t\tm.apply(new LPUVScale(1, 0.75));\n\t\tMap<BlockRotation, IModel3D> map = new HashMap<>();\n\t\tfor (BlockRotation rot : BlockRotation.values()) {\n\t\t\tIModel3D model = m.copy();\n\t\t\tswitch (rot.getInteger()) {\n\t\t\t\tcase 0:\n\t\t\t\t\tmodel.apply(LPRotation.sideOrientation(0, 3));\n\t\t\t\t\tmodel.apply(new LPTranslation(0, 0, 1));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tmodel.apply(LPRotation.sideOrientation(0, 1));\n\t\t\t\t\tmodel.apply(new LPTranslation(1, 0, 0));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tmodel.apply(LPRotation.sideOrientation(0, 2));\n\t\t\t\t\tmodel.apply(new LPTranslation(1, 0, 1));\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmodel.computeNormals();\n\t\t\tmodel.computeStandardLighting();\n\t\t\tmap.put(rot, model);\n\t\t}\n\t\treturn map;\n\t}\n/*\n\tpublic void renderWorldBlock(IBlockAccess world, LogisticsSolidTileEntity blockTile, RenderBlocks renderer, int x, int y, int z) {\n\t\tTessellator tess = Tessellator.instance;\n\t\tSimpleServiceLocator.cclProxy.getRenderState().reset();\n\t\tSimpleServiceLocator.cclProxy.getRenderState().setUseNormals(true);\n\t\tSimpleServiceLocator.cclProxy.getRenderState().setAlphaOverride(0xff);\n\n\t\tBlockRotation rotation = BlockRotation.ZERO;\n\t\tint brightness = 0;\n\t\tIIconTransformation icon;\n\t\tif(blockTile != null) {\n\t\t\tBlockRotation.getRotation(blockTile.getRotation());\n\t\t\tbrightness = new DoubleCoordinates(blockTile).getBlock(world).getMixedBrightnessForBlock(world, blockTile.xCoord, blockTile.yCoord, blockTile.zCoord);\n\t\t\ticon = SimpleServiceLocator.cclProxy.createIconTransformer(LogisticsSolidBlock.getNewIcon(world, blockTile.xCoord, blockTile.yCoord, blockTile.zCoord));\n\t\t} else {\n\t\t\tbrightness = LogisticsPipes.LogisticsSolidBlock.getMixedBrightnessForBlock(world, x, y, z);\n\t\t\ticon = SimpleServiceLocator.cclProxy.createIconTransformer(LogisticsSolidBlock.getNewIcon(world, x, y, z));\n\t\t}\n\n\n\t\ttess.setColorOpaque_F(1F, 1F, 1F);\n\t\ttess.setBrightness(brightness);\n\n\t\t//Draw\n\t\tLogisticsNewSolidBlockWorldRenderer.block.get(rotation).render(new LPTranslation(x, y, z), icon);\n\t\tif(blockTile != null) {\n\t\t\tDoubleCoordinates pos = new DoubleCoordinates(blockTile);\n\t\t\tfor (CoverSides side : CoverSides.values()) {\n\t\t\t\tboolean render = true;\n\t\t\t\tDoubleCoordinates newPos = CoordinateUtils.sum(pos, side.getDir(rotation));\n\t\t\t\tTileEntity sideTile = newPos.getTileEntity(blockTile.getworld());\n\t\t\t\tif (sideTile instanceof LogisticsTileGenericPipe) {\n\t\t\t\t\tLogisticsTileGenericPipe tilePipe = (LogisticsTileGenericPipe) sideTile;\n\t\t\t\t\tif (tilePipe.renderState.pipeConnectionMatrix.isConnected(side.getDir(rotation).getOpposite())) {\n\t\t\t\t\t\trender = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (render) {\n\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation).render(new LPTranslation(x, y, z), icon);\n\t\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Inner.get(side).get(rotation).render(new LPTranslation(x, y, z), icon);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t}\n\n\tpublic void renderInventoryBlock(Block block2, int metadata) {\n\t\tGL11.glPushAttrib(GL11.GL_COLOR_BUFFER_BIT); //don't break other mods' guis when holding a pipe\n\t\t//force transparency\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\tGL11.glEnable(GL11.GL_BLEND);\n\n\t\tGL11.glTranslatef(-0.5F, -0.5F, -0.5F);\n\t\tBlock block = LogisticsPipes.LogisticsPipeBlock;\n\t\tTessellator tess = Tessellator.instance;\n\n\t\tBlockRotation rotation = BlockRotation.ZERO;\n\n\t\ttess.startDrawingQuads();\n\n\t\tTextureTransformation icon = SimpleServiceLocator.cclProxy.createIconTransformer(LogisticsSolidBlock.getNewIcon(metadata));\n\n\t\t//Draw\n\t\tLogisticsNewSolidBlockWorldRenderer.block.get(rotation).render(icon);\n\t\tif(metadata != LogisticsSolidBlock.LOGISTICS_BLOCK_FRAME) {\n\t\t\tfor (CoverSides side : CoverSides.values()) {\n\t\t\t\tLogisticsNewSolidBlockWorldRenderer.texturePlate_Outer.get(side).get(rotation).render(icon);\n\t\t\t}\n\t\t}\n\t\ttess.draw();\n\t\tblock.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tGL11.glPopAttrib(); // nicely leave the rendering how it was\n\t}*/\n\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/PropertyCache.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport net.minecraftforge.common.property.IUnlistedProperty;\n\nimport com.google.common.cache.Cache;\n\nimport logisticspipes.renderer.state.PipeRenderState;\n\npublic class PropertyCache implements IUnlistedProperty<Cache<PipeRenderState.LocalCacheType, Object>> {\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"lpcache\";\n\t}\n\n\t@Override\n\tpublic boolean isValid(Cache<PipeRenderState.LocalCacheType, Object> value) {\n\t\treturn value != null;\n\t}\n\n\t@SuppressWarnings({ \"unchecked\", \"rawtypes\" })\n\t@Override\n\tpublic Class<Cache<PipeRenderState.LocalCacheType, Object>> getType() {\n\t\treturn (Class) Cache.class;\n\t}\n\n\t@Override\n\tpublic String valueToString(Cache<PipeRenderState.LocalCacheType, Object> value) {\n\t\treturn value.toString();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/PropertyRenderList.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport java.util.List;\n\nimport net.minecraftforge.common.property.IUnlistedProperty;\n\npublic class PropertyRenderList implements IUnlistedProperty<List<RenderEntry>> {\n\n\t@Override\n\tpublic String getName() {\n\t\treturn \"lprenderentrylist\";\n\t}\n\n\t@Override\n\tpublic boolean isValid(List<RenderEntry> value) {\n\t\treturn value != null;\n\t}\n\n\t@SuppressWarnings({ \"unchecked\", \"rawtypes\" })\n\t@Override\n\tpublic Class<List<RenderEntry>> getType() {\n\t\treturn (Class) List.class;\n\t}\n\n\t@Override\n\tpublic String valueToString(List<RenderEntry> value) {\n\t\treturn value.toString();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/RenderEntry.java",
    "content": "package logisticspipes.renderer.newpipe;\n\nimport net.minecraft.util.ResourceLocation;\n\nimport lombok.Data;\n\nimport logisticspipes.proxy.object3d.interfaces.I3DOperation;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\n\n@Data\npublic class RenderEntry {\n\n\tprivate static final ResourceLocation BLOCKS = new ResourceLocation(\"textures/atlas/blocks.png\");\n\n\tpublic RenderEntry(IModel3D model, I3DOperation[] operations, ResourceLocation texture) {\n\t\tthis.model = model;\n\t\tthis.operations = operations;\n\t\tthis.texture = texture;\n\t}\n\n\tpublic RenderEntry(IModel3D model, I3DOperation... operations) {\n\t\tthis(model, operations, RenderEntry.BLOCKS);\n\t}\n\n\tpublic RenderEntry(IModel3D model) {\n\t\tthis(model, new I3DOperation[] {});\n\t}\n\n\tpublic RenderEntry(IModel3D model, ResourceLocation texture) {\n\t\tthis(model, new I3DOperation[] {}, texture);\n\t}\n\n\tpublic RenderEntry clone() {\n\t\treturn new RenderEntry(model.copy(), operations.clone(), texture);\n\t}\n\n\tpublic RenderEntry clone(I3DOperation[] ops) {\n\t\treturn new RenderEntry(model.copy(), ops, RenderEntry.BLOCKS);\n\t}\n\n\tprivate final IModel3D model;\n\tprivate final I3DOperation[] operations;\n\tprivate final ResourceLocation texture;\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/tube/CurveTubeRenderer.java",
    "content": "package logisticspipes.renderer.newpipe.tube;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.tubes.HSTubeCurve;\nimport logisticspipes.pipes.tubes.HSTubeCurve.TurnDirection;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPColourMultiplier;\nimport logisticspipes.proxy.object3d.operation.LPRotation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class CurveTubeRenderer implements ISpecialPipeRenderer, IHighlightPlacementRenderer {\n\n\tprivate CurveTubeRenderer() {}\n\n\tpublic static final CurveTubeRenderer instance = new CurveTubeRenderer();\n\n\tenum TubeMount {\n\t\tUP_LEFT,\n\t\tUP_RIGHT,\n\t\tDOWN_LEFT,\n\t\tDOWN_RIGHT\n\t}\n\n\t//Tube Models\n\tstatic Map<TurnDirection, List<IModel3D>> tubeTurnBase = new HashMap<>();\n\tstatic Map<TurnDirection, Map<Pair<TubeMount, Integer>, IModel3D>> tubeTurnMounts = new HashMap<>();\n\n\t//Tube global Access\n\tpublic static Map<TurnDirection, IModel3D> tubeCurve = new HashMap<>();\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/blocks/pipes/HS-Tube.png\");\n\n\tpublic static void loadModels() {\n\t\ttry {\n\t\t\tMap<String, IModel3D> pipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/HSTube-Turn_result.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\t//tubeTurnMounts\n\t\t\tfor (TurnDirection turn : TurnDirection.values()) {\n\t\t\t\tCurveTubeRenderer.tubeTurnBase.put(turn, new ArrayList<>());\n\t\t\t}\n\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t.filter(entry -> entry.getKey().startsWith(\"Lane \") || entry.getKey().contains(\" Lane \") || entry.getKey().endsWith(\" Lane\"))\n\t\t\t\t\t.forEach(entry -> {\n\t\t\t\t\t\tCurveTubeRenderer.tubeTurnBase.get(TurnDirection.SOUTH_WEST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 0.0)).apply(new LPRotation(-Math.PI / 2, 0, 1, 0))));\n\t\t\t\t\t\tCurveTubeRenderer.tubeTurnBase.get(TurnDirection.EAST_SOUTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tCurveTubeRenderer.tubeTurnBase.get(TurnDirection.NORTH_EAST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(-1.0, 0.0, 1.0)).apply(new LPRotation(Math.PI / 2, 0, 1, 0))));\n\t\t\t\t\t\tCurveTubeRenderer.tubeTurnBase.get(TurnDirection.WEST_NORTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(-1.0, 0.0, 0.0)).apply(new LPRotation(Math.PI, 0, 1, 0))));\n\t\t\t\t\t});\n\t\t\tif (CurveTubeRenderer.tubeTurnBase.get(TurnDirection.NORTH_EAST).size() != 4) {\n\t\t\t\tthrow new RuntimeException(\"Couldn't load Tube Lanes. Only loaded \" + CurveTubeRenderer.tubeTurnBase.get(TurnDirection.NORTH_EAST).size());\n\t\t\t}\n\n\t\t\tfor (TurnDirection turn : TurnDirection.values()) {\n\t\t\t\tCurveTubeRenderer.tubeCurve.put(turn, SimpleServiceLocator.cclProxy.combine(CurveTubeRenderer.tubeTurnBase.get(turn)));\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsWithoutPipe() {\n\t\treturn CurveTubeRenderer.tubeTurnBase.get(TurnDirection.NORTH_EAST);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsFromPipe(@Nonnull CoreUnroutedPipe pipe) {\n\t\tif (pipe instanceof HSTubeCurve && ((HSTubeCurve) pipe).getOrientation() != null) {\n\t\t\tfinal TurnDirection orientation = ((HSTubeCurve) pipe).getOrientation().getRenderOrientation();\n\t\t\treturn Objects.requireNonNull(CurveTubeRenderer.tubeTurnBase.get(orientation), \"Could not fetch model for CurveTubeRenderer for orientation \" + orientation);\n\t\t} else {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ResourceLocation getTexture() {\n\t\treturn CurveTubeRenderer.TEXTURE;\n\t}\n\n\t@Override\n\tpublic void renderHighlight(ITubeOrientation orientation) {\n\t\tCurveTubeRenderer.tubeCurve.get(orientation.getRenderOrientation()).copy().render(LPColourMultiplier.instance(0xFFFFFFFF));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/tube/GainTubeRenderer.java",
    "content": "package logisticspipes.renderer.newpipe.tube;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.tubes.HSTubeGain;\nimport logisticspipes.pipes.tubes.HSTubeGain.TubeGainRenderOrientation;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.IBounds;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPColourMultiplier;\nimport logisticspipes.proxy.object3d.operation.LPRotation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class GainTubeRenderer implements ISpecialPipeRenderer, IHighlightPlacementRenderer {\n\n\tprivate GainTubeRenderer() {}\n\n\tpublic static final GainTubeRenderer instance = new GainTubeRenderer();\n\n\tenum TubeMount {\n\t\tUP_LEFT,\n\t\tUP_RIGHT,\n\t\tDOWN_LEFT,\n\t\tDOWN_RIGHT\n\t}\n\n\t//Tube Models\n\tstatic Map<TubeGainRenderOrientation, List<IModel3D>> tubeTurnBase = new HashMap<>();\n\tstatic Map<TubeGainRenderOrientation, Map<Pair<TubeMount, Integer>, IModel3D>> tubeTurnMounts = new HashMap<>();\n\n\t//Tube global Access\n\tpublic static Map<TubeGainRenderOrientation, IModel3D> tubeGain = new HashMap<>();\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/blocks/pipes/HS-Tube.png\");\n\n\tpublic static void loadModels() {\n\t\ttry {\n\t\t\tMap<String, IModel3D> pipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/HSTube-Gain_result.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\t//tubeTurnMounts\n\t\t\tfor (TubeGainRenderOrientation turn : TubeGainRenderOrientation.values()) {\n\t\t\t\tGainTubeRenderer.tubeTurnBase.put(turn, new ArrayList<>());\n\t\t\t}\n\t\t\tpipePartModels.entrySet().stream().filter(entry -> entry.getKey().startsWith(\"Lane \") || entry.getKey().contains(\" Lane \") || entry.getKey().endsWith(\" Lane\")).forEach(entry -> {\n\t\t\t\tGainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.EAST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 0.0)).apply(new LPRotation(-Math.PI / 2, 0, 1, 0))));\n\t\t\t\tGainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.NORTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\tGainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.WEST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(-1.0, 0.0, 1.0)).apply(new LPRotation(Math.PI / 2, 0, 1, 0))));\n\t\t\t\tGainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.SOUTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(-1.0, 0.0, 0.0)).apply(new LPRotation(Math.PI, 0, 1, 0))));\n\t\t\t});\n\t\t\tif (GainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.NORTH).size() != 4) {\n\t\t\t\tthrow new RuntimeException(\"Couldn't load Tube Lanes. Only loaded \" + GainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.NORTH).size());\n\t\t\t}\n\n\t\t\tfor (TubeGainRenderOrientation turn : TubeGainRenderOrientation.values()) {\n\t\t\t\tGainTubeRenderer.tubeGain.put(turn, SimpleServiceLocator.cclProxy.combine(GainTubeRenderer.tubeTurnBase.get(turn)));\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsWithoutPipe() {\n\t\treturn GainTubeRenderer.tubeTurnBase.get(TubeGainRenderOrientation.NORTH);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsFromPipe(@Nonnull CoreUnroutedPipe pipe) {\n\t\tif (pipe instanceof HSTubeGain && ((HSTubeGain) pipe).getOrientation() != null) {\n\t\t\tfinal TubeGainRenderOrientation orientation = ((HSTubeGain) pipe).getOrientation().getRenderOrientation();\n\t\t\treturn Objects.requireNonNull(GainTubeRenderer.tubeTurnBase.get(orientation), \"Could not fetch model for GainTubeRenderer for orientation \" + orientation);\n\t\t} else {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ResourceLocation getTexture() {\n\t\treturn GainTubeRenderer.TEXTURE;\n\t}\n\n\t@Override\n\tpublic void renderHighlight(ITubeOrientation orientation) {\n\t\tGainTubeRenderer.tubeGain.get(orientation.getRenderOrientation()).copy().render(LPColourMultiplier.instance(0xFFFFFFFF));\n\t}\n\n\tpublic static AxisAlignedBB getObjectBoundsAt(AxisAlignedBB boundingBox, ITubeOrientation orientation) {\n\t\tIModel3D model = GainTubeRenderer.tubeGain.get(orientation.getRenderOrientation());\n\t\tIBounds c = model.getBoundsInside(boundingBox);\n\t\tif (c != null) {\n\t\t\treturn c.toAABB();\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/tube/LineTubeRenderer.java",
    "content": "package logisticspipes.renderer.newpipe.tube;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.tubes.HSTubeLine;\nimport logisticspipes.pipes.tubes.HSTubeLine.TubeLineRenderOrientation;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPColourMultiplier;\nimport logisticspipes.proxy.object3d.operation.LPRotation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\n\npublic final class LineTubeRenderer implements ISpecialPipeRenderer, IHighlightPlacementRenderer {\n\n\tprivate LineTubeRenderer() {}\n\n\tpublic static final LineTubeRenderer instance = new LineTubeRenderer();\n\n\tstatic Map<TubeLineRenderOrientation, List<IModel3D>> tubeLineBase = new HashMap<>();\n\n\t//Global Access\n\tpublic static Map<TubeLineRenderOrientation, IModel3D> tubeLine = new HashMap<>();\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/blocks/pipes/HS-Tube-Line.png\");\n\n\tpublic static void loadModels() {\n\t\ttry {\n\t\t\tMap<String, IModel3D> pipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/HSTube-Line_result.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\t//tubeTurnMounts\n\t\t\tfor (TubeLineRenderOrientation turn : TubeLineRenderOrientation.values()) {\n\t\t\t\tLineTubeRenderer.tubeLineBase.put(turn, new ArrayList<>());\n\t\t\t}\n\t\t\tpipePartModels.entrySet().stream().filter(entry -> entry.getKey().startsWith(\"Side \") || entry.getKey().contains(\" Side \") || entry.getKey().endsWith(\" Side\")).forEach(entry -> {\n\t\t\t\tLineTubeRenderer.tubeLineBase.get(TubeLineRenderOrientation.EAST_WEST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 0.0)).apply(new LPRotation(-Math.PI / 2, 0, 1, 0))));\n\t\t\t\tLineTubeRenderer.tubeLineBase.get(TubeLineRenderOrientation.NORTH_SOUTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t});\n\t\t\tif (LineTubeRenderer.tubeLineBase.get(TubeLineRenderOrientation.EAST_WEST).size() != 4) {\n\t\t\t\tthrow new RuntimeException(\"Couldn't load Tube Side. Only loaded \" + LineTubeRenderer.tubeLineBase.get(TubeLineRenderOrientation.EAST_WEST).size());\n\t\t\t}\n\n\t\t\tfor (TubeLineRenderOrientation turn : TubeLineRenderOrientation.values()) {\n\t\t\t\tLineTubeRenderer.tubeLine.put(turn, SimpleServiceLocator.cclProxy.combine(LineTubeRenderer.tubeLineBase.get(turn)));\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsWithoutPipe() {\n\t\treturn LineTubeRenderer.tubeLineBase.get(TubeLineRenderOrientation.NORTH_SOUTH);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsFromPipe(@Nonnull CoreUnroutedPipe pipe) {\n\t\tif (pipe instanceof HSTubeLine && ((HSTubeLine) pipe).getOrientation() != null) {\n\t\t\tfinal TubeLineRenderOrientation orientation = ((HSTubeLine) pipe).getOrientation().getRenderOrientation();\n\t\t\treturn Objects.requireNonNull(LineTubeRenderer.tubeLineBase.get(orientation), \"Could not fetch model for LineTubeRenderer for orientation \" + orientation);\n\t\t} else {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ResourceLocation getTexture() {\n\t\treturn LineTubeRenderer.TEXTURE;\n\t}\n\n\t@Override\n\tpublic void renderHighlight(ITubeOrientation orientation) {\n\t\tTubeLineRenderOrientation direction = (TubeLineRenderOrientation) orientation.getRenderOrientation();\n\t\tLineTubeRenderer.tubeLine.get(direction).copy().render(LPColourMultiplier.instance(0xFFFFFFFF));\n\t}\n}\n\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/tube/SCurveTubeRenderer.java",
    "content": "package logisticspipes.renderer.newpipe.tube;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.tubes.HSTubeSCurve;\nimport logisticspipes.pipes.tubes.HSTubeSCurve.TurnSDirection;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.IBounds;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPColourMultiplier;\nimport logisticspipes.proxy.object3d.operation.LPRotation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class SCurveTubeRenderer implements ISpecialPipeRenderer, IHighlightPlacementRenderer {\n\n\tprivate SCurveTubeRenderer() {}\n\n\tpublic static final SCurveTubeRenderer instance = new SCurveTubeRenderer();\n\n\tenum TubeMount {\n\t\tUP_LEFT,\n\t\tUP_RIGHT,\n\t\tDOWN_LEFT,\n\t\tDOWN_RIGHT\n\t}\n\n\t//Tube Models\n\tstatic Map<TurnSDirection, List<IModel3D>> tubeSCurveBase = new HashMap<>();\n\tstatic Map<TurnSDirection, Map<Pair<TubeMount, Integer>, IModel3D>> tubeSCurveMounts = new HashMap<>();\n\n\t//Tube global Access\n\tpublic static Map<TurnSDirection, IModel3D> tubeSCurve = new HashMap<>();\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/blocks/pipes/HS-Tube.png\");\n\n\tpublic static void loadModels() {\n\t\ttry {\n\t\t\tMap<String, IModel3D> pipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/HSTube-Gain_result.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\t//tubeTurnMounts\n\t\t\tfor (TurnSDirection turn : TurnSDirection.values()) {\n\t\t\t\tSCurveTubeRenderer.tubeSCurveBase.put(turn, new ArrayList<>());\n\t\t\t}\n\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t.filter(entry -> entry.getKey().startsWith(\"Lane \") || entry.getKey().contains(\" Lane \") || entry.getKey().endsWith(\" Lane\"))\n\t\t\t\t\t.forEach(entry -> {\n\t\t\t\t\t\tSCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.EAST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPRotation(Math.PI / 2, 0, 0, 1)).apply(new LPTranslation(1.0, 0.0, 0.0)).apply(new LPRotation(-Math.PI / 2, 0, 1, 0))));\n\t\t\t\t\t\tSCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.NORTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPRotation(Math.PI / 2, 0, 0, 1)).apply(new LPTranslation(1.0, 0.0, 1.0))));\n\t\t\t\t\t\tSCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.EAST_INV).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPRotation(-Math.PI / 2, 0, 0, 1)).apply(new LPTranslation(-2.0, 1.0, 4.0)).apply(new LPRotation(Math.PI / 2, 0, 1, 0))));\n\t\t\t\t\t\tSCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.NORTH_INV).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPRotation(-Math.PI / 2, 0, 0, 1)).apply(new LPTranslation(-2.0, 1.0, 3.0)).apply(new LPRotation(Math.PI, 0, 1, 0))));\n\t\t\t\t\t});\n\t\t\tif (SCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.NORTH).size() != 4) {\n\t\t\t\tthrow new RuntimeException(\"Couldn't load Tube Lanes. Only loaded \" + SCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.NORTH).size());\n\t\t\t}\n\n\t\t\tfor (TurnSDirection turn : TurnSDirection.values()) {\n\t\t\t\tSCurveTubeRenderer.tubeSCurve.put(turn, SimpleServiceLocator.cclProxy.combine(SCurveTubeRenderer.tubeSCurveBase.get(turn)));\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsWithoutPipe() {\n\t\treturn SCurveTubeRenderer.tubeSCurveBase.get(TurnSDirection.NORTH);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<IModel3D> getModelsFromPipe(@Nonnull CoreUnroutedPipe pipe) {\n\t\tif (pipe instanceof HSTubeSCurve && ((HSTubeSCurve) pipe).getOrientation() != null) {\n\t\t\tfinal TurnSDirection orientation = ((HSTubeSCurve) pipe).getOrientation().getRenderOrientation();\n\t\t\treturn Objects.requireNonNull(SCurveTubeRenderer.tubeSCurveBase.get(orientation), \"Could not fetch model for SCurveTubeRenderer for orientation \" + orientation);\n\t\t} else {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ResourceLocation getTexture() {\n\t\treturn SCurveTubeRenderer.TEXTURE;\n\t}\n\n\t@Override\n\tpublic void renderHighlight(ITubeOrientation orientation) {\n\t\tSCurveTubeRenderer.tubeSCurve.get(orientation.getRenderOrientation()).render(LPColourMultiplier.instance(0xFFFFFFFF));\n\t}\n\n\tpublic static AxisAlignedBB getObjectBoundsAt(AxisAlignedBB boundingBox, ITubeOrientation orientation) {\n\t\tIModel3D model = SCurveTubeRenderer.tubeSCurve.get(orientation.getRenderOrientation());\n\t\tIBounds c = model.getBoundsInside(boundingBox);\n\t\tif (c != null) {\n\t\t\treturn c.toAABB();\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/newpipe/tube/SpeedupTubeRenderer.java",
    "content": "package logisticspipes.renderer.newpipe.tube;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.ResourceLocation;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.interfaces.ITubeRenderOrientation;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.tubes.HSTubeSpeedup;\nimport logisticspipes.pipes.tubes.HSTubeSpeedup.SpeedupDirection;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.IModel3D;\nimport logisticspipes.proxy.object3d.operation.LPColourMultiplier;\nimport logisticspipes.proxy.object3d.operation.LPRotation;\nimport logisticspipes.proxy.object3d.operation.LPScale;\nimport logisticspipes.proxy.object3d.operation.LPTranslation;\nimport logisticspipes.renderer.newpipe.IHighlightPlacementRenderer;\nimport logisticspipes.renderer.newpipe.ISpecialPipeRenderer;\nimport logisticspipes.renderer.newpipe.LogisticsNewRenderPipe;\n\npublic final class SpeedupTubeRenderer implements ISpecialPipeRenderer, IHighlightPlacementRenderer {\n\n\tprivate SpeedupTubeRenderer() {}\n\n\tpublic static final SpeedupTubeRenderer instance = new SpeedupTubeRenderer();\n\n\tstatic Map<SpeedupDirection, List<IModel3D>> tubeSpeedupBase = new HashMap<>();\n\n\t//Global Access\n\tpublic static Map<SpeedupDirection, IModel3D> tubeSpeedup = new HashMap<>();\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/blocks/pipes/HS-Speedup.png\");\n\n\tpublic static void loadModels() {\n\t\ttry {\n\t\t\tMap<String, IModel3D> pipePartModels = SimpleServiceLocator.cclProxy.parseObjModels(LogisticsPipes.class.getResourceAsStream(\"/logisticspipes/models/HSTube-Speedup_result.obj\"), 7, new LPScale(1 / 100f));\n\n\t\t\t//tubeTurnMounts\n\t\t\tfor (SpeedupDirection turn : SpeedupDirection.values()) {\n\t\t\t\tSpeedupTubeRenderer.tubeSpeedupBase.put(turn, new ArrayList<>());\n\t\t\t}\n\t\t\tpipePartModels.entrySet().stream()\n\t\t\t\t\t.filter(entry -> entry.getKey().startsWith(\"Side \") || entry.getKey().contains(\" Side \") || entry.getKey().endsWith(\" Side\"))\n\t\t\t\t\t.forEach(entry -> {\n\t\t\t\t\t\tSpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.EAST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 0.0)).apply(new LPRotation(-Math.PI / 2, 0, 1, 0))));\n\t\t\t\t\t\tSpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.NORTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(0.0, 0.0, 1.0))));\n\t\t\t\t\t\tSpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.WEST).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(-1.0, 0.0, 1.0)).apply(new LPRotation(Math.PI / 2, 0, 1, 0))));\n\t\t\t\t\t\tSpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.SOUTH).add(LogisticsNewRenderPipe.compute(entry.getValue().twoFacedCopy().apply(new LPTranslation(-1.0, 0.0, 0.0)).apply(new LPRotation(Math.PI, 0, 1, 0))));\n\t\t\t\t\t});\n\t\t\tif (SpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.NORTH).size() != 4) {\n\t\t\t\tthrow new RuntimeException(\"Couldn't load Tube Side. Only loaded \" + SpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.NORTH).size());\n\t\t\t}\n\n\t\t\tfor (SpeedupDirection turn : SpeedupDirection.values()) {\n\t\t\t\tSpeedupTubeRenderer.tubeSpeedup.put(turn, SimpleServiceLocator.cclProxy.combine(SpeedupTubeRenderer.tubeSpeedupBase.get(turn)));\n\t\t\t}\n\t\t} catch (Throwable e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic List<IModel3D> getModelsWithoutPipe() {\n\t\treturn SpeedupTubeRenderer.tubeSpeedupBase.get(SpeedupDirection.NORTH);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic List<IModel3D> getModelsFromPipe(@Nonnull CoreUnroutedPipe pipe) {\n\t\tif (pipe instanceof HSTubeSpeedup && ((HSTubeSpeedup) pipe).getOrientation() != null) {\n\t\t\tfinal ITubeRenderOrientation orientation = ((HSTubeSpeedup) pipe).getOrientation().getRenderOrientation();\n\t\t\treturn Objects.requireNonNull(SpeedupTubeRenderer.tubeSpeedupBase.get(orientation), \"Could not fetch model for HSTubeSpeedup for orientation \" + orientation);\n\t\t} else {\n\t\t\treturn Collections.emptyList();\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ResourceLocation getTexture() {\n\t\treturn SpeedupTubeRenderer.TEXTURE;\n\t}\n\n\t@Override\n\tpublic void renderHighlight(ITubeOrientation orientation) {\n\t\tSpeedupDirection speedupDirection = (SpeedupDirection) orientation.getRenderOrientation();\n\t\tSpeedupTubeRenderer.tubeSpeedup.get(speedupDirection).copy().render(LPColourMultiplier.instance(0xFFFFFFFF));\n\t\tLogisticsNewRenderPipe.renderBoxWithDir(((SpeedupDirection) orientation.getRenderOrientation()).getDir1());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/state/ConnectionMatrix.java",
    "content": "package logisticspipes.renderer.state;\n\nimport net.minecraft.util.EnumFacing;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class ConnectionMatrix {\n\n\tprivate int mask = 0;\n\tprivate int isBCPipeMask = 0;\n\tprivate int isTDPipeMask = 0;\n\tprivate boolean dirty = false;\n\n\tpublic boolean isConnected(EnumFacing direction) {\n\t\t// test if the direction.ordinal()'th bit of mask is set\n\t\treturn (mask & (1 << direction.ordinal())) != 0;\n\t}\n\n\tpublic void setConnected(EnumFacing direction, boolean value) {\n\t\tif (isConnected(direction) != value) {\n\t\t\t// invert the direction.ordinal()'th bit of mask\n\t\t\tmask ^= 1 << direction.ordinal();\n\t\t\tdirty = true;\n\t\t}\n\t\tif (!value) {\n\t\t\tsetBCConnected(direction, false);\n\t\t\tsetTDConnected(direction, false);\n\t\t}\n\t}\n\n\tpublic boolean isBCConnected(EnumFacing direction) {\n\t\t// test if the direction.ordinal()'th bit of mask is set\n\t\treturn direction != null && (isBCPipeMask & (1 << direction.ordinal())) != 0;\n\t}\n\n\tpublic void setBCConnected(EnumFacing direction, boolean value) {\n\t\tif (isBCConnected(direction) != value) {\n\t\t\t// invert the direction.ordinal()'th bit of mask\n\t\t\tisBCPipeMask ^= 1 << direction.ordinal();\n\t\t\tdirty = true;\n\t\t}\n\t}\n\n\tpublic boolean isTDConnected(EnumFacing direction) {\n\t\t// test if the direction.ordinal()'th bit of mask is set\n\t\treturn direction != null && (isTDPipeMask & (1 << direction.ordinal())) != 0;\n\t}\n\n\tpublic void setTDConnected(EnumFacing direction, boolean value) {\n\t\tif (isTDConnected(direction) != value) {\n\t\t\t// invert the direction.ordinal()'th bit of mask\n\t\t\tisTDPipeMask ^= 1 << direction.ordinal();\n\t\t\tdirty = true;\n\t\t}\n\t}\n\n\t/**\n\t * Return a mask representing the connectivity for all sides.\n\t *\n\t * @return mask in EnumFacing order, least significant bit = first entry\n\t */\n\tpublic int getMask() {\n\t\treturn mask;\n\t}\n\n\tpublic boolean isDirty() {\n\t\treturn dirty;\n\t}\n\n\tpublic void clean() {\n\t\tdirty = false;\n\t}\n\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeByte(mask);\n\t\toutput.writeByte(isBCPipeMask);\n\t\toutput.writeByte(isTDPipeMask);\n\t}\n\n\tpublic void readData(LPDataInput input) {\n\t\tbyte newMask = input.readByte();\n\n\t\tif (newMask != mask) {\n\t\t\tmask = newMask;\n\t\t\tdirty = true;\n\t\t}\n\n\t\tnewMask = input.readByte();\n\t\tif (newMask != isBCPipeMask) {\n\t\t\tisBCPipeMask = newMask;\n\t\t\tdirty = true;\n\t\t}\n\n\t\tnewMask = input.readByte();\n\t\tif (newMask != isTDPipeMask) {\n\t\t\tisTDPipeMask = newMask;\n\t\t\tdirty = true;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/state/PipeRenderState.java",
    "content": "package logisticspipes.renderer.state;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\n\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\n\nimport logisticspipes.interfaces.IClientState;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.newpipe.GLRenderList;\nimport logisticspipes.renderer.newpipe.RenderEntry;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class PipeRenderState implements IClientState {\n\n\tpublic enum LocalCacheType {\n\t\tQUADS\n\t}\n\n\tpublic final ConnectionMatrix pipeConnectionMatrix = new ConnectionMatrix();\n\tpublic final TextureMatrix textureMatrix = new TextureMatrix();\n\n\tpublic List<RenderEntry> cachedRenderer = null;\n\tpublic Cache<LocalCacheType, Object> objectCache = CacheBuilder.newBuilder().build();\n\tpublic int cachedRenderIndex = -1;\n\tpublic boolean forceRenderOldPipe = false;\n\tprivate boolean[] solidSidesCache = new boolean[6];\n\tprivate boolean savedStateHasMCMultiParts = false;\n\n\tpublic int[] buffer = null;\n\tpublic Map<ResourceLocation, GLRenderList> renderLists;\n\n\tprivate boolean dirty = true;\n\n\tpublic PipeRenderState() {\n\t}\n\n\tpublic void clean() {\n\t\tdirty = false;\n\t\tpipeConnectionMatrix.clean();\n\t\ttextureMatrix.clean();\n\t\tclearRenderCaches();\n\t}\n\n\tpublic boolean isDirty() {\n\t\treturn dirty || pipeConnectionMatrix.isDirty() || textureMatrix.isDirty();\n\t}\n\n\tpublic boolean needsRenderUpdate() {\n\t\treturn pipeConnectionMatrix.isDirty() || textureMatrix.isDirty();\n\t}\n\n\tpublic void checkForRenderUpdate(IBlockAccess worldIn, BlockPos blockPos) {\n\t\tboolean[] solidSides = new boolean[6];\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tDoubleCoordinates pos = CoordinateUtils.add(new DoubleCoordinates(blockPos), dir);\n\t\t\tIBlockState blockSide = pos.getBlockState(worldIn);\n\t\t\tif (blockSide.isSideSolid(worldIn, pos.getBlockPos(), dir.getOpposite()) && !pipeConnectionMatrix.isConnected(dir)) {\n\t\t\t\tsolidSides[dir.ordinal()] = true;\n\t\t\t}\n\t\t}\n\t\tif (!Arrays.equals(solidSides, solidSidesCache)) {\n\t\t\tsolidSidesCache = solidSides.clone();\n\t\t\tclearRenderCaches();\n\t\t}\n\t\tDoubleCoordinates pos = new DoubleCoordinates(blockPos);\n\t\tTileEntity tile = pos.getTileEntity(worldIn);\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tboolean hasParts = SimpleServiceLocator.mcmpProxy.hasParts((LogisticsTileGenericPipe) tile);\n\t\t\tif (savedStateHasMCMultiParts != hasParts) {\n\t\t\t\tsavedStateHasMCMultiParts = hasParts;\n\t\t\t\tclearRenderCaches();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void clearRenderCaches() {\n\t\tcachedRenderer = null;\n\t\tobjectCache.invalidateAll();\n\t\tobjectCache.cleanUp();\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tpipeConnectionMatrix.writeData(output);\n\t\ttextureMatrix.writeData(output);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tpipeConnectionMatrix.readData(input);\n\t\ttextureMatrix.readData(input);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/state/PipeSubRenderState.java",
    "content": "package logisticspipes.renderer.state;\n\nimport java.util.List;\n\nimport logisticspipes.renderer.newpipe.GLRenderList;\nimport logisticspipes.renderer.newpipe.RenderEntry;\n\npublic class PipeSubRenderState {\n\n\tpublic List<RenderEntry> cachedRenderer = null;\n\tpublic GLRenderList renderList;\n\tpublic boolean forceRenderOldPipe = false;\n}\n"
  },
  {
    "path": "common/logisticspipes/renderer/state/TextureMatrix.java",
    "content": "package logisticspipes.renderer.state;\n\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.Getter;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class TextureMatrix {\n\n\t//Old Pipe Renderer\n\tprivate final int[] iconIndexes = new int[7];\n\n\t//New Pipe Renderer\n\t@Getter\n\tprivate int textureIndex;\n\t@Getter\n\tprivate boolean isRouted;\n\tprivate boolean[] isRoutedInDir = new boolean[6];\n\tprivate boolean[] isSubPowerInDir = new boolean[6];\n\t@Getter\n\tprivate boolean hasPowerUpgrade;\n\t@Getter\n\tprivate boolean hasPower;\n\t@Getter\n\tprivate boolean isFluid;\n\t@Getter\n\tprivate EnumFacing pointedOrientation;\n\n\tprivate boolean dirty = true;\n\n\tpublic int getTextureIndex(EnumFacing direction) {\n\t\treturn iconIndexes[direction.ordinal()];\n\t}\n\n\tpublic void setIconIndex(EnumFacing direction, int value) {\n\t\tif (iconIndexes[direction.ordinal()] != value) {\n\t\t\ticonIndexes[direction.ordinal()] = value;\n\t\t\tdirty = true;\n\t\t}\n\t}\n\n\tpublic void refreshStates(CoreUnroutedPipe pipe) {\n\t\tif (textureIndex != pipe.getTextureIndex()) {\n\t\t\tdirty = true;\n\t\t}\n\t\ttextureIndex = pipe.getTextureIndex();\n\t\tif (isRouted != pipe.isRoutedPipe()) {\n\t\t\tdirty = true;\n\t\t}\n\t\tisRouted = pipe.isRoutedPipe();\n\t\tif (isRouted) {\n\t\t\tCoreRoutedPipe cPipe = (CoreRoutedPipe) pipe;\n\t\t\tfor (int i = 0; i < 6; i++) {\n\t\t\t\tif (isRoutedInDir[i] != cPipe.getRouter().isRoutedExit(EnumFacing.byIndex(i))) {\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t\tisRoutedInDir[i] = cPipe.getRouter().isRoutedExit(EnumFacing.byIndex(i));\n\t\t\t}\n\t\t\tfor (int i = 0; i < 6; i++) {\n\t\t\t\tif (isSubPowerInDir[i] != cPipe.getRouter().isSubPoweredExit(EnumFacing.byIndex(i))) {\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t\tisSubPowerInDir[i] = cPipe.getRouter().isSubPoweredExit(EnumFacing.byIndex(i));\n\t\t\t}\n\t\t\tif (hasPowerUpgrade != (cPipe.getUpgradeManager().hasRFPowerSupplierUpgrade() || cPipe.getUpgradeManager().getIC2PowerLevel() > 0)) {\n\t\t\t\tdirty = true;\n\t\t\t}\n\t\t\thasPowerUpgrade = cPipe.getUpgradeManager().hasRFPowerSupplierUpgrade() || cPipe.getUpgradeManager().getIC2PowerLevel() > 0;\n\t\t\tif (hasPower != (cPipe._textureBufferPowered || Configs.LOGISTICS_POWER_USAGE_DISABLED)) {\n\t\t\t\tdirty = true;\n\t\t\t}\n\t\t\thasPower = cPipe._textureBufferPowered || Configs.LOGISTICS_POWER_USAGE_DISABLED;\n\t\t\tif (isFluid != cPipe.isFluidPipe()) {\n\t\t\t\tdirty = true;\n\t\t\t}\n\t\t\tisFluid = cPipe.isFluidPipe();\n\t\t\tif (pointedOrientation != cPipe.getPointedOrientation()) {\n\t\t\t\tdirty = true;\n\t\t\t}\n\t\t\tpointedOrientation = cPipe.getPointedOrientation();\n\t\t} else {\n\t\t\tisRoutedInDir = new boolean[6];\n\t\t}\n\t}\n\n\tpublic boolean isRoutedInDir(EnumFacing dir) {\n\t\tif (dir == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn isRoutedInDir[dir.ordinal()];\n\t}\n\n\tpublic boolean isSubPowerInDir(EnumFacing dir) {\n\t\tif (dir == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn isSubPowerInDir[dir.ordinal()];\n\t}\n\n\tpublic boolean isDirty() {\n\t\treturn dirty;\n\t}\n\n\tpublic void clean() {\n\t\tdirty = false;\n\t}\n\n\tpublic void writeData(LPDataOutput output) {\n\t\tfor (int iconIndexe : iconIndexes) {\n\t\t\toutput.writeByte(iconIndexe);\n\t\t}\n\t\toutput.writeInt(textureIndex);\n\t\toutput.writeBoolean(isRouted);\n\t\toutput.writeBooleanArray(isRoutedInDir);\n\t\toutput.writeBooleanArray(isSubPowerInDir);\n\t\toutput.writeBoolean(hasPowerUpgrade);\n\t\toutput.writeBoolean(hasPower);\n\t\toutput.writeBoolean(isFluid);\n\t\toutput.writeFacing(pointedOrientation);\n\t}\n\n\tpublic void readData(LPDataInput input) {\n\t\tfor (int i = 0; i < iconIndexes.length; i++) {\n\t\t\tint icon = input.readByte();\n\t\t\tif (iconIndexes[i] != icon) {\n\t\t\t\ticonIndexes[i] = icon;\n\t\t\t\tdirty = true;\n\t\t\t}\n\t\t}\n\t\ttextureIndex = input.readInt();\n\t\tisRouted = input.readBoolean();\n\t\tisRoutedInDir = input.readBooleanArray();\n\t\tisSubPowerInDir = input.readBooleanArray();\n\t\thasPowerUpgrade = input.readBoolean();\n\t\thasPower = input.readBoolean();\n\t\tisFluid = input.readBoolean();\n\t\tpointedOrientation = input.readFacing();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/DictCraftingTemplate.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.request;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.LogisticsDictPromise;\nimport logisticspipes.routing.LogisticsExtraPromise;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class DictCraftingTemplate implements IReqCraftingTemplate {\n\n\tprotected DictResource _result;\n\tprotected ICraftItems _crafter;\n\n\tprotected ArrayList<Pair<IResource, IAdditionalTargetInformation>> _required = new ArrayList<>(9);\n\n\tprotected ArrayList<ItemIdentifierStack> _byproduct = new ArrayList<>(9);\n\n\tprivate final int priority;\n\n\tpublic DictCraftingTemplate(DictResource result, ICraftItems crafter, int priority) {\n\t\t_result = result;\n\t\t_crafter = crafter;\n\t\tthis.priority = priority;\n\t}\n\n\tpublic void addRequirement(IResource requirement, IAdditionalTargetInformation info) {\n\t\t_required.add(new Pair<>(requirement, info));\n\t}\n\n\tpublic void addByproduct(ItemIdentifierStack stack) {\n\t\tfor (ItemIdentifierStack i : _byproduct) {\n\t\t\tif (i.getItem().equals(stack.getItem())) {\n\t\t\t\ti.setStackSize(i.getStackSize() + stack.getStackSize());\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t_byproduct.add(stack);\n\t}\n\n\t@Override\n\tpublic LogisticsPromise generatePromise(int nResultSets) {\n\t\treturn new LogisticsDictPromise(_result, _result.stack.getStackSize() * nResultSets, _crafter, ResourceType.CRAFTING);\n\t}\n\n\t//TODO: refactor so that other classes don't reach through the template to the crafter.\n\t// needed to get the crafter todo, in order to sort\n\t@Override\n\tpublic ICraftItems getCrafter() {\n\t\treturn _crafter;\n\t}\n\n\t@Override\n\tpublic int getPriority() {\n\t\treturn priority;\n\t}\n\n\t@Override\n\tpublic int compareTo(ICraftingTemplate o) {\n\t\tint c = o.comparePriority(priority);\n\t\tif (c == 0) {\n\t\t\tc = o.compareStack(_result.stack);\n\t\t}\n\t\tif (c == 0) {\n\t\t\tc = o.compareCrafter(_crafter);\n\t\t}\n\t\treturn c;\n\t}\n\n\t@Override\n\tpublic int comparePriority(int priority) {\n\t\treturn priority - this.priority;\n\t}\n\n\t@Override\n\tpublic int compareStack(ItemIdentifierStack stack) {\n\t\treturn stack.compareTo(this._result.stack);\n\t}\n\n\t@Override\n\tpublic int compareCrafter(ICraftItems crafter) {\n\t\treturn crafter.compareTo(this._crafter);\n\t}\n\n\t@Override\n\tpublic boolean canCraft(IResource type) {\n\t\treturn _result.matches(type, IResource.MatchSettings.NORMAL);\n\t}\n\n\t@Override\n\tpublic int getResultStackSize() {\n\t\treturn _result.stack.getStackSize();\n\t}\n\n\t@Override\n\tpublic IResource getResultItem() {\n\t\treturn _result;\n\t}\n\n\t@Override\n\tpublic List<IExtraPromise> getByproducts(int workSets) {\n\t\treturn _byproduct.stream()\n\t\t\t\t.map(stack -> new LogisticsExtraPromise(stack.getItem(), stack.getStackSize() * workSets, getCrafter(), false))\n\t\t\t\t.collect(Collectors.toList());\n\t}\n\n\t@Override\n\tpublic List<Pair<IResource, IAdditionalTargetInformation>> getComponents(int nCraftingSetsNeeded) {\n\t\tList<Pair<IResource, IAdditionalTargetInformation>> stacks = new ArrayList<>(_required.size());\n\n\t\t// for each thing needed to satisfy this promise\n\t\tfor (Pair<IResource, IAdditionalTargetInformation> stack : _required) {\n\t\t\tPair<IResource, IAdditionalTargetInformation> pair = new Pair<>(stack.getValue1()\n\t\t\t\t\t.clone(nCraftingSetsNeeded), stack.getValue2());\n\t\t\tstacks.add(pair);\n\t\t}\n\t\treturn stacks;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/ICraftingTemplate.java",
    "content": "package logisticspipes.request;\n\nimport java.util.List;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.ICraft;\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\npublic interface ICraftingTemplate extends Comparable<ICraftingTemplate> {\n\n\tList<Pair<IResource, IAdditionalTargetInformation>> getComponents(int nCraftingSets);\n\n\tList<IExtraPromise> getByproducts(int workSets);\n\n\tint getResultStackSize();\n\n\tIPromise generatePromise(int nCraftingSetsNeeded);\n\n\tICraft getCrafter();\n\n\tint getPriority();\n\n\tboolean canCraft(IResource requestType);\n\n\tIResource getResultItem();\n\n\tint comparePriority(int priority);\n\n\tint compareStack(ItemIdentifierStack stack);\n\n\tint compareCrafter(ICraftItems crafter);\n}\n"
  },
  {
    "path": "common/logisticspipes/request/IExtraPromise.java",
    "content": "package logisticspipes.request;\n\nimport logisticspipes.request.resources.IResource;\n\npublic interface IExtraPromise extends IPromise {\n\n\tvoid registerExtras(IResource requestType);\n\n\t@Override\n\tIExtraPromise copy();\n\n\tboolean isProvided();\n\n\tvoid lowerAmount(int usedcount);\n\n\tvoid setAmount(int amount);\n}\n"
  },
  {
    "path": "common/logisticspipes/request/IPromise.java",
    "content": "package logisticspipes.request;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IProvide;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface IPromise {\n\n\tboolean matches(IResource requestType);\n\n\tint getAmount();\n\n\tIExtraPromise split(int more);\n\n\tIProvide getProvider();\n\n\tItemIdentifier getItemType();\n\n\tResourceType getType();\n\n\tIOrderInfoProvider fullFill(IResource requestType, IAdditionalTargetInformation info);\n\n\tIPromise copy();\n}\n"
  },
  {
    "path": "common/logisticspipes/request/IReqCraftingTemplate.java",
    "content": "package logisticspipes.request;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface IReqCraftingTemplate extends ICraftingTemplate {\n\n\tvoid addRequirement(IResource requirement, IAdditionalTargetInformation info);\n\n\tvoid addByproduct(ItemIdentifierStack byproductItem);\n}\n"
  },
  {
    "path": "common/logisticspipes/request/ItemCraftingTemplate.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.request;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.LogisticsExtraPromise;\nimport logisticspipes.routing.LogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class ItemCraftingTemplate implements IReqCraftingTemplate {\n\n\tprotected ItemIdentifierStack _result;\n\tprotected ICraftItems _crafter;\n\n\tprotected ArrayList<Pair<IResource, IAdditionalTargetInformation>> _required = new ArrayList<>(9);\n\n\tprotected ArrayList<ItemIdentifierStack> _byproduct = new ArrayList<>(9);\n\n\tprivate final int priority;\n\n\tpublic ItemCraftingTemplate(ItemIdentifierStack result, ICraftItems crafter, int priority) {\n\t\t_result = result;\n\t\t_crafter = crafter;\n\t\tthis.priority = priority;\n\t}\n\n\tpublic void addRequirement(IResource requirement, IAdditionalTargetInformation info) {\n\t\t_required.add(new Pair<>(requirement, info));\n\t}\n\n\tpublic void addByproduct(ItemIdentifierStack stack) {\n\t\tfor (ItemIdentifierStack i : _byproduct) {\n\t\t\tif (i.getItem().equals(stack.getItem())) {\n\t\t\t\ti.setStackSize(i.getStackSize() + stack.getStackSize());\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t_byproduct.add(stack);\n\t}\n\n\t@Override\n\tpublic LogisticsPromise generatePromise(int nResultSets) {\n\t\treturn new LogisticsPromise(_result.getItem(), _result.getStackSize() * nResultSets, _crafter, ResourceType.CRAFTING);\n\t}\n\n\t//TODO: refactor so that other classes don't reach through the template to the crafter.\n\t// needed to get the crafter todo, in order to sort\n\t@Override\n\tpublic ICraftItems getCrafter() {\n\t\treturn _crafter;\n\t}\n\n\t@Override\n\tpublic int getPriority() {\n\t\treturn priority;\n\t}\n\n\t@Override\n\tpublic int compareTo(ICraftingTemplate o) {\n\t\tint c = o.comparePriority(priority);\n\t\tif (c == 0) {\n\t\t\tc = o.compareStack(_result);\n\t\t}\n\t\tif (c == 0) {\n\t\t\tc = o.compareCrafter(_crafter);\n\t\t}\n\t\treturn c;\n\t}\n\n\t@Override\n\tpublic int comparePriority(int priority) {\n\t\treturn priority - this.priority;\n\t}\n\n\t@Override\n\tpublic int compareStack(ItemIdentifierStack stack) {\n\t\treturn stack.compareTo(this._result);\n\t}\n\n\t@Override\n\tpublic int compareCrafter(ICraftItems crafter) {\n\t\treturn crafter.compareTo(this._crafter);\n\t}\n\n\t@Override\n\tpublic boolean canCraft(IResource type) {\n\t\treturn type.matches(_result.getItem(), IResource.MatchSettings.NORMAL);\n\t}\n\n\t@Override\n\tpublic int getResultStackSize() {\n\t\treturn _result.getStackSize();\n\t}\n\n\t@Override\n\tpublic IResource getResultItem() {\n\t\treturn new ItemResource(_result, null);\n\t}\n\n\t@Override\n\tpublic List<IExtraPromise> getByproducts(int workSets) {\n\t\treturn _byproduct.stream()\n\t\t\t\t.map(stack -> new LogisticsExtraPromise(stack.getItem(), stack.getStackSize() * workSets, getCrafter(), false))\n\t\t\t\t.collect(Collectors.toList());\n\t}\n\n\t@Override\n\tpublic List<Pair<IResource, IAdditionalTargetInformation>> getComponents(int nCraftingSetsNeeded) {\n\t\tList<Pair<IResource, IAdditionalTargetInformation>> stacks = new ArrayList<>(_required.size());\n\n\t\t// for each thing needed to satisfy this promise\n\t\tfor (Pair<IResource, IAdditionalTargetInformation> stack : _required) {\n\t\t\tPair<IResource, IAdditionalTargetInformation> pair = new Pair<>(stack.getValue1()\n\t\t\t\t\t.clone(nCraftingSetsNeeded), stack.getValue2());\n\t\t\tstacks.add(pair);\n\t\t}\n\t\treturn stacks;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/RequestHandler.java",
    "content": "package logisticspipes.request;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.TreeSet;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.Item;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.util.text.TextComponentTranslation;\n\nimport logisticspipes.interfaces.IRequestWatcher;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.orderer.ComponentList;\nimport logisticspipes.network.packets.orderer.MissingItems;\nimport logisticspipes.network.packets.orderer.OrdererContent;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.request.RequestTree.ActiveRequestType;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class RequestHandler {\n\n\tpublic enum DisplayOptions {\n\t\tBoth,\n\t\tSupplyOnly,\n\t\tCraftOnly\n\t}\n\n\tpublic static void request(final EntityPlayer player, final ItemIdentifierStack stack, final CoreRoutedPipe pipe) {\n\t\tif (!pipe.useEnergy(5)) {\n\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\treturn;\n\t\t}\n\t\tRequestTree.request(new ItemIdentifierStack(stack), pipe, new RequestLog() {\n\n\t\t\t@Override\n\t\t\tpublic void handleMissingItems(List<IResource> resources) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(resources).setFlag(true), player);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList parts) {\n\t\t\t\tCollection<IResource> coll = new ArrayList<>(1);\n\t\t\t\tcoll.add(item);\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(coll).setFlag(false), player);\n\t\t\t\tif (pipe instanceof IRequestWatcher) {\n\t\t\t\t\t((IRequestWatcher) pipe).handleOrderList(item, parts);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList parts) {}\n\t\t}, null);\n\t}\n\n\tpublic static void simulate(final EntityPlayer player, final ItemIdentifierStack stack, CoreRoutedPipe pipe) {\n\t\tfinal List<IResource> usedList = new ArrayList<>();\n\t\tfinal List<IResource> missingList = new ArrayList<>();\n\t\tRequestTree.simulate(new ItemIdentifierStack(stack), pipe, new RequestLog() {\n\n\t\t\t@Override\n\t\t\tpublic void handleMissingItems(List<IResource> resources) {\n\t\t\t\tmissingList.addAll(resources);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList parts) {}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList parts) {\n\t\t\t\tusedList.addAll(resources);\n\t\t\t}\n\t\t});\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(ComponentList.class).setUsed(usedList).setMissing(missingList), player);\n\t}\n\n\tpublic static void refresh(EntityPlayer player, CoreRoutedPipe pipe, DisplayOptions option) {\n\t\tMap<ItemIdentifier, Integer> _availableItems;\n\t\tLinkedList<ItemIdentifier> _craftableItems;\n\n\t\tif (option == DisplayOptions.SupplyOnly || option == DisplayOptions.Both) {\n\t\t\t_availableItems = SimpleServiceLocator.logisticsManager.getAvailableItems(pipe.getRouter().getIRoutersByCost());\n\t\t} else {\n\t\t\t_availableItems = new HashMap<>();\n\t\t}\n\t\tif (option == DisplayOptions.CraftOnly || option == DisplayOptions.Both) {\n\t\t\t_craftableItems = SimpleServiceLocator.logisticsManager.getCraftableItems(pipe.getRouter().getIRoutersByCost());\n\t\t} else {\n\t\t\t_craftableItems = new LinkedList<>();\n\t\t}\n\t\tTreeSet<ItemIdentifierStack> _allItems = new TreeSet<>();\n\n\t\tfor (Entry<ItemIdentifier, Integer> item : _availableItems.entrySet()) {\n\t\t\tItemIdentifierStack newStack = item.getKey().makeStack(item.getValue());\n\t\t\t_allItems.add(newStack);\n\t\t}\n\n\t\tfor (ItemIdentifier item : _craftableItems) {\n\t\t\tif (_availableItems.containsKey(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t_allItems.add(item.makeStack(0));\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OrdererContent.class).setIdentSet(_allItems), player);\n\t}\n\n\tpublic static void requestList(final EntityPlayer player, final List<ItemIdentifierStack> list, final CoreRoutedPipe pipe) {\n\t\tif (!pipe.useEnergy(5)) {\n\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\treturn;\n\t\t}\n\t\tRequestTree.request(list, pipe, new RequestLog() {\n\n\t\t\t@Override\n\t\t\tpublic void handleMissingItems(List<IResource> resources) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(resources).setFlag(true), player);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList parts) {}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList parts) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(resources).setFlag(false), player);\n\t\t\t\tif (pipe instanceof IRequestWatcher) {\n\t\t\t\t\t((IRequestWatcher) pipe).handleOrderList(null, parts);\n\t\t\t\t}\n\t\t\t}\n\t\t}, RequestTree.defaultRequestFlags, null);\n\t}\n\n\tpublic static void requestMacrolist(NBTTagCompound itemlist, final CoreRoutedPipe requester, final EntityPlayer player) {\n\t\tif (!requester.useEnergy(5)) {\n\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\treturn;\n\t\t}\n\t\tNBTTagList list = itemlist.getTagList(\"inventar\", 10);\n\t\tfinal List<ItemIdentifierStack> transaction = new ArrayList<>(list.tagCount());\n\t\tfor (int i = 0; i < list.tagCount(); i++) {\n\t\t\tNBTTagCompound itemnbt = list.getCompoundTagAt(i);\n\t\t\tNBTTagCompound itemNBTContent = itemnbt.getCompoundTag(\"nbt\");\n\t\t\tif (!itemnbt.hasKey(\"nbt\")) {\n\t\t\t\titemNBTContent = null;\n\t\t\t}\n\t\t\tItemIdentifierStack stack = ItemIdentifier.get(Item.getItemById(itemnbt.getInteger(\"id\")), itemnbt.getInteger(\"data\"), itemNBTContent).makeStack(itemnbt.getInteger(\"amount\"));\n\t\t\ttransaction.add(stack);\n\t\t}\n\t\tRequestTree.request(transaction, requester, new RequestLog() {\n\n\t\t\t@Override\n\t\t\tpublic void handleMissingItems(List<IResource> resources) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(resources).setFlag(true), player);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList parts) {}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList parts) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(resources).setFlag(false), player);\n\t\t\t\tif (requester instanceof IRequestWatcher) {\n\t\t\t\t\t((IRequestWatcher) requester).handleOrderList(null, parts);\n\t\t\t\t}\n\t\t\t}\n\t\t}, RequestTree.defaultRequestFlags, null);\n\t}\n\n\tpublic static Object[] computerRequest(final ItemIdentifierStack makeStack, final CoreRoutedPipe pipe, boolean craftingOnly) {\n\n\t\tEnumSet<ActiveRequestType> requestFlags;\n\t\tif (craftingOnly) {\n\t\t\trequestFlags = EnumSet.of(ActiveRequestType.Craft);\n\t\t} else {\n\t\t\trequestFlags = EnumSet.of(ActiveRequestType.Craft, ActiveRequestType.Provide);\n\t\t}\n\t\tif (!pipe.useEnergy(15)) {\n\t\t\treturn new Object[] { \"NO_POWER\" };\n\t\t}\n\t\tfinal Object[] status = new Object[2];\n\t\tRequestTree.request(makeStack, pipe, new RequestLog() {\n\n\t\t\t@Override\n\t\t\tpublic void handleMissingItems(List<IResource> resources) {\n\t\t\t\tstatus[0] = \"MISSING\";\n\t\t\t\tstatus[1] = resources;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList parts) {\n\t\t\t\tstatus[0] = \"DONE\";\n\t\t\t\tList<IResource> itemList = new LinkedList<>();\n\t\t\t\titemList.add(item);\n\t\t\t\tstatus[1] = itemList;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList parts) {}\n\t\t}, false, false, true, false, requestFlags, null);\n\t\treturn status;\n\t}\n\n\tpublic static void refreshFluid(EntityPlayer player, CoreRoutedPipe pipe) {\n\t\tTreeSet<FluidIdentifierStack> _allItems = SimpleServiceLocator.logisticsFluidManager.getAvailableFluid(pipe.getRouter().getIRoutersByCost());\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OrdererContent.class)\n\t\t\t\t\t\t.setIdentSet(\n\t\t\t\t\t\t\t\t_allItems.stream()\n\t\t\t\t\t\t\t\t\t\t.map(item -> new ItemIdentifierStack(item.getFluid().getItemIdentifier(), item.getAmount()))\n\t\t\t\t\t\t\t\t\t\t.collect(Collectors.toCollection(TreeSet::new))\n\t\t\t\t\t\t)\n\t\t\t\t, player);\n\t}\n\n\tpublic static void requestFluid(final EntityPlayer player, final ItemIdentifierStack stack, CoreRoutedPipe pipe, IRequestFluid requester) {\n\t\tif (!pipe.useEnergy(10)) {\n\t\t\tplayer.sendMessage(new TextComponentTranslation(\"lp.misc.noenergy\"));\n\t\t\treturn;\n\t\t}\n\n\t\tRequestTree.requestFluid(FluidIdentifier.get(stack.getItem()), stack.getStackSize(), requester, new RequestLog() {\n\n\t\t\t@Override\n\t\t\tpublic void handleMissingItems(List<IResource> resources) {\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(resources).setFlag(true), player);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList parts) {\n\t\t\t\tCollection<IResource> coll = new ArrayList<>(1);\n\t\t\t\tcoll.add(item);\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(MissingItems.class).setItems(coll).setFlag(false), player);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList parts) {}\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/RequestLog.java",
    "content": "package logisticspipes.request;\n\nimport java.util.List;\n\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\n\npublic interface RequestLog {\n\n\tvoid handleMissingItems(List<IResource> resources);\n\n\tvoid handleSucessfullRequestOf(IResource item, LinkedLogisticsOrderList paticipating);\n\n\tvoid handleSucessfullRequestOfList(List<IResource> resources, LinkedLogisticsOrderList paticipating);\n}\n"
  },
  {
    "path": "common/logisticspipes/request/RequestTree.java",
    "content": "package logisticspipes.request;\n\nimport java.util.Comparator;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.init.Blocks;\nimport net.minecraft.item.Item;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IProvide;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.request.resources.FluidResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.utils.FinalPair;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.IHavePriority;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class RequestTree extends RequestTreeNode {\n\n\tpublic enum ActiveRequestType {\n\t\tProvide,\n\t\tCraft,\n\t\tAcceptPartial,\n\t\tSimulateOnly,\n\t\tLogMissing,\n\t\tLogUsed\n\t}\n\n\tpublic static final EnumSet<ActiveRequestType> defaultRequestFlags = EnumSet.of(ActiveRequestType.Provide, ActiveRequestType.Craft);\n\tprivate HashMap<FinalPair<IProvide, ItemIdentifier>, Integer> _promisetotals;\n\n\tpublic RequestTree(IResource requestType, RequestTree parent, EnumSet<ActiveRequestType> requestFlags, IAdditionalTargetInformation info) {\n\t\tsuper(requestType, parent, requestFlags, info);\n\t}\n\n\tprivate int getExistingPromisesFor(FinalPair<IProvide, ItemIdentifier> key) {\n\t\tif (_promisetotals == null) {\n\t\t\t_promisetotals = new HashMap<>();\n\t\t}\n\t\tInteger n = _promisetotals.get(key);\n\t\tif (n == null) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn n;\n\t}\n\n\tpublic int getAllPromissesFor(IProvide provider, ItemIdentifier item) {\n\t\tFinalPair<IProvide, ItemIdentifier> key = new FinalPair<>(provider, item);\n\t\treturn getExistingPromisesFor(key);\n\t}\n\n\tpublic LinkedList<IExtraPromise> getExtrasFor(IResource item) {\n\t\tHashMap<IProvide, List<IExtraPromise>> extraMap = new HashMap<>();\n\t\tcheckForExtras(item, extraMap);\n\t\tremoveUsedExtras(item, extraMap);\n\t\tLinkedList<IExtraPromise> extras = new LinkedList<>();\n\t\textraMap.values().forEach(extras::addAll);\n\t\treturn extras;\n\t}\n\n\tprotected LinkedLogisticsOrderList fullFillAll() {\n\t\treturn fullFill();\n\t}\n\n\tpublic void sendMissingMessage(RequestLog log) {\n\t\tMap<IResource, Integer> missing = new HashMap<>();\n\t\tbuildMissingMap(missing);\n\t\tlog.handleMissingItems(RequestTreeNode.shrinkToList(missing));\n\t}\n\n\tpublic void sendUsedMessage(RequestLog log) {\n\t\tMap<IResource, Integer> used = new HashMap<>();\n\t\tMap<IResource, Integer> missing = new HashMap<>();\n\t\tbuildUsedMap(used, missing);\n\t\tlog.handleSucessfullRequestOfList(RequestTreeNode.shrinkToList(used), new LinkedLogisticsOrderList());\n\t\tlog.handleMissingItems(RequestTreeNode.shrinkToList(missing));\n\t}\n\n\tprotected void promiseAdded(IPromise promise) {\n\t\tFinalPair<IProvide, ItemIdentifier> key = new FinalPair<>(promise.getProvider(), promise.getItemType());\n\t\tif (_promisetotals == null) {\n\t\t\t_promisetotals = new HashMap<>();\n\t\t}\n\t\t_promisetotals.put(key, getExistingPromisesFor(key) + promise.getAmount());\n\t}\n\n\tprotected void promiseRemoved(IPromise promise) {\n\t\tFinalPair<IProvide, ItemIdentifier> key = new FinalPair<>(promise.getProvider(), promise.getItemType());\n\t\tint r = getExistingPromisesFor(key) - promise.getAmount();\n\t\tif (r == 0) {\n\t\t\t_promisetotals.remove(key);\n\t\t} else {\n\t\t\t_promisetotals.put(key, r);\n\t\t}\n\t}\n\n\tpublic static class workWeightedSorter implements Comparator<ExitRoute> {\n\n\t\tpublic final double distanceWeight;\n\n\t\tpublic workWeightedSorter(double distanceWeight) {\n\t\t\tthis.distanceWeight = distanceWeight;\n\t\t}\n\n\t\t@Override\n\t\tpublic int compare(ExitRoute o1, ExitRoute o2) {\n\t\t\tint c;\n\t\t\tfinal CoreRoutedPipe firstExitPipe = o1.destination.getPipe();\n\t\t\tfinal CoreRoutedPipe secondExitPipe = o2.destination.getPipe();\n\t\t\tif (firstExitPipe instanceof IHavePriority) {\n\t\t\t\tif (secondExitPipe instanceof IHavePriority) {\n\t\t\t\t\tc = Integer.compare(((IHavePriority) secondExitPipe).getPriority(), ((IHavePriority) firstExitPipe).getPriority());\n\t\t\t\t\tif (c != 0) {\n\t\t\t\t\t\treturn c;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (secondExitPipe instanceof IHavePriority) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (distanceWeight < 1/64.0) {\n\t\t\t\tc = Double.compare(firstExitPipe.getLoadFactor(), secondExitPipe.getLoadFactor());\n\t\t\t} else {\n\t\t\t\tc = Double.compare(\n\t\t\t\t\t\t(firstExitPipe.getLoadFactor() * 64) + (o1.distanceToDestination * distanceWeight),\n\t\t\t\t\t\t(secondExitPipe.getLoadFactor() * 64) + (o2.distanceToDestination * distanceWeight));\n\t\t\t}\n\t\t\treturn c;\n\t\t}\n\n\t}\n\n\tpublic static boolean request(List<ItemIdentifierStack> items, IRequestItems requester, RequestLog log, EnumSet<ActiveRequestType> requestFlags, IAdditionalTargetInformation info) {\n\t\tMap<IResource, Integer> messages = new HashMap<>();\n\t\tRequestTree tree = new RequestTree(new ItemResource(new ItemIdentifierStack(ItemIdentifier.get(Item.getItemFromBlock(Blocks.STONE), 0, null), 0), requester), null, requestFlags, info);\n\t\tboolean isDone = true;\n\t\tfor (ItemIdentifierStack stack : items) {\n\t\t\tItemResource req = new ItemResource(stack, requester);\n\t\t\tInteger count = messages.get(req);\n\t\t\tif (count == null) {\n\t\t\t\tcount = 0;\n\t\t\t}\n\t\t\tcount += stack.getStackSize();\n\t\t\tmessages.put(req, count);\n\t\t\tRequestTree node = new RequestTree(req, tree, requestFlags, info);\n\t\t\tisDone = isDone && node.isDone();\n\t\t}\n\t\tif (isDone) {\n\t\t\tLinkedLogisticsOrderList list = tree.fullFillAll();\n\t\t\tif (log != null) {\n\t\t\t\tlog.handleSucessfullRequestOfList(RequestTreeNode.shrinkToList(messages), list);\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tif (log != null) {\n\t\t\t\ttree.logFailedRequestTree(log);\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic static int request(ItemIdentifierStack item, IRequestItems requester, RequestLog log, boolean acceptPartial, boolean simulateOnly, boolean logMissing, boolean logUsed, EnumSet<ActiveRequestType> requestFlags, IAdditionalTargetInformation info) {\n\t\tItemResource req = new ItemResource(item, requester);\n\t\tRequestTree tree = new RequestTree(req, null, requestFlags, info);\n\t\tif (!simulateOnly && (tree.isDone() || ((tree.getPromiseAmount() > 0) && acceptPartial))) {\n\t\t\tLinkedLogisticsOrderList list = tree.fullFillAll();\n\t\t\tif (log != null) {\n\t\t\t\tlog.handleSucessfullRequestOf(req.copyForDisplayWith(item.getStackSize()), list);\n\t\t\t}\n\t\t\treturn tree.getPromiseAmount();\n\t\t} else {\n\t\t\tif (log != null) {\n\t\t\t\tif (!tree.isDone()) {\n\t\t\t\t\ttree.recurseFailedRequestTree();\n\t\t\t\t}\n\t\t\t\tif (logMissing) {\n\t\t\t\t\ttree.sendMissingMessage(log);\n\t\t\t\t}\n\t\t\t\tif (logUsed) {\n\t\t\t\t\ttree.sendUsedMessage(log);\n\t\t\t\t}\n\n\t\t\t}\n\t\t\treturn tree.getPromiseAmount();\n\t\t}\n\t}\n\n\tpublic static boolean request(ItemIdentifierStack item, IRequestItems requester, RequestLog log, IAdditionalTargetInformation info) {\n\t\treturn RequestTree.request(item, requester, log, false, false, true, false, RequestTree.defaultRequestFlags, info) == item.getStackSize();\n\t}\n\n\tpublic static int requestPartial(ItemIdentifierStack item, IRequestItems requester, IAdditionalTargetInformation info) {\n\t\treturn RequestTree.request(item, requester, null, true, false, true, false, RequestTree.defaultRequestFlags, info);\n\t}\n\n\tpublic static int simulate(ItemIdentifierStack item, IRequestItems requester, RequestLog log) {\n\t\treturn RequestTree.request(item, requester, log, true, true, false, true, RequestTree.defaultRequestFlags, null);\n\t}\n\n\tpublic static int requestFluidPartial(FluidIdentifier liquid, int amount, IRequestFluid pipe, RequestLog log) {\n\t\treturn RequestTree.requestFluid(liquid, amount, pipe, log, true);\n\t}\n\n\tpublic static boolean requestFluid(FluidIdentifier liquid, int amount, IRequestFluid pipe, RequestLog log) {\n\t\treturn RequestTree.requestFluid(liquid, amount, pipe, log, false) == amount;\n\t}\n\n\tprivate static int requestFluid(FluidIdentifier liquid, int amount, IRequestFluid pipe, RequestLog log, boolean acceptPartial) {\n\t\tFluidResource req = new FluidResource(liquid, amount, pipe);\n\t\tRequestTree request = new RequestTree(req, null, RequestTree.defaultRequestFlags, null);\n\t\tif (request.isDone() || acceptPartial) {\n\t\t\trequest.fullFill();\n\t\t\tif (log != null) {\n\t\t\t\tlog.handleSucessfullRequestOf(req.copyForDisplayWith(req.getRequestedAmount()), null);\n\t\t\t}\n\t\t\treturn request.getPromiseAmount();\n\t\t} else {\n\t\t\tif (log != null) {\n\t\t\t\trequest.sendMissingMessage(log);\n\t\t\t}\n\t\t\treturn request.getPromiseAmount();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/RequestTreeNode.java",
    "content": "package logisticspipes.request;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.PriorityQueue;\nimport java.util.Set;\nimport java.util.SortedSet;\nimport java.util.TreeSet;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.ICraft;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.interfaces.routing.IProvide;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.request.RequestTree.ActiveRequestType;\nimport logisticspipes.request.RequestTree.workWeightedSorter;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.routing.order.LinkedLogisticsOrderList;\nimport logisticspipes.routing.order.LogisticsOrderManager;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class RequestTreeNode {\n\n\tprotected final RequestTree root;\n\t@Getter\n\tprivate final IResource requestType;\n\tprivate final IAdditionalTargetInformation info;\n\tprivate final RequestTreeNode parentNode;\n\tprivate List<RequestTreeNode> subRequests = new ArrayList<>();\n\tprivate List<IPromise> promises = new ArrayList<>();\n\tprivate List<IExtraPromise> extrapromises = new ArrayList<>();\n\tprivate List<IExtraPromise> byproducts = new ArrayList<>();\n\tprivate SortedSet<ICraftingTemplate> usedCrafters = new TreeSet<>();\n\tprivate Set<LogisticsOrderManager<?, ?>> usedExtrasFromManager = new HashSet<LogisticsOrderManager<?, ?>>();\n\tprivate ICraftingTemplate lastCrafterTried = null;\n\tprivate int promiseAmount = 0;\n\n\tprotected RequestTreeNode(IResource requestType, RequestTreeNode parentNode, EnumSet<ActiveRequestType> requestFlags, IAdditionalTargetInformation info) {\n\t\tthis(null, requestType, parentNode, requestFlags, info);\n\t}\n\n\tprivate RequestTreeNode(ICraftingTemplate template, IResource requestType, RequestTreeNode parentNode, EnumSet<ActiveRequestType> requestFlags, IAdditionalTargetInformation info) {\n\t\tthis.info = info;\n\t\tthis.parentNode = parentNode;\n\t\tthis.requestType = requestType;\n\t\tif (parentNode != null) {\n\t\t\tparentNode.subRequests.add(this);\n\t\t\troot = parentNode.root;\n\t\t} else {\n\t\t\troot = (RequestTree) this;\n\t\t}\n\t\tif (template != null) {\n\t\t\tdeclareCrafterUsed(template);\n\t\t}\n\n\t\tif (requestFlags.contains(ActiveRequestType.Provide) && checkProvider()) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (requestFlags.contains(ActiveRequestType.Craft) && checkExtras()) {\n\t\t\treturn;// crafting was able to complete\n\t\t}\n\n\t\tif (requestFlags.contains(ActiveRequestType.Craft) && checkCrafting()) {\n\t\t\treturn;// crafting was able to complete\n\t\t}\n\n\t\t// crafting is not done!\n\t}\n\n\tprivate static List<Pair<IProvide, List<IFilter>>> getProviders(IRouter destination, IResource item) {\n\n\t\t// get all the routers\n\t\tBitSet routersIndex = ServerRouter.getRoutersInterestedIn(item);\n\t\tList<ExitRoute> validSources = new ArrayList<>(); // get the routing table\n\t\tfor (int i = routersIndex.nextSetBit(0); i >= 0; i = routersIndex.nextSetBit(i + 1)) {\n\t\t\tIRouter r = SimpleServiceLocator.routerManager.getServerRouter(i);\n\n\t\t\tif (r.isCacheInvalid()) {\n\t\t\t\tcontinue; //Skip Routers without a valid pipe\n\t\t\t}\n\n\t\t\tList<ExitRoute> e = destination.getDistanceTo(r);\n\t\t\tif (e != null) {\n\t\t\t\tvalidSources.addAll(e);\n\t\t\t}\n\t\t}\n\t\t// closer providers are good\n\t\tvalidSources.sort(new workWeightedSorter(1.0));\n\n\t\tList<Pair<IProvide, List<IFilter>>> providers = new LinkedList<>();\n\t\tvalidSources.stream().filter(r -> r.containsFlag(PipeRoutingConnectionType.canRequestFrom)).forEach(r -> {\n\t\t\tCoreRoutedPipe pipe = r.destination.getPipe();\n\t\t\tif (pipe instanceof IProvide) {\n\t\t\t\tList<IFilter> list = new LinkedList<>(r.filters);\n\t\t\t\tproviders.add(new Pair<>((IProvide) pipe, list));\n\t\t\t}\n\t\t});\n\t\treturn providers;\n\t}\n\n\tprivate static List<Pair<ICraftingTemplate, List<IFilter>>> getCrafters(IResource iRequestType, List<ExitRoute> validDestinations) {\n\t\tList<Pair<ICraftingTemplate, List<IFilter>>> crafters = new ArrayList<>(validDestinations.size());\n\t\touter:\n\t\tfor (ExitRoute r : validDestinations) {\n\t\t\tCoreRoutedPipe pipe = r.destination.getPipe();\n\t\t\tif (r.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\tif (pipe instanceof ICraft) {\n\t\t\t\t\tICraftingTemplate craftable = ((ICraft) pipe).addCrafting(iRequestType);\n\t\t\t\t\tif (craftable != null) {\n\t\t\t\t\t\tfor (IFilter filter : r.filters) {\n\t\t\t\t\t\t\tif (filter.isBlocked() == filter.isFilteredItem(craftable.getResultItem()) || filter.blockCrafting()) {\n\t\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tList<IFilter> list = new LinkedList<>(r.filters);\n\t\t\t\t\t\tcrafters.add(new Pair<>(craftable, list));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// don't need to sort, as a sorted list is passed in and List guarantees order preservation\n\t\t//\t\tCollections.sort(crafters,new CraftingTemplate.PairPrioritizer());\n\t\treturn crafters;\n\t}\n\n\tprotected static List<IResource> shrinkToList(Map<IResource, Integer> items) {\n\t\tList<IResource> resources = new ArrayList<>();\n\t\touter:\n\t\tfor (Entry<IResource, Integer> entry : items.entrySet()) {\n\t\t\tfor (IResource resource : resources) {\n\t\t\t\tif (resource.mergeForDisplay(entry.getKey(), entry.getValue())) {\n\t\t\t\t\tcontinue outer;\n\t\t\t\t}\n\t\t\t}\n\t\t\tresources.add(entry.getKey().copyForDisplayWith(entry.getValue()));\n\t\t}\n\t\treturn resources;\n\t}\n\n\tprivate boolean isCrafterUsed(ICraftingTemplate test) {\n\t\tif (!usedCrafters.isEmpty() && usedCrafters.contains(test)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (parentNode == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn parentNode.isCrafterUsed(test);\n\t}\n\n\t// returns false if the crafter was already on the list.\n\tprivate boolean declareCrafterUsed(ICraftingTemplate test) {\n\t\tif (isCrafterUsed(test)) {\n\t\t\treturn false;\n\t\t}\n\t\tusedCrafters.add(test);\n\t\treturn true;\n\t}\n\n\tpublic int getPromiseAmount() {\n\t\treturn promiseAmount;\n\t}\n\n\tpublic int getMissingAmount() {\n\t\treturn requestType.getRequestedAmount() - promiseAmount;\n\t}\n\n\tpublic void addPromise(IPromise promise) {\n\t\tif (!promise.matches(requestType)) {\n\t\t\tthrow new IllegalArgumentException(\"wrong item\");\n\t\t}\n\t\tif (getMissingAmount() == 0) {\n\t\t\tthrow new IllegalArgumentException(\"zero count needed, promises not needed.\");\n\t\t}\n\t\tif (promise.getAmount() > getMissingAmount()) {\n\t\t\tint more = promise.getAmount() - getMissingAmount();\n\t\t\t//promise.numberOfItems = getMissingAmount();\n\t\t\t//Add Extra\n\t\t\t//LogisticsExtraPromise extra = new LogisticsExtraPromise(promise.item, more, promise.sender, false);\n\t\t\textrapromises.add(promise.split(more));\n\t\t}\n\t\tif (promise.getAmount() <= 0) {\n\t\t\tthrow new IllegalArgumentException(\"zero count ... again\");\n\t\t}\n\t\tpromises.add(promise);\n\t\tpromiseAmount += promise.getAmount();\n\t\troot.promiseAdded(promise);\n\t}\n\n\tpublic boolean isDone() {\n\t\treturn getMissingAmount() <= 0;\n\t}\n\n\tpublic boolean isAllDone() {\n\t\tboolean result = getMissingAmount() <= 0;\n\t\tfor (RequestTreeNode node : subRequests) {\n\t\t\tresult &= node.isAllDone();\n\t\t}\n\t\treturn result;\n\t}\n\n\tprotected void remove(RequestTreeNode subNode) {\n\t\tsubRequests.remove(subNode);\n\t\tsubNode.removeSubPromisses();\n\t}\n\n\t/* RequestTree helpers */\n\tprotected void removeSubPromisses() {\n\t\tpromises.forEach(root::promiseRemoved);\n\t\tsubRequests.forEach(RequestTreeNode::removeSubPromisses);\n\t}\n\n\tprotected void checkForExtras(IResource item, HashMap<IProvide, List<IExtraPromise>> extraMap) {\n\t\tfor (IExtraPromise extra : extrapromises) {\n\t\t\tif (item.matches(extra.getItemType(), IResource.MatchSettings.NORMAL)) {\n\t\t\t\tList<IExtraPromise> extras = extraMap.get(extra.getProvider());\n\t\t\t\tif (extras == null) {\n\t\t\t\t\textras = new LinkedList<>();\n\t\t\t\t\textraMap.put(extra.getProvider(), extras);\n\t\t\t\t}\n\t\t\t\textras.add(extra.copy());\n\t\t\t}\n\t\t}\n\t\tfor (RequestTreeNode subNode : subRequests) {\n\t\t\tsubNode.checkForExtras(item, extraMap);\n\t\t}\n\t}\n\n\tprotected void removeUsedExtras(IResource item, HashMap<IProvide, List<IExtraPromise>> extraMap) {\n\t\tfor (IPromise promise : promises) {\n\t\t\tif (!item.matches(promise.getItemType(), IResource.MatchSettings.NORMAL)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!(promise instanceof IExtraPromise)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tIExtraPromise epromise = (IExtraPromise) promise;\n\t\t\tif (epromise.isProvided()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint usedcount = epromise.getAmount();\n\t\t\tList<IExtraPromise> extras = extraMap.get(epromise.getProvider());\n\t\t\tif (extras == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (Iterator<IExtraPromise> it = extras.iterator(); it.hasNext(); ) {\n\t\t\t\tIExtraPromise extra = it.next();\n\t\t\t\tif (extra.getAmount() >= usedcount) {\n\t\t\t\t\textra.lowerAmount(usedcount);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tusedcount -= extra.getAmount();\n\t\t\t\t\tit.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (RequestTreeNode subNode : subRequests) {\n\t\t\tsubNode.removeUsedExtras(item, extraMap);\n\t\t}\n\t}\n\n\tprotected LinkedLogisticsOrderList fullFill() {\n\t\tLinkedLogisticsOrderList list = new LinkedLogisticsOrderList();\n\t\tfor (RequestTreeNode subNode : subRequests) {\n\t\t\tlist.getSubOrders().add(subNode.fullFill());\n\t\t}\n\t\tfor (IPromise promise : promises) {\n\t\t\tIOrderInfoProvider result = promise.fullFill(requestType, info);\n\t\t\tif (result != null) {\n\t\t\t\tlist.add(result);\n\t\t\t}\n\t\t}\n\t\tfor (IExtraPromise promise : extrapromises) {\n\t\t\tpromise.registerExtras(requestType);\n\t\t}\n\t\tfor (IExtraPromise promise : byproducts) {\n\t\t\tpromise.registerExtras(requestType);\n\t\t}\n\t\treturn list;\n\t}\n\n\tprotected void buildMissingMap(Map<IResource, Integer> missing) {\n\t\tif (getMissingAmount() != 0) {\n\t\t\tInteger count = missing.get(getRequestType());\n\t\t\tif (count == null) {\n\t\t\t\tcount = 0;\n\t\t\t}\n\t\t\tcount += getMissingAmount();\n\t\t\tmissing.put(getRequestType(), count);\n\t\t}\n\t\tfor (RequestTreeNode subNode : subRequests) {\n\t\t\tsubNode.buildMissingMap(missing);\n\t\t}\n\t}\n\n\tprotected void buildUsedMap(Map<IResource, Integer> used, Map<IResource, Integer> missing) {\n\t\tint usedcount = 0;\n\t\tfor (IPromise promise : promises) {\n\t\t\tif (promise.getType() == ResourceType.PROVIDER) {\n\t\t\t\tusedcount += promise.getAmount();\n\t\t\t}\n\t\t}\n\t\tif (usedcount != 0) {\n\t\t\tInteger count = used.get(getRequestType());\n\t\t\tif (count == null) {\n\t\t\t\tcount = 0;\n\t\t\t}\n\t\t\tcount += usedcount;\n\t\t\tused.put(getRequestType(), count);\n\t\t}\n\t\tif (getMissingAmount() != 0) {\n\t\t\tInteger count = missing.get(getRequestType());\n\t\t\tif (count == null) {\n\t\t\t\tcount = 0;\n\t\t\t}\n\t\t\tcount += getMissingAmount();\n\t\t\tmissing.put(getRequestType(), count);\n\t\t}\n\t\tfor (RequestTreeNode subNode : subRequests) {\n\t\t\tsubNode.buildUsedMap(used, missing);\n\t\t}\n\t}\n\n\tprivate boolean checkProvider() {\n\t\tCoreRoutedPipe thisPipe = requestType.getRouter().getCachedPipe();\n\t\tif (thisPipe == null) {\n\t\t\treturn false;\n\t\t}\n\t\tfor (Pair<IProvide, List<IFilter>> provider : RequestTreeNode.getProviders(requestType.getRouter(), getRequestType())) {\n\t\t\tif (isDone()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (provider.getValue1() == null || provider.getValue1().getRouter().getPipe() == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!thisPipe.isOnSameContainer(provider.getValue1().getRouter().getPipe())) {\n\t\t\t\tprovider.getValue1().canProvide(this, root, provider.getValue2());\n\t\t\t}\n\t\t}\n\t\treturn isDone();\n\t}\n\n\tprivate boolean checkExtras() {\n\t\tLinkedList<IExtraPromise> map = root.getExtrasFor(requestType);\n\t\tfor (IExtraPromise extraPromise : map) {\n\t\t\tif (isDone()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (extraPromise.getAmount() == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tboolean valid = false;\n\t\t\tList<ExitRoute> sources = extraPromise.getProvider().getRouter().getRouteTable().get(getRequestType().getRouter().getSimpleID());\n\t\t\touter:\n\t\t\tfor (ExitRoute source : sources) {\n\t\t\t\tif (source != null && source.containsFlag(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\t\t\tfor (ExitRoute node : getRequestType().getRouter().getIRoutersByCost()) {\n\t\t\t\t\t\tif (node.destination == extraPromise.getProvider().getRouter()) {\n\t\t\t\t\t\t\tif (node.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\t\t\t\t\tvalid = true;\n\t\t\t\t\t\t\t\tbreak outer;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (valid) {\n\t\t\t\textraPromise.setAmount(Math.min(extraPromise.getAmount(), getMissingAmount()));\n\t\t\t\taddPromise(extraPromise);\n\t\t\t}\n\t\t}\n\t\treturn isDone();\n\t}\n\n\tprivate boolean checkCrafting() {\n\n\t\t// get all the routers\n\t\tBitSet routersIndex = ServerRouter.getRoutersInterestedIn(getRequestType());\n\t\tList<ExitRoute> validSources = new ArrayList<>(); // get the routing table\n\t\tfor (int i = routersIndex.nextSetBit(0); i >= 0; i = routersIndex.nextSetBit(i + 1)) {\n\t\t\tIRouter r = SimpleServiceLocator.routerManager.getServerRouter(i);\n\n\t\t\tif (r.isCacheInvalid()) {\n\t\t\t\tcontinue; //Skip Routers without a valid pipe\n\t\t\t}\n\n\t\t\tList<ExitRoute> e = getRequestType().getRouter().getDistanceTo(r);\n\t\t\tif (e != null) {\n\t\t\t\tvalidSources.addAll(e);\n\t\t\t}\n\t\t}\n\t\tworkWeightedSorter wSorter = new workWeightedSorter(0); // distance doesn't matter, because ingredients have to be delivered to the crafter, and we can't tell how long that will take.\n\t\tCollections.sort(validSources, wSorter);\n\n\t\tList<Pair<ICraftingTemplate, List<IFilter>>> allCraftersForItem = RequestTreeNode.getCrafters(getRequestType(), validSources);\n\n\t\t// if you have a crafter which can make the top treeNode.getStack().getItem()\n\t\tIterator<Pair<ICraftingTemplate, List<IFilter>>> iterAllCrafters = allCraftersForItem.iterator();\n\n\t\t//a queue to store the crafters, sorted by todo; we will fill up from least-most in a balanced way.\n\t\tPriorityQueue<CraftingSorterNode> craftersSamePriority = new PriorityQueue<>(5);\n\t\tArrayList<CraftingSorterNode> craftersToBalance = new ArrayList<>();\n\t\t//TODO ^ Make this a generic list\n\t\tboolean done = false;\n\t\tPair<ICraftingTemplate, List<IFilter>> lastCrafter = null;\n\t\tint currentPriority = 0;\n\t\touter:\n\t\twhile (!done) {\n\n\t\t\t/// First: Create a list of all crafters with the same priority (craftersSamePriority).\n\t\t\tif (iterAllCrafters.hasNext()) {\n\t\t\t\tif (lastCrafter == null) {\n\t\t\t\t\tlastCrafter = iterAllCrafters.next();\n\t\t\t\t}\n\t\t\t} else if (lastCrafter == null) {\n\t\t\t\tdone = true;\n\t\t\t}\n\n\t\t\tint itemsNeeded = getMissingAmount();\n\n\t\t\tif (lastCrafter != null && (craftersSamePriority.isEmpty() || (currentPriority == lastCrafter.getValue1().getPriority()))) {\n\t\t\t\tcurrentPriority = lastCrafter.getValue1().getPriority();\n\t\t\t\tPair<ICraftingTemplate, List<IFilter>> crafter = lastCrafter;\n\t\t\t\tlastCrafter = null;\n\t\t\t\tICraftingTemplate template = crafter.getValue1();\n\t\t\t\tif (isCrafterUsed(template)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!template.canCraft(getRequestType())) {\n\t\t\t\t\tcontinue; // we this is crafting something else\n\t\t\t\t}\n\t\t\t\tfor (IFilter filter : crafter.getValue2()) { // is this filtered for some reason.\n\t\t\t\t\tif (filter.isBlocked() == filter.isFilteredItem(template.getResultItem()) || filter.blockCrafting()) {\n\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tCraftingSorterNode cn = new CraftingSorterNode(crafter, itemsNeeded, root, this);\n\t\t\t\t//\t\t\t\tif(cn.getWorkSetsAvailableForCrafting()>0)\n\t\t\t\tcraftersSamePriority.add(cn);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (craftersToBalance.isEmpty() && (craftersSamePriority == null || craftersSamePriority.isEmpty())) {\n\t\t\t\tcontinue; //nothing at this priority was available for crafting\n\t\t\t}\n\t\t\t/// end of crafter prioriy selection.\n\n\t\t\tif (craftersSamePriority.size() == 1) { // then no need to balance.\n\t\t\t\tcraftersToBalance.add(craftersSamePriority.poll());\n\t\t\t\t// automatically capped at the real amount of extra work.\n\t\t\t\tcraftersToBalance.get(0).addToWorkRequest(itemsNeeded);\n\t\t\t} else {\n\t\t\t\t//\t\t\t\tfor(CraftingSorterNode c:craftersSamePriority)\n\t\t\t\t//\t\t\t\t\tc.clearWorkRequest(); // so the max request isn't in there; nothing is reserved, balancing can work correctly.\n\n\t\t\t\t// go through this list, pull the crafter(s) with least work, add work until either they can not do more work,\n\t\t\t\t//   or the amount of work they have is equal to the next-least busy crafter. then pull the next crafter and repeat.\n\t\t\t\tif (!craftersSamePriority.isEmpty()) {\n\t\t\t\t\tcraftersToBalance.add(craftersSamePriority.poll());\n\t\t\t\t}\n\t\t\t\t// while we crafters that can work and we have work to do.\n\t\t\t\twhile (!craftersToBalance.isEmpty() && itemsNeeded > 0) {\n\t\t\t\t\t//while there is more, and the next crafter has the same toDo as the current one, add it to craftersToBalance.\n\t\t\t\t\t//  typically pulls 1 at a time, but may pull multiple, if they have the exact same todo.\n\t\t\t\t\twhile (!craftersSamePriority.isEmpty() && craftersSamePriority.peek().currentToDo() <= craftersToBalance.get(0).currentToDo()) {\n\t\t\t\t\t\tcraftersToBalance.add(craftersSamePriority.poll());\n\t\t\t\t\t}\n\n\t\t\t\t\t// find the most we can add this iteration\n\t\t\t\t\tint cap;\n\t\t\t\t\tif (!craftersSamePriority.isEmpty()) {\n\t\t\t\t\t\tcap = craftersSamePriority.peek().currentToDo();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcap = Integer.MAX_VALUE;\n\t\t\t\t\t}\n\n\t\t\t\t\t//split the work between N crafters, up to \"cap\" (at which point we would be dividing the work between N+1 crafters.\n\t\t\t\t\tint floor = craftersToBalance.get(0).currentToDo();\n\t\t\t\t\tcap = Math.min(cap, floor + (itemsNeeded + craftersToBalance.size() - 1) / craftersToBalance.size());\n\n\t\t\t\t\tfor (CraftingSorterNode crafter : craftersToBalance) {\n\t\t\t\t\t\tint request = Math.min(itemsNeeded, cap - floor);\n\t\t\t\t\t\tif (request > 0) {\n\t\t\t\t\t\t\tint craftingDone = crafter.addToWorkRequest(request);\n\t\t\t\t\t\t\titemsNeeded -= craftingDone; // ignored under-crafting\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} // all craftersToBalance exhausted, or work completed.\n\n\t\t\t}// end of else more than 1 crafter at this priority\n\t\t\t// commit this work set.\n\t\t\tIterator<CraftingSorterNode> iter = craftersToBalance.iterator();\n\t\t\twhile (iter.hasNext()) {\n\t\t\t\tCraftingSorterNode c = iter.next();\n\t\t\t\tif (c.stacksOfWorkRequested > 0 && !c.addWorkPromisesToTree()) { // then it ran out of resources\n\t\t\t\t\titer.remove();\n\t\t\t\t}\n\n\t\t\t}\n\t\t\titemsNeeded = getMissingAmount();\n\n\t\t\tif (itemsNeeded <= 0) {\n\t\t\t\tbreak; // we have everything we need for this crafting request\n\t\t\t}\n\n\t\t\t// don't clear, because we might have under-requested, and need to consider these again\n\t\t\tif (!craftersToBalance.isEmpty()) {\n\t\t\t\tdone = false;\n\t\t\t\t//craftersSamePriority.clear(); // we've extracted all we can from these priority crafters, and we still have more to do, back to the top to get the next priority level.\n\t\t\t}\n\t\t}\n\t\t//LogisticsPipes.log.info(\"done\");\n\t\treturn isDone();\n\t}\n\n\tpublic boolean hasBeenQueried(LogisticsOrderManager<?, ?> orderManager) {\n\t\treturn usedExtrasFromManager.contains(orderManager);\n\t}\n\n\tpublic void setQueried(LogisticsOrderManager<?, ?> orderManager) {\n\t\tusedExtrasFromManager.add(orderManager);\n\t}\n\n\tprivate int getSubRequests(int nCraftingSets, ICraftingTemplate template) {\n\t\tboolean failed = false;\n\t\tList<Pair<IResource, IAdditionalTargetInformation>> stacks = template.getComponents(nCraftingSets);\n\t\tint workSetsAvailable = nCraftingSets;\n\t\tArrayList<RequestTreeNode> lastNodes = new ArrayList<>(stacks.size());\n\t\tfor (Pair<IResource, IAdditionalTargetInformation> stack : stacks) {\n\t\t\tRequestTreeNode node = new RequestTreeNode(template, stack.getValue1(), this, RequestTree.defaultRequestFlags, stack.getValue2());\n\t\t\tlastNodes.add(node);\n\t\t\tif (!node.isDone()) {\n\t\t\t\tfailed = true;\n\t\t\t}\n\t\t}\n\t\tif (failed) {\n\t\t\t// drop the failed requests.\n\t\t\tlastNodes.forEach(RequestTreeNode::destroy);\n\t\t\t//save last tried template for filling out the tree\n\t\t\tlastCrafterTried = template;\n\t\t\t//figure out how many we can actually get\n\t\t\tfor (int i = 0; i < stacks.size(); i++) {\n\t\t\t\tworkSetsAvailable = Math.min(workSetsAvailable, lastNodes.get(i).getPromiseAmount() / (stacks.get(i).getValue1().getRequestedAmount() / nCraftingSets));\n\t\t\t}\n\n\t\t\treturn generateRequestTreeFor(workSetsAvailable, template);\n\t\t}\n\t\tbyproducts.addAll(new ArrayList<>(template.getByproducts(workSetsAvailable)));\n\t\treturn workSetsAvailable;\n\t}\n\n\tprivate int generateRequestTreeFor(int workSets, ICraftingTemplate template) {\n\t\t//and try it\n\t\tArrayList<RequestTreeNode> newChildren = new ArrayList<>();\n\t\tif (workSets > 0) {\n\t\t\t//now set the amounts\n\t\t\tList<Pair<IResource, IAdditionalTargetInformation>> stacks = template.getComponents(workSets);\n\t\t\tboolean failed = false;\n\t\t\tfor (Pair<IResource, IAdditionalTargetInformation> stack : stacks) {\n\t\t\t\tRequestTreeNode node = new RequestTreeNode(template, stack.getValue1(), this, RequestTree.defaultRequestFlags, stack.getValue2());\n\t\t\t\tnewChildren.add(node);\n\t\t\t\tif (!node.isDone()) {\n\t\t\t\t\tfailed = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (failed) {\n\t\t\t\tnewChildren.forEach(RequestTreeNode::destroy);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\tbyproducts.addAll(new ArrayList<>(template.getByproducts(workSets)));\n\t\treturn workSets;\n\t}\n\n\tvoid recurseFailedRequestTree() {\n\t\tif (isDone()) {\n\t\t\treturn;\n\t\t}\n\t\tif (lastCrafterTried == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tICraftingTemplate template = lastCrafterTried;\n\n\t\tint nCraftingSetsNeeded = (getMissingAmount() + template.getResultStackSize() - 1) / template.getResultStackSize();\n\n\t\tList<Pair<IResource, IAdditionalTargetInformation>> stacks = template.getComponents(nCraftingSetsNeeded);\n\n\t\tfor (Pair<IResource, IAdditionalTargetInformation> stack : stacks) {\n\t\t\tnew RequestTreeNode(template, stack.getValue1(), this, RequestTree.defaultRequestFlags, stack.getValue2());\n\t\t}\n\n\t\taddPromise(template.generatePromise(nCraftingSetsNeeded));\n\n\t\tsubRequests.forEach(RequestTreeNode::recurseFailedRequestTree);\n\t}\n\n\tprotected void logFailedRequestTree(RequestLog log) {\n\t\tMap<IResource, Integer> missing = new HashMap<>();\n\t\tsubRequests.stream().filter(node -> node instanceof RequestTree).filter(node -> !node.isDone())\n\t\t\t\t.forEach(node -> {\n\t\t\t\t\tnode.recurseFailedRequestTree();\n\t\t\t\t\tnode.buildMissingMap(missing);\n\t\t\t\t});\n\t\tlog.handleMissingItems(RequestTreeNode.shrinkToList(missing));\n\t}\n\n\tprivate void destroy() {\n\t\tparentNode.remove(this);\n\t}\n\n\tprivate class CraftingSorterNode implements Comparable<CraftingSorterNode> {\n\n\t\tpublic final Pair<ICraftingTemplate, List<IFilter>> crafter;\n\t\tpublic final int originalToDo;\n\t\tprivate final int setSize;\n\t\tprivate final int maxWorkSetsAvailable;\n\t\tprivate final RequestTreeNode treeNode; // current node we are calculating\n\t\tprivate int stacksOfWorkRequested;\n\n\t\tCraftingSorterNode(Pair<ICraftingTemplate, List<IFilter>> crafter, int maxCount, RequestTree tree, RequestTreeNode treeNode) {\n\t\t\tthis.crafter = crafter;\n\t\t\tthis.treeNode = treeNode;\n\t\t\toriginalToDo = crafter.getValue1().getCrafter().getTodo();\n\t\t\tstacksOfWorkRequested = 0;\n\t\t\tsetSize = crafter.getValue1().getResultStackSize();\n\t\t\tmaxWorkSetsAvailable = ((treeNode.getMissingAmount()) + setSize - 1) / setSize;\n\t\t}\n\n\t\tint calculateMaxWork(int maxSetsToCraft) {\n\n\t\t\tint nCraftingSetsNeeded;\n\t\t\tif (maxSetsToCraft == 0) {\n\t\t\t\tnCraftingSetsNeeded = ((treeNode.getMissingAmount()) + setSize - 1) / setSize;\n\t\t\t} else {\n\t\t\t\tnCraftingSetsNeeded = maxSetsToCraft;\n\t\t\t}\n\n\t\t\tif (nCraftingSetsNeeded == 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tICraftingTemplate template = crafter.getValue1();\n\n\t\t\treturn getSubRequests(nCraftingSetsNeeded, template);\n\t\t}\n\n\t\tint addToWorkRequest(int extraWork) {\n\t\t\tint stacksRequested = (extraWork + setSize - 1) / setSize;\n\t\t\tstacksOfWorkRequested += stacksRequested;\n\t\t\treturn stacksRequested * setSize;\n\t\t}\n\n\t\t/**\n\t\t * Add promises for the requested work to the tree.\n\t\t */\n\t\tboolean addWorkPromisesToTree() {\n\t\t\tICraftingTemplate template = crafter.getValue1();\n\t\t\tint setsToCraft = Math.min(stacksOfWorkRequested, maxWorkSetsAvailable);\n\t\t\tint setsAbleToCraft = calculateMaxWork(setsToCraft); // Deliberately outside the 0 check, because calling generatePromies(0) here clears the old ones.\n\n\t\t\tif (setsAbleToCraft > 0) { // sanity check, as creating 0 sized promises is an exception. This should never be hit.\n\t\t\t\t//if we got here, we can at least some of the remaining amount\n\t\t\t\tIPromise job = template.generatePromise(setsAbleToCraft);\n\t\t\t\tif (job.getAmount() != setsAbleToCraft * setSize) {\n\t\t\t\t\tthrow new IllegalStateException(\"generatePromises not creating the promisesPromised; this is goign to end badly.\");\n\t\t\t\t}\n\t\t\t\ttreeNode.addPromise(job);\n\t\t\t}\n\t\t\tboolean isDone = setsToCraft == setsAbleToCraft;\n\t\t\tstacksOfWorkRequested = 0; // just incase we call it twice.\n\t\t\treturn isDone;\n\t\t}\n\n\t\t@Override\n\t\tpublic int compareTo(CraftingSorterNode o) {\n\t\t\treturn currentToDo() - o.currentToDo();\n\t\t}\n\n\t\tpublic int currentToDo() {\n\t\t\treturn originalToDo + stacksOfWorkRequested * setSize;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/resources/DictResource.java",
    "content": "package logisticspipes.request.resources;\n\nimport java.util.BitSet;\nimport javax.annotation.Nonnull;\n\nimport com.google.common.base.Objects;\n\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.FuzzyFlag;\nimport network.rs485.logisticspipes.util.FuzzyUtil;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class DictResource implements IResource {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate final IRequestItems requester;\n\tpublic ItemIdentifierStack stack;\n\tprivate BitSet fuzzyFlags = new BitSet(4);\n\n\tpublic DictResource(ItemIdentifierStack stack, IRequestItems requester) {\n\t\tthis.stack = stack;\n\t\tthis.requester = requester;\n\t}\n\n\tpublic DictResource(LPDataInput input) {\n\t\tstack = input.readItemIdentifierStack();\n\t\trequester = null;\n\t\tfuzzyFlags = input.readBitSet().get(0, 3);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeItemIdentifierStack(stack);\n\t\toutput.writeBitSet(fuzzyFlags);\n\t}\n\n\t@Override\n\tpublic ItemIdentifier getAsItem() {\n\t\treturn stack.getItem();\n\t}\n\n\t@Override\n\tpublic int getRequestedAmount() {\n\t\treturn stack.getStackSize();\n\t}\n\n\t@Override\n\tpublic boolean matches(IResource resource, MatchSettings settings) {\n\t\tif (resource instanceof DictResource) {\n\t\t\treturn matches(((DictResource) resource).getItem(), IResource.MatchSettings.NORMAL)\n\t\t\t\t\t&& resource.matches(getItem(), IResource.MatchSettings.NORMAL)\n\t\t\t\t\t&& getBitSet().equals(((DictResource) resource).getBitSet());\n\t\t} else if (resource instanceof ItemResource) {\n\t\t\treturn matches(((ItemResource) resource).getItem(), MatchSettings.NORMAL);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean matches(ItemIdentifier other, MatchSettings settings) {\n\t\treturn FuzzyUtil.INSTANCE.fuzzyMatches(FuzzyUtil.INSTANCE.getter(fuzzyFlags), stack.getItem(), other);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\treturn requester.getRouter();\n\t}\n\n\t@Override\n\tpublic IResource clone(int multiplier) {\n\t\tItemIdentifierStack stack = new ItemIdentifierStack(this.stack);\n\t\tstack.setStackSize(stack.getStackSize() * multiplier);\n\t\tDictResource clone = new DictResource(stack, requester);\n\t\tclone.fuzzyFlags.or(fuzzyFlags);\n\t\treturn clone;\n\t}\n\n\tpublic DictResource clone() {\n\t\tDictResource clone = new DictResource(new ItemIdentifierStack(this.stack), requester);\n\t\tclone.fuzzyFlags.or(fuzzyFlags);\n\t\treturn clone;\n\t}\n\n\tpublic IRequestItems getTarget() {\n\t\treturn requester;\n\t}\n\n\tpublic ItemIdentifier getItem() {\n\t\treturn stack.getItem();\n\t}\n\n\tpublic ItemIdentifierStack getItemStack() {\n\t\treturn stack;\n\t}\n\n\t@Override\n\tpublic boolean mergeForDisplay(IResource resource, int withAmount) {\n\t\tif (resource instanceof DictResource) {\n\t\t\tif (((DictResource) resource).fuzzyFlags.equals(fuzzyFlags) && ((DictResource) resource).getItem()\n\t\t\t\t\t.equals(getItem())) {\n\t\t\t\tstack.setStackSize(stack.getStackSize() + withAmount);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IResource copyForDisplayWith(int amount) {\n\t\tItemIdentifierStack stack = new ItemIdentifierStack(this.stack);\n\t\tstack.setStackSize(amount);\n\t\tDictResource clone = new DictResource(stack, null);\n\t\tclone.fuzzyFlags.or(fuzzyFlags);\n\t\treturn clone;\n\t}\n\n\t@Override\n\tpublic String getDisplayText(ColorCode code) {\n\t\tStringBuilder builder = new StringBuilder();\n\t\tbuilder.append(ChatColor.GRAY);\n\t\tbuilder.append(\"{\");\n\t\tif (code != ColorCode.NONE) {\n\t\t\tbuilder.append(code == ColorCode.MISSING ? ChatColor.RED : ChatColor.GREEN);\n\t\t}\n\t\tbuilder.append(stack.getFriendlyName());\n\t\tif (code != ColorCode.NONE) {\n\t\t\tbuilder.append(ChatColor.GRAY);\n\t\t}\n\t\tbuilder.append(\" [\");\n\t\tbuilder.append(useOreDict() ? ChatColor.GREEN : ChatColor.RED);\n\t\tbuilder.append(\"OreDict\");\n\t\tbuilder.append(ChatColor.GRAY);\n\t\tbuilder.append(\", \");\n\t\tbuilder.append(useOreCategory() ? ChatColor.GREEN : ChatColor.RED);\n\t\tbuilder.append(\"OreCat\");\n\t\tbuilder.append(ChatColor.GRAY);\n\t\tbuilder.append(\", \");\n\t\tbuilder.append(ignoreDamage() ? ChatColor.GREEN : ChatColor.RED);\n\t\tbuilder.append(\"IgnDmg\");\n\t\tbuilder.append(ChatColor.GRAY);\n\t\tbuilder.append(\", \");\n\t\tbuilder.append(ignoreNBT() ? ChatColor.GREEN : ChatColor.RED);\n\t\tbuilder.append(\"IgnNBT\");\n\t\tbuilder.append(ChatColor.GRAY);\n\t\treturn builder.append(\"]}\").toString();\n\t}\n\n\t@Override\n\tpublic ItemIdentifierStack getDisplayItem() {\n\t\treturn stack;\n\t}\n\n\tpublic DictResource loadFromBitSet(BitSet bits) {\n\t\tfuzzyFlags.clear();\n\t\tfuzzyFlags.or(bits);\n\t\treturn this;\n\t}\n\n\tpublic BitSet getBitSet() {\n\t\treturn fuzzyFlags.get(0, 3);\n\t}\n\n\tpublic Identifier getIdentifier() {\n\t\treturn new Identifier();\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n\tpublic boolean useOreDict() {\n\t\treturn FuzzyUtil.INSTANCE.get(fuzzyFlags, FuzzyFlag.USE_ORE_DICT);\n\t}\n\n\tpublic boolean useOreCategory() {\n\t\treturn FuzzyUtil.INSTANCE.get(fuzzyFlags, FuzzyFlag.USE_ORE_CATEGORY);\n\t}\n\n\tpublic boolean ignoreDamage() {\n\t\treturn FuzzyUtil.INSTANCE.get(fuzzyFlags, FuzzyFlag.IGNORE_DAMAGE);\n\t}\n\n\tpublic boolean ignoreNBT() {\n\t\treturn FuzzyUtil.INSTANCE.get(fuzzyFlags, FuzzyFlag.IGNORE_NBT);\n\t}\n\n\tpublic class Identifier {\n\n\t\tprivate ItemIdentifier getItem() {\n\t\t\treturn stack.getItem();\n\t\t}\n\n\t\tprivate BitSet getBitSet() {\n\t\t\treturn DictResource.this.getBitSet();\n\t\t}\n\n\t\t@Override\n\t\tpublic int hashCode() {\n\t\t\treturn Objects.hashCode(getItem(), getBitSet());\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean equals(Object obj) {\n\t\t\tif (obj instanceof Identifier) {\n\t\t\t\tIdentifier id = (Identifier) obj;\n\t\t\t\treturn id.getItem().equals(getItem()) && id.getBitSet().equals(getBitSet());\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/request/resources/FluidResource.java",
    "content": "package logisticspipes.request.resources;\n\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class FluidResource implements IResource {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate final FluidIdentifier liquid;\n\tprivate final IRequestFluid target;\n\tprivate int amount;\n\n\tpublic FluidResource(FluidIdentifier liquid, int amount, IRequestFluid target) {\n\t\tthis.liquid = liquid;\n\t\tthis.amount = amount;\n\t\tthis.target = target;\n\t}\n\n\tpublic FluidResource(LPDataInput input) {\n\t\tliquid = FluidIdentifier.get(Objects.requireNonNull(input.readItemIdentifier()));\n\t\tamount = input.readInt();\n\t\ttarget = null;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeItemIdentifier(liquid.getItemIdentifier());\n\t\toutput.writeInt(amount);\n\t}\n\n\t@Override\n\tpublic ItemIdentifier getAsItem() {\n\t\treturn liquid.getItemIdentifier();\n\t}\n\n\t@Override\n\tpublic int getRequestedAmount() {\n\t\treturn amount;\n\t}\n\n\tpublic FluidIdentifier getFluid() {\n\t\treturn liquid;\n\t}\n\n\tpublic IRequestFluid getTarget() {\n\t\treturn target;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\treturn target.getRouter();\n\t}\n\n\t@Override\n\tpublic boolean matches(IResource resource, MatchSettings settings) {\n\t\treturn resource instanceof FluidResource && matches(resource.getAsItem(), settings);\n\t}\n\n\t@Override\n\tpublic boolean matches(ItemIdentifier itemType, MatchSettings settings) {\n\t\tif (itemType.isFluidContainer()) {\n\t\t\tFluidIdentifier other = FluidIdentifier.get(itemType);\n\t\t\treturn other.equals(liquid);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IResource clone(int multiplier) {\n\t\treturn new FluidResource(liquid, amount * multiplier, target);\n\t}\n\n\t@Override\n\tpublic boolean mergeForDisplay(IResource resource, int withAmount) {\n\t\tif (resource instanceof FluidResource) {\n\t\t\tif (((FluidResource) resource).liquid.equals(liquid)) {\n\t\t\t\tamount += withAmount;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IResource copyForDisplayWith(int amount) {\n\t\treturn new FluidResource(liquid, amount, null);\n\t}\n\n\t@Override\n\tpublic String getDisplayText(ColorCode code) {\n\t\tStringBuilder builder = new StringBuilder();\n\t\tif (code != ColorCode.NONE) {\n\t\t\tbuilder.append(code == ColorCode.MISSING ? ChatColor.RED : ChatColor.GREEN);\n\t\t}\n\t\tbuilder.append(amount);\n\t\tbuilder.append(\"mB \");\n\t\tbuilder.append(liquid.makeFluidStack(0).getLocalizedName());\n\t\tif (code != ColorCode.NONE) {\n\t\t\tbuilder.append(ChatColor.WHITE);\n\t\t}\n\t\treturn builder.toString();\n\t}\n\n\t@Override\n\tpublic ItemIdentifierStack getDisplayItem() {\n\t\treturn liquid.getItemIdentifier().makeStack(amount);\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/request/resources/IResource.java",
    "content": "package logisticspipes.request.resources;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.LPFinalSerializable;\n\n/**\n * With Destination and amount\n */\npublic interface IResource extends ILPCCTypeHolder, LPFinalSerializable {\n\n\tItemIdentifier getAsItem();\n\n\tint getRequestedAmount();\n\n\t@Nonnull\n\tIRouter getRouter();\n\n\tboolean matches(IResource resource, MatchSettings settings);\n\n\tboolean matches(ItemIdentifier itemType, MatchSettings settings);\n\n\tIResource clone(int multiplier);\n\n\tvoid writeData(LPDataOutput output);\n\n\tboolean mergeForDisplay(IResource resource, int withAmount); //Amount overrides existing amount inside the resource\n\n\tIResource copyForDisplayWith(int amount);\n\n\t@SideOnly(Side.CLIENT)\n\tString getDisplayText(ColorCode missing);\n\n\tItemIdentifierStack getDisplayItem();\n\n\t@Override\n\tdefault void write(LPDataOutput output) {\n\t\tResourceNetwork.writeResource(output, this);\n\t}\n\n\t/**\n\t * Settings only apply for the normal Item Implementation.\n\t */\n\tenum MatchSettings {\n\t\tNORMAL,\n\t\tWITHOUT_NBT\n\t}\n\n\tenum ColorCode {\n\t\tNONE,\n\t\tMISSING,\n\t\tSUCCESS\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/resources/ItemResource.java",
    "content": "package logisticspipes.request.resources;\n\nimport javax.annotation.Nonnull;\n\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.string.ChatColor;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class ItemResource implements IResource {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate final ItemIdentifierStack stack;\n\tprivate final IRequestItems requester;\n\n\tpublic ItemResource(ItemIdentifierStack stack, IRequestItems requester) {\n\t\tthis.stack = stack;\n\t\tthis.requester = requester;\n\t}\n\n\tpublic ItemResource(LPDataInput input) {\n\t\tstack = input.readItemIdentifierStack();\n\t\trequester = null;\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeItemIdentifierStack(stack);\n\t}\n\n\t@Override\n\tpublic ItemIdentifier getAsItem() {\n\t\treturn stack.getItem();\n\t}\n\n\t@Override\n\tpublic int getRequestedAmount() {\n\t\treturn stack.getStackSize();\n\t}\n\n\tpublic ItemIdentifier getItem() {\n\t\treturn stack.getItem();\n\t}\n\n\tpublic ItemIdentifierStack getItemStack() {\n\t\treturn stack;\n\t}\n\n\tpublic IRequestItems getTarget() {\n\t\treturn requester;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\treturn requester.getRouter();\n\t}\n\n\t@Override\n\tpublic boolean matches(IResource resource, MatchSettings settings) {\n\t\tif (resource instanceof DictResource) {\n\t\t\treturn resource.matches(this, settings);\n\t\t} else if (resource instanceof ItemResource) {\n\t\t\treturn matches(((ItemResource) resource).getItem(), settings)\n\t\t\t\t\t&& resource.matches(getItem(), settings);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean matches(ItemIdentifier itemType, MatchSettings settings) {\n\t\tswitch (settings) {\n\t\t\tcase NORMAL:\n\t\t\t\treturn stack.getItem().equals(itemType);\n\t\t\tcase WITHOUT_NBT:\n\t\t\t\treturn stack.getItem().equalsWithoutNBT(itemType);\n\t\t}\n\t\treturn stack.getItem().equals(itemType);\n\t}\n\n\t@Override\n\tpublic IResource clone(int multiplier) {\n\t\tItemIdentifierStack stack = new ItemIdentifierStack(this.stack);\n\t\tstack.setStackSize(stack.getStackSize() * multiplier);\n\t\treturn new ItemResource(stack, requester);\n\t}\n\n\t@Override\n\tpublic boolean mergeForDisplay(IResource resource, int withAmount) {\n\t\tif (resource instanceof ItemResource) {\n\t\t\tif (((ItemResource) resource).stack.getItem().equals(stack.getItem())) {\n\t\t\t\tstack.setStackSize(stack.getStackSize() + withAmount);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic IResource copyForDisplayWith(int amount) {\n\t\tItemIdentifierStack stack = new ItemIdentifierStack(this.stack);\n\t\tstack.setStackSize(amount);\n\t\treturn new ItemResource(stack, requester);\n\t}\n\n\t@Override\n\tpublic String getDisplayText(ColorCode code) {\n\t\tStringBuilder builder = new StringBuilder();\n\t\tif (code != ColorCode.NONE) {\n\t\t\tbuilder.append(code == ColorCode.MISSING ? ChatColor.RED : ChatColor.GREEN);\n\t\t}\n\t\tbuilder.append(stack.getFriendlyName());\n\t\tif (code != ColorCode.NONE) {\n\t\t\tbuilder.append(ChatColor.WHITE);\n\t\t}\n\t\treturn builder.toString();\n\t}\n\n\t@Override\n\tpublic ItemIdentifierStack getDisplayItem() {\n\t\treturn stack;\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\t// only ItemResources can be equal specifically\n\t\treturn obj instanceof ItemResource && matches((IResource) obj, MatchSettings.NORMAL);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"ItemResource(%s, target=%s)\", stack, requester);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/request/resources/ResourceNetwork.java",
    "content": "package logisticspipes.request.resources;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic enum ResourceNetwork {\n\tDictResource(DictResource.class) {\n\t\t@Override\n\t\tprotected IResource readData(LPDataInput input) {\n\t\t\treturn new DictResource(input);\n\t\t}\n\t},\n\tItemResource(ItemResource.class) {\n\t\t@Override\n\t\tprotected IResource readData(LPDataInput input) {\n\t\t\treturn new ItemResource(input);\n\t\t}\n\t},\n\tFluidResource(FluidResource.class) {\n\t\t@Override\n\t\tprotected IResource readData(LPDataInput input) {\n\t\t\treturn new FluidResource(input);\n\t\t}\n\t};\n\n\tprivate final Class<? extends IResource> clazz;\n\n\tResourceNetwork(Class<? extends IResource> clazz) {\n\t\tthis.clazz = clazz;\n\t}\n\n\tpublic static void writeResource(LPDataOutput output, IResource resource) {\n\t\tif (resource == null) {\n\t\t\toutput.writeInt(-1);\n\t\t\treturn;\n\t\t}\n\t\tResourceNetwork[] values = ResourceNetwork.values();\n\t\tfor (ResourceNetwork value : values) {\n\t\t\tif (value.clazz.isAssignableFrom(resource.getClass())) {\n\t\t\t\toutput.writeInt(value.ordinal());\n\t\t\t\tresource.writeData(output);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthrow new UnsupportedOperationException(resource.getClass().toString());\n\t}\n\n\tpublic static IResource readResource(LPDataInput input) {\n\t\tint id = input.readInt();\n\t\tif (id == -1) {\n\t\t\treturn null;\n\t\t}\n\t\treturn ResourceNetwork.values()[id].readData(input);\n\t}\n\n\tprotected abstract IResource readData(LPDataInput input);\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/ClientRouter.java",
    "content": "package logisticspipes.routing;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.UUID;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class ClientRouter implements IRouter {\n\n\tprivate final int _xCoord;\n\tprivate final int _yCoord;\n\tprivate final int _zCoord;\n\n\tpublic ClientRouter(UUID id, int dimension, int xCoord, int yCoord, int zCoord) {\n\t\t_xCoord = xCoord;\n\t\t_yCoord = yCoord;\n\t\t_zCoord = zCoord;\n\t}\n\n\t@Override\n\tpublic void destroy() {}\n\n\t@Override\n\tpublic int getSimpleID() {\n\t\treturn -420;\n\t}\n\n\t@Override\n\tpublic void update(boolean doFullRefresh, CoreRoutedPipe pipe) {}\n\n\t@Override\n\tpublic boolean isRoutedExit(EnumFacing connection) {\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tthrow new UnsupportedOperationException(\"noClientRouting\");\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean hasRoute(int id, boolean flag, ItemIdentifier item) {\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tthrow new UnsupportedOperationException(\"noClientRouting\");\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic ExitRoute getExitFor(int id, boolean flag, ItemIdentifier item) {\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tthrow new UnsupportedOperationException(\"noClientRouting\");\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic ArrayList<List<ExitRoute>> getRouteTable() {\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tthrow new UnsupportedOperationException(\"noClientRouting\");\n\t\t}\n\t\treturn new ArrayList<>();\n\t}\n\n\t@Override\n\tpublic List<ExitRoute> getIRoutersByCost() {\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tthrow new UnsupportedOperationException(\"noClientRouting\");\n\t\t}\n\t\treturn new LinkedList<>();\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getPipe() {\n\t\tWorld world = MainProxy.proxy.getWorld();\n\t\tif (world == null) {\n\t\t\treturn null;\n\t\t}\n\t\tTileEntity tile = world.getTileEntity(new BlockPos(_xCoord, _yCoord, _zCoord));\n\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\tLogisticsTileGenericPipe pipe = (LogisticsTileGenericPipe) tile;\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn (CoreRoutedPipe) pipe.pipe;\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getCachedPipe() {\n\t\treturn getPipe();\n\t}\n\n\t@Override\n\tpublic boolean isInDim(int dimension) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isAt(int dimension, int xCoord, int yCoord, int zCoord) {\n\t\treturn _xCoord == xCoord && _yCoord == yCoord && _zCoord == zCoord;\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getLPPosition() {\n\t\treturn new DoubleCoordinates(_xCoord, _yCoord, _zCoord);\n\t}\n\n\t@Override\n\tpublic UUID getId() {\n\t\treturn UUID.randomUUID();\n\t}\n\n\t@Override\n\tpublic LogisticsModule getLogisticsModule() {\n\t\tCoreRoutedPipe pipe = getPipe();\n\t\tif (pipe == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn pipe.getLogisticsModule();\n\t}\n\n\t@Override\n\tpublic void clearPipeCache() {}\n\n\t@Override\n\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> getPowerProvider() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isSideDisconnected(EnumFacing dir) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic List<ExitRoute> getDistanceTo(IRouter r) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void clearInterests() {}\n\n\t@Override\n\tpublic boolean isCacheInvalid() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void forceLsaUpdate() {}\n\n\t@Override\n\tpublic boolean isSubPoweredExit(EnumFacing connection) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic List<Pair<ISubSystemPowerProvider, List<IFilter>>> getSubSystemPowerProvider() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"ServerRouter: {UUID: %s, AT: (%d, %d, %d)}\", getId(), _xCoord, _yCoord, _zCoord);\n\t}\n\n\t@Override\n\tpublic List<ExitRoute> getRoutersOnSide(EnumFacing exitOrientation) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int getDistanceToNextPowerPipe(EnumFacing dir) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void queueTask(int i, IRouterQueuedTask callable) {}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/DummyRoutingDebugAdapter.java",
    "content": "package logisticspipes.routing;\n\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.PriorityQueue;\n\nimport logisticspipes.interfaces.IRoutingDebugAdapter;\nimport logisticspipes.interfaces.routing.IFilter;\n\npublic class DummyRoutingDebugAdapter implements IRoutingDebugAdapter {\n\n\t@Override\n\tpublic void start(PriorityQueue<ExitRoute> candidatesCost, ArrayList<EnumSet<PipeRoutingConnectionType>> closedSet, ArrayList<EnumMap<PipeRoutingConnectionType, List<List<IFilter>>>> filterList) {}\n\n\t@Override\n\tpublic void nextPipe(ExitRoute lowestCostNode) {}\n\n\t@Override\n\tpublic void handledPipe() {}\n\n\t@Override\n\tpublic void newCanidate(ExitRoute next) {}\n\n\t@Override\n\tpublic void stepOneDone() {}\n\n\t@Override\n\tpublic void stepTwoDone() {}\n\n\t@Override\n\tpublic void done() {}\n\n\t@Override\n\tpublic void init() {}\n\n\t@Override\n\tpublic void newFlagsForPipe(EnumSet<PipeRoutingConnectionType> newFlags) {}\n\n\t@Override\n\tpublic void filterList(EnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters) {}\n\n\t@Override\n\tpublic boolean independent() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isDebug() {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/ExitRoute.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.List;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.debug.ExitRouteDebug;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.LPFinalSerializable;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n/**\n * Defines direction with a cost\n */\npublic class ExitRoute implements Comparable<ExitRoute>, LPFinalSerializable {\n\n\tpublic final double destinationDistanceToRoot;\n\tpublic final int blockDistance;\n\tpublic final EnumSet<PipeRoutingConnectionType> connectionDetails;\n\tpublic final @Nonnull IRouter destination;\n\tpublic EnumFacing exitOrientation;\n\tpublic EnumFacing insertOrientation;\n\tpublic double distanceToDestination;\n\tpublic IRouter root;\n\tpublic List<IFilter> filters = Collections.unmodifiableList(new ArrayList<>(0));\n\t/**\n\t * Used to store debug information. No use in the actual Routing table\n\t * calculation\n\t */\n\tpublic ExitRouteDebug debug = new ExitRouteDebug();\n\n\tpublic ExitRoute(@Nullable IRouter source, @Nonnull IRouter destination, @Nullable EnumFacing exitOrientation, @Nullable EnumFacing insertOrientation, double metric,\n\t\t\tEnumSet<PipeRoutingConnectionType> connectionDetails, int blockDistance) {\n\t\tthis.destination = destination;\n\t\tthis.root = source;\n\t\tthis.exitOrientation = exitOrientation;\n\t\tthis.insertOrientation = insertOrientation;\n\t\tthis.connectionDetails = connectionDetails;\n\t\tif (connectionDetails.contains(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\tdistanceToDestination = metric;\n\t\t} else {\n\t\t\tdistanceToDestination = Integer.MAX_VALUE;\n\t\t}\n\t\tif (connectionDetails.contains(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\tdestinationDistanceToRoot = metric;\n\t\t} else {\n\t\t\tdestinationDistanceToRoot = Integer.MAX_VALUE;\n\t\t}\n\t\tthis.blockDistance = blockDistance;\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic ExitRoute(LPDataInput input) {\n\t\tif (!input.readBoolean()) {\n\t\t\tthrow new RuntimeException(\"Cannot read an ExitRoute without destination\");\n\t\t}\n\t\tfinal IRouter destinationRouter = readRouter(input);\n\t\tif (destinationRouter == null) {\n\t\t\tthrow new RuntimeException(\"Destination of the ExitRoute could not be determined\");\n\t\t}\n\t\tdestination = destinationRouter;\n\n\t\tif (input.readBoolean()) {\n\t\t\troot = readRouter(input);\n\t\t} else {\n\t\t\troot = null;\n\t\t}\n\n\t\texitOrientation = input.readFacing();\n\t\tinsertOrientation = input.readFacing();\n\n\t\tconnectionDetails = input.readEnumSet(PipeRoutingConnectionType.class);\n\n\t\tdistanceToDestination = input.readDouble();\n\n\t\tdouble metric = input.readDouble();\n\t\tif (!connectionDetails.contains(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\tmetric = Integer.MAX_VALUE;\n\t\t}\n\t\tdestinationDistanceToRoot = metric;\n\n\t\tblockDistance = input.readInt();\n\n\t\tdebug.filterPosition = input.readArrayList(DoubleCoordinates::new);\n\t\tdebug.toStringNetwork = input.readUTF();\n\t\tdebug.isNewlyAddedCanidate = input.readBoolean();\n\t\tdebug.isTraced = input.readBoolean();\n\t\tdebug.index = input.readInt();\n\t}\n\n\tpublic ExitRoute(IRouter source, IRouter destination, double distance, EnumSet<PipeRoutingConnectionType> enumSet, List<IFilter> filterA,\n\t\t\tList<IFilter> filterB, int blockDistance) {\n\t\tthis(source, destination, null, null, distance, enumSet, blockDistance);\n\t\tList<IFilter> filter = new ArrayList<>(filterA.size() + filterB.size());\n\t\tfilter.addAll(filterA);\n\t\tfilter.addAll(filterB);\n\t\tfilters = Collections.unmodifiableList(filter);\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tprivate IRouter readRouter(LPDataInput input) {\n\t\tDoubleCoordinates pos = new DoubleCoordinates(input);\n\t\tTileEntity tile = pos.getTileEntity(MainProxy.getClientMainWorld());\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe instanceof CoreRoutedPipe) {\n\t\t\treturn ((CoreRoutedPipe) ((LogisticsTileGenericPipe) tile).pipe).getRouter();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void write(LPDataOutput output) {\n\t\toutput.writeBoolean(true);\n\t\tdestination.write(output);\n\n\t\tif (root == null) {\n\t\t\toutput.writeBoolean(false);\n\t\t} else {\n\t\t\toutput.writeBoolean(true);\n\t\t\troot.write(output);\n\t\t}\n\n\t\toutput.writeFacing(exitOrientation);\n\t\toutput.writeFacing(insertOrientation);\n\n\t\toutput.writeEnumSet(connectionDetails, PipeRoutingConnectionType.class);\n\n\t\toutput.writeDouble(distanceToDestination);\n\n\t\toutput.writeDouble(destinationDistanceToRoot);\n\n\t\toutput.writeInt(blockDistance);\n\n\t\toutput.writeCollection(filters, (innerOutput, filter) -> innerOutput.writeSerializable(filter.getLPPosition()));\n\t\toutput.writeUTF(toString());\n\t\toutput.writeBoolean(debug.isNewlyAddedCanidate);\n\t\toutput.writeBoolean(debug.isTraced);\n\t\toutput.writeInt(debug.index);\n\t}\n\n\t@Override\n\tpublic boolean equals(Object aThat) {\n\t\t//check for self-comparison\n\t\tif (this == aThat) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!(aThat instanceof ExitRoute)) {\n\t\t\treturn false;\n\t\t}\n\t\tExitRoute that = (ExitRoute) aThat;\n\t\treturn exitOrientation.equals(that.exitOrientation) && insertOrientation.equals(that.insertOrientation) && connectionDetails.equals(that.connectionDetails) && distanceToDestination == that.distanceToDestination && destinationDistanceToRoot == that.destinationDistanceToRoot && destination == that.destination\n\t\t\t\t&& filters.equals(that.filters);\n\t}\n\n\tpublic boolean isSameWay(ExitRoute that) {\n\t\tif (equals(that)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn connectionDetails.equals(that.connectionDetails) && destination == that.destination && filters.equals(that.filters);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"ExitRoute(exitdir=%s, insertdir=%s, distance=%s, reverse distance=%s, conn. details=%s, \"\n\t\t\t\t\t\t+ \"filters=%s)\", exitOrientation, insertOrientation, distanceToDestination, destinationDistanceToRoot,\n\t\t\t\tconnectionDetails, filters);\n\t}\n\n\tpublic void removeFlags(EnumSet<PipeRoutingConnectionType> flags) {\n\t\tconnectionDetails.removeAll(flags);\n\t}\n\n\tpublic boolean containsFlag(PipeRoutingConnectionType flag) {\n\t\treturn connectionDetails.contains(flag);\n\t}\n\n\tpublic boolean hasActivePipe() {\n\t\treturn destination.getCachedPipe() != null;\n\t}\n\n\t//copies\n\tpublic EnumSet<PipeRoutingConnectionType> getFlags() {\n\t\treturn EnumSet.copyOf(connectionDetails);\n\t}\n\n\t// Doesn't copy\n\tpublic Set<PipeRoutingConnectionType> getFlagsNoCopy() {\n\t\treturn Collections.unmodifiableSet(connectionDetails);\n\t}\n\n\t@Override\n\tpublic int compareTo(ExitRoute o) {\n\t\tfinal int c = Double.compare(distanceToDestination, o.distanceToDestination);\n\t\tif (c == 0) {\n\t\t\treturn Integer.compare(destination.getSimpleID(), o.destination.getSimpleID());\n\t\t}\n\t\treturn c;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/FluidLogisticsPromise.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IProvide;\nimport logisticspipes.interfaces.routing.IProvideFluids;\nimport logisticspipes.request.IExtraPromise;\nimport logisticspipes.request.IPromise;\nimport logisticspipes.request.resources.FluidResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class FluidLogisticsPromise implements IPromise {\n\n\tpublic FluidIdentifier liquid;\n\tpublic int amount;\n\tpublic IProvideFluids sender;\n\tpublic ResourceType type;\n\n\t@Override\n\tpublic FluidLogisticsPromise copy() {\n\t\tFluidLogisticsPromise result = new FluidLogisticsPromise();\n\t\tresult.liquid = liquid;\n\t\tresult.amount = amount;\n\t\tresult.sender = sender;\n\t\tresult.type = type;\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic boolean matches(IResource requestType) {\n\t\tif (requestType instanceof FluidResource) {\n\t\t\tFluidResource fluid = (FluidResource) requestType;\n\t\t\treturn fluid.getFluid().equals(liquid);\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int getAmount() {\n\t\treturn amount;\n\t}\n\n\t@Override\n\tpublic IExtraPromise split(int more) {\n\t\t// TODO Add When Fluid crafing is supported\n\t\tthrow new UnsupportedOperationException(\"Fluid Promises can't be split\");\n\t}\n\n\t@Override\n\tpublic IProvide getProvider() {\n\t\treturn sender;\n\t}\n\n\t@Override\n\tpublic ItemIdentifier getItemType() {\n\t\treturn liquid.getItemIdentifier();\n\t}\n\n\t@Override\n\tpublic ResourceType getType() {\n\t\treturn type;\n\t}\n\n\t@Override\n\tpublic IOrderInfoProvider fullFill(IResource requestType, IAdditionalTargetInformation info) {\n\t\treturn sender.fullFill(this, ((FluidResource) requestType).getTarget(), type, info);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/IPaintPath.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport net.minecraft.world.World;\n\npublic interface IPaintPath {\n\n\tvoid addLaser(World world, LaserData laser);\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/IRouter.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.LPFinalSerializable;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface IRouter extends LPFinalSerializable {\n\n\tvoid destroy();\n\n\tvoid update(boolean doFullRefresh, CoreRoutedPipe pipe);\n\n\t// TODO: Check if all usages (non-texture related) are OK.\n\tboolean isRoutedExit(EnumFacing connection);\n\n\tboolean isSubPoweredExit(EnumFacing connection);\n\n\tint getDistanceToNextPowerPipe(EnumFacing dir);\n\n\tboolean hasRoute(int id, boolean active, ItemIdentifier type);\n\n\tExitRoute getExitFor(int id, boolean active, ItemIdentifier type);\n\n\tList<List<ExitRoute>> getRouteTable();\n\n\tList<ExitRoute> getIRoutersByCost();\n\n\tCoreRoutedPipe getPipe();\n\n\tCoreRoutedPipe getCachedPipe();\n\n\tboolean isInDim(int dimension);\n\n\tboolean isAt(int dimension, int xCoord, int yCoord, int zCoord);\n\n\tUUID getId();\n\n\tLogisticsModule getLogisticsModule();\n\n\tvoid clearPipeCache();\n\n\tint getSimpleID();\n\n\tDoubleCoordinates getLPPosition();\n\n\t/* Automated Disconnection */\n\tboolean isSideDisconnected(EnumFacing dir);\n\n\tList<ExitRoute> getDistanceTo(IRouter r);\n\n\tvoid clearInterests();\n\n\tList<Pair<ILogisticsPowerProvider, List<IFilter>>> getPowerProvider();\n\n\tList<Pair<ISubSystemPowerProvider, List<IFilter>>> getSubSystemPowerProvider();\n\n\tboolean isCacheInvalid();\n\n\t//force-update LSA version in the network\n\tvoid forceLsaUpdate();\n\n\tList<ExitRoute> getRoutersOnSide(EnumFacing direction);\n\n\tvoid queueTask(int i, IRouterQueuedTask callable);\n\n\t@Override\n\tdefault void write(LPDataOutput output) {\n\t\toutput.writeSerializable(getLPPosition());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/IRouterQueuedTask.java",
    "content": "package logisticspipes.routing;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\n\npublic interface IRouterQueuedTask {\n\n\tvoid call(CoreRoutedPipe pipe, IRouter router);\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/ItemRoutingInformation.java",
    "content": "package logisticspipes.routing;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.order.IDistanceTracker;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\n\npublic class ItemRoutingInformation {\n\n\tpublic static class DelayComparator implements Comparator<ItemRoutingInformation> {\n\n\t\t@Override\n\t\tpublic int compare(ItemRoutingInformation o1, ItemRoutingInformation o2) {\n\t\t\treturn (int) (o2.getTimeOut() - o1.getTimeOut()); // cast will never overflow because the delta is in 1/20ths of a second.\n\t\t}\n\t}\n\n\t@Override\n\tpublic ItemRoutingInformation clone() {\n\t\tItemRoutingInformation that = new ItemRoutingInformation();\n\t\tthat.destinationint = destinationint;\n\t\tthat.destinationUUID = destinationUUID;\n\t\tthat.arrived = arrived;\n\t\tthat.bufferCounter = bufferCounter;\n\t\tthat._doNotBuffer = _doNotBuffer;\n\t\tthat._transportMode = _transportMode;\n\t\tthat.jamlist = new ArrayList<>(jamlist);\n\t\tthat.tracker = tracker;\n\t\tthat.targetInfo = targetInfo;\n\t\tthat.item = new ItemIdentifierStack(getItem());\n\t\treturn that;\n\t}\n\n\tpublic int destinationint = -1;\n\tpublic UUID destinationUUID;\n\tpublic boolean arrived;\n\tpublic int bufferCounter = 0;\n\tpublic boolean _doNotBuffer;\n\tpublic TransportMode _transportMode = TransportMode.Unknown;\n\tpublic List<Integer> jamlist = new ArrayList<>();\n\tpublic IDistanceTracker tracker = null;\n\tpublic IAdditionalTargetInformation targetInfo;\n\n\tprivate long delay = 640 + MainProxy.getGlobalTick();\n\n\t@Getter\n\t@Setter\n\tprivate ItemIdentifierStack item;\n\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tif (nbttagcompound.hasKey(\"destinationUUID\")) {\n\t\t\tdestinationUUID = UUID.fromString(nbttagcompound.getString(\"destinationUUID\"));\n\t\t}\n\t\tarrived = nbttagcompound.getBoolean(\"arrived\");\n\t\tbufferCounter = nbttagcompound.getInteger(\"bufferCounter\");\n\t\t_transportMode = TransportMode.values()[nbttagcompound.getInteger(\"transportMode\")];\n\t\tItemStack stack = ItemStackLoader.loadAndFixItemStackFromNBT(nbttagcompound.getCompoundTag(\"Item\"));\n\t\tsetItem(ItemIdentifierStack.getFromStack(stack));\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tif (destinationUUID != null) {\n\t\t\tnbttagcompound.setString(\"destinationUUID\", destinationUUID.toString());\n\t\t}\n\t\tnbttagcompound.setBoolean(\"arrived\", arrived);\n\t\tnbttagcompound.setInteger(\"bufferCounter\", bufferCounter);\n\t\tnbttagcompound.setInteger(\"transportMode\", _transportMode.ordinal());\n\n\t\tNBTTagCompound nbttagcompound2 = new NBTTagCompound();\n\t\tgetItem().makeNormalStack().writeToNBT(nbttagcompound2);\n\t\tnbttagcompound.setTag(\"Item\", nbttagcompound2);\n\t}\n\n\t// the global LP tick in which getTickToTimeOut returns 0.\n\tpublic long getTimeOut() {\n\t\treturn delay;\n\t}\n\n\t// how many ticks until this times out\n\tpublic long getTickToTimeOut() {\n\t\treturn delay - MainProxy.getGlobalTick();\n\t}\n\n\tpublic void resetDelay() {\n\t\tdelay = 640 + MainProxy.getGlobalTick();\n\t\tif (tracker != null) {\n\t\t\ttracker.setDelay(delay);\n\t\t}\n\t}\n\n\tpublic void setItemTimedout() {\n\t\tdelay = MainProxy.getGlobalTick() - 1;\n\t\tif (tracker != null) {\n\t\t\ttracker.setDelay(delay);\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"(%s, %d, %s, %s, %s, %d, %s)\", item, destinationint, destinationUUID, _transportMode, jamlist, delay, tracker);\n\t}\n\n\tpublic void storeToNBT(NBTTagCompound nbtTagCompound) {\n\t\tUUID uuid = UUID.randomUUID();\n\t\tnbtTagCompound.setString(\"StoreUUID\", uuid.toString());\n\t\tthis.writeToNBT(nbtTagCompound);\n\t\tstoreMap.put(uuid, this);\n\t}\n\n\tpublic static ItemRoutingInformation restoreFromNBT(NBTTagCompound nbtTagCompound) {\n\t\tif (nbtTagCompound.hasKey(\"StoreUUID\")) {\n\t\t\tUUID uuid = UUID.fromString(nbtTagCompound.getString(\"StoreUUID\"));\n\t\t\tif (storeMap.containsKey(uuid)) {\n\t\t\t\tItemRoutingInformation result = storeMap.get(uuid);\n\t\t\t\tstoreMap.remove(uuid);\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\tItemRoutingInformation info = new ItemRoutingInformation();\n\t\tinfo.readFromNBT(nbtTagCompound);\n\t\treturn info;\n\t}\n\n\tprivate static final Map<UUID, ItemRoutingInformation> storeMap = new HashMap<>();\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/LaserData.java",
    "content": "package logisticspipes.routing;\n\nimport java.util.EnumSet;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.EnumFacing;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\npublic class LaserData {\n\n\tprivate int posX;\n\tprivate int posY;\n\tprivate int posZ;\n\tprivate boolean finalPipe = true;\n\tprivate boolean startPipe = false;\n\tprivate int length = 1;\n\n\t@Nonnull\n\tprivate EnumFacing dir;\n\t@Nonnull\n\tprivate EnumSet<PipeRoutingConnectionType> connectionType;\n\n\tpublic LaserData(int posX, int posY, int posZ, @Nonnull EnumFacing dir, @Nonnull EnumSet<PipeRoutingConnectionType> connectionType) {\n\t\tthis.posX = posX;\n\t\tthis.posY = posY;\n\t\tthis.posZ = posZ;\n\t\tthis.dir = dir;\n\t\tthis.connectionType = connectionType;\n\t}\n\n\tpublic LaserData(LPDataInput input) {\n\t\tposX = input.readInt();\n\t\tposY = input.readInt();\n\t\tposZ = input.readInt();\n\t\tdir = Objects.requireNonNull(input.readFacing());\n\t\tfinalPipe = input.readBoolean();\n\t\tstartPipe = input.readBoolean();\n\t\tlength = input.readInt();\n\t\tconnectionType = EnumSet.noneOf(PipeRoutingConnectionType.class);\n\t\tfor (PipeRoutingConnectionType type : PipeRoutingConnectionType.values()) {\n\t\t\tif (input.readBoolean()) {\n\t\t\t\tconnectionType.add(type);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void writeData(LPDataOutput output) {\n\t\toutput.writeInt(posX);\n\t\toutput.writeInt(posY);\n\t\toutput.writeInt(posZ);\n\t\toutput.writeFacing(dir);\n\t\toutput.writeBoolean(finalPipe);\n\t\toutput.writeBoolean(startPipe);\n\t\toutput.writeInt(length);\n\t\tfor (PipeRoutingConnectionType type : PipeRoutingConnectionType.values()) {\n\t\t\toutput.writeBoolean(connectionType.contains(type));\n\t\t}\n\t}\n\n\tpublic int getPosX() {\n\t\treturn this.posX;\n\t}\n\n\tpublic LaserData setPosX(int posX) {\n\t\tthis.posX = posX;\n\t\treturn this;\n\t}\n\n\tpublic int getPosY() {\n\t\treturn this.posY;\n\t}\n\n\tpublic LaserData setPosY(int posY) {\n\t\tthis.posY = posY;\n\t\treturn this;\n\t}\n\n\tpublic int getPosZ() {\n\t\treturn this.posZ;\n\t}\n\n\tpublic LaserData setPosZ(int posZ) {\n\t\tthis.posZ = posZ;\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\tpublic EnumFacing getDir() {\n\t\treturn this.dir;\n\t}\n\n\tpublic LaserData setDir(EnumFacing dir) {\n\t\tthis.dir = dir;\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\tpublic EnumSet<PipeRoutingConnectionType> getConnectionType() {\n\t\treturn this.connectionType;\n\t}\n\n\tpublic LaserData setConnectionType(@Nonnull EnumSet<PipeRoutingConnectionType> connectionType) {\n\t\tthis.connectionType = connectionType;\n\t\treturn this;\n\t}\n\n\tpublic boolean isFinalPipe() {\n\t\treturn this.finalPipe;\n\t}\n\n\tpublic LaserData setFinalPipe(boolean finalPipe) {\n\t\tthis.finalPipe = finalPipe;\n\t\treturn this;\n\t}\n\n\tpublic boolean isStartPipe() {\n\t\treturn this.startPipe;\n\t}\n\n\tpublic LaserData setStartPipe(boolean startPipe) {\n\t\tthis.startPipe = startPipe;\n\t\treturn this;\n\t}\n\n\tpublic int getLength() {\n\t\treturn this.length;\n\t}\n\n\tpublic LaserData setLength(int length) {\n\t\tthis.length = length;\n\t\treturn this;\n\t}\n\n\tpublic boolean equals(final Object o) {\n\t\tif (o == this) return true;\n\t\tif (!(o instanceof LaserData)) return false;\n\t\tfinal LaserData other = (LaserData) o;\n\t\tif (this.getPosX() != other.getPosX()) return false;\n\t\tif (this.getPosY() != other.getPosY()) return false;\n\t\tif (this.getPosZ() != other.getPosZ()) return false;\n\t\tif (!Objects.equals(this.getDir(), other.getDir())) return false;\n\t\tif (!Objects.equals(this.getConnectionType(), other.getConnectionType())) return false;\n\t\tif (this.isFinalPipe() != other.isFinalPipe()) return false;\n\t\tif (this.isStartPipe() != other.isStartPipe()) return false;\n\t\treturn this.getLength() == other.getLength();\n\t}\n\n\tpublic int hashCode() {\n\t\tfinal int PRIME = 59;\n\t\tint result = 1;\n\t\tresult = result * PRIME + this.getPosX();\n\t\tresult = result * PRIME + this.getPosY();\n\t\tresult = result * PRIME + this.getPosZ();\n\t\tresult = result * PRIME + this.getDir().hashCode();\n\t\tresult = result * PRIME + this.getConnectionType().hashCode();\n\t\tresult = result * PRIME + (this.isFinalPipe() ? 79 : 97);\n\t\tresult = result * PRIME + (this.isStartPipe() ? 79 : 97);\n\t\tresult = result * PRIME + this.getLength();\n\t\treturn result;\n\t}\n\n\tpublic String toString() {\n\t\treturn \"LaserData(posX=\" + this.getPosX() + \", posY=\" + this.getPosY() + \", posZ=\" + this.getPosZ() + \", dir=\" + this.getDir() + \", connectionType=\" + this.getConnectionType() + \", finalPipe=\" + this.isFinalPipe() + \", startPipe=\" + this.isStartPipe() + \", length=\" + this.getLength() + \")\";\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/LogisticsDictPromise.java",
    "content": "package logisticspipes.routing;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.request.IExtraPromise;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class LogisticsDictPromise extends LogisticsPromise {\n\n\t@Getter\n\tprivate DictResource resource;\n\n\tpublic LogisticsDictPromise(DictResource item, int stackSize, IProvideItems sender, IOrderInfoProvider.ResourceType type) {\n\t\tsuper(item.stack.getItem(), stackSize, sender, type);\n\t\tthis.resource = item;\n\t\tthis.resource.stack = new ItemIdentifierStack(this.resource.stack);\n\t\tthis.resource.stack.setStackSize(stackSize);\n\t}\n\n\t@Override\n\tpublic IExtraPromise split(int more) {\n\t\tnumberOfItems -= more;\n\t\tthis.resource.stack.setStackSize(numberOfItems);\n\t\treturn new LogisticsExtraDictPromise(getResource().clone(), more, sender, false);\n\t}\n\n\t@Override\n\tpublic IOrderInfoProvider fullFill(IResource requestType, IAdditionalTargetInformation info) {\n\t\tIRequestItems destination;\n\t\tif (requestType instanceof ItemResource) {\n\t\t\tdestination = ((ItemResource) requestType).getTarget();\n\t\t} else if (requestType instanceof DictResource) {\n\t\t\tdestination = ((DictResource) requestType).getTarget();\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\treturn sender.fullFill(this, destination, info);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/LogisticsExtraDictPromise.java",
    "content": "package logisticspipes.routing;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.request.IExtraPromise;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.IResource;\n\npublic class LogisticsExtraDictPromise extends LogisticsDictPromise implements IExtraPromise {\n\n\tpublic LogisticsExtraDictPromise(DictResource item, int numberOfItems, IProvideItems sender, boolean provided) {\n\t\tsuper(item, numberOfItems, sender, null);\n\t\tthis.provided = provided;\n\t}\n\n\t@Getter\n\tpublic boolean provided;\n\n\t@Override\n\tpublic LogisticsExtraDictPromise copy() {\n\t\treturn new LogisticsExtraDictPromise(getResource(), numberOfItems, sender, provided);\n\t}\n\n\t@Override\n\tpublic void registerExtras(IResource requestType) {\n\t\tif (sender instanceof ICraftItems) {\n\t\t\t((ICraftItems) sender).registerExtras(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void lowerAmount(int usedcount) {\n\t\tnumberOfItems -= usedcount;\n\t}\n\n\t@Override\n\tpublic void setAmount(int amount) {\n\t\tnumberOfItems = amount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/LogisticsExtraPromise.java",
    "content": "package logisticspipes.routing;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.routing.ICraftItems;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.request.IExtraPromise;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class LogisticsExtraPromise extends LogisticsPromise implements IExtraPromise {\n\n\tpublic LogisticsExtraPromise(ItemIdentifier item, int numberOfItems, IProvideItems sender, boolean provided) {\n\t\tsuper(item, numberOfItems, sender, null);\n\t\tthis.provided = provided;\n\t}\n\n\t@Getter\n\tpublic boolean provided;\n\n\t@Override\n\tpublic LogisticsExtraPromise copy() {\n\t\treturn new LogisticsExtraPromise(item, numberOfItems, sender, provided);\n\t}\n\n\t@Override\n\tpublic void registerExtras(IResource requestType) {\n\t\tif (sender instanceof ICraftItems) {\n\t\t\t((ICraftItems) sender).registerExtras(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void lowerAmount(int usedcount) {\n\t\tnumberOfItems -= usedcount;\n\t}\n\n\t@Override\n\tpublic void setAmount(int amount) {\n\t\tnumberOfItems = amount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/LogisticsPromise.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IProvide;\nimport logisticspipes.interfaces.routing.IProvideItems;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.request.IExtraPromise;\nimport logisticspipes.request.IPromise;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.order.IOrderInfoProvider;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic class LogisticsPromise implements IPromise {\n\n\tpublic ItemIdentifier item;\n\tpublic int numberOfItems;\n\tpublic IProvideItems sender;\n\tpublic ResourceType type;\n\n\tpublic LogisticsPromise(ItemIdentifier item, int numberOfItems, IProvideItems sender, ResourceType type) {\n\t\tthis.item = item;\n\t\tthis.numberOfItems = numberOfItems;\n\t\tthis.sender = sender;\n\t\tthis.type = type;\n\t}\n\n\t@Override\n\tpublic LogisticsPromise copy() {\n\t\treturn new LogisticsPromise(item, numberOfItems, sender, type);\n\t}\n\n\t@Override\n\tpublic boolean matches(IResource requestType) {\n\t\treturn requestType.matches(item, IResource.MatchSettings.NORMAL);\n\t}\n\n\t@Override\n\tpublic int getAmount() {\n\t\treturn numberOfItems;\n\t}\n\n\t@Override\n\tpublic IExtraPromise split(int more) {\n\t\tnumberOfItems -= more;\n\t\treturn new LogisticsExtraPromise(getItemType(), more, sender, false);\n\t}\n\n\t@Override\n\tpublic IProvide getProvider() {\n\t\treturn sender;\n\t}\n\n\t@Override\n\tpublic ItemIdentifier getItemType() {\n\t\treturn item;\n\t}\n\n\t@Override\n\tpublic ResourceType getType() {\n\t\treturn type;\n\t}\n\n\t@Override\n\tpublic IOrderInfoProvider fullFill(IResource requestType, IAdditionalTargetInformation info) {\n\t\tIRequestItems destination;\n\t\tif (requestType instanceof ItemResource) {\n\t\t\tdestination = ((ItemResource) requestType).getTarget();\n\t\t} else if (requestType instanceof DictResource) {\n\t\t\tdestination = ((DictResource) requestType).getTarget();\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t\treturn sender.fullFill(this, destination, info);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/PipeRoutingConnectionType.java",
    "content": "package logisticspipes.routing;\n\npublic enum PipeRoutingConnectionType {\n\tcanRouteTo,\n\tcanRequestFrom,\n\tcanPowerFrom,\n\tcanPowerSubSystemFrom;\n\n\tpublic static PipeRoutingConnectionType[] values = new PipeRoutingConnectionType[] { canRouteTo, canRequestFrom, canPowerFrom, canPowerSubSystemFrom };\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/RouterCost.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nclass RouterCost {\n\n\tpublic final IRouter router;\n\tpublic final int cost;\n\n\tpublic RouterCost(IRouter router, int cost) {\n\t\tthis.router = router;\n\t\tthis.cost = cost;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/RouterManager.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.UUID;\nimport java.util.WeakHashMap;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.world.World;\n\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.interfaces.ISecurityStationManager;\nimport logisticspipes.interfaces.routing.IChannelConnectionManager;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.block.SecurityStationAuthorizedList;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.channels.ChannelConnection;\n\npublic class RouterManager implements IChannelConnectionManager, ISecurityStationManager {\n\n\tprivate final ArrayList<IRouter> _routersClient = new ArrayList<>();\n\tprivate final ArrayList<ServerRouter> _routersServer = new ArrayList<>();\n\tprivate final Map<UUID, Integer> _uuidMap = new HashMap<>();\n\n\tprivate final WeakHashMap<LogisticsSecurityTileEntity, Void> _security = new WeakHashMap<>();\n\tprivate List<String> _authorized = new LinkedList<>();\n\n\tprivate final ArrayList<ChannelConnection> channelConnectedPipes = new ArrayList<>();\n\n\t@Nullable\n\tpublic IRouter getRouter(int id) {\n\t\t//TODO: isClient without a world is expensive\n\t\tif (id <= 0 || MainProxy.isClient()) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn _routersServer.get(id);\n\t\t}\n\t}\n\n\t@Nullable\n\tpublic ServerRouter getServerRouter(int id) {\n\t\tif (id <= 0) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn _routersServer.get(id);\n\t\t}\n\t}\n\n\tpublic int getIDforUUID(UUID id) {\n\t\tif (id == null) {\n\t\t\treturn -1;\n\t\t}\n\t\tInteger iId = _uuidMap.get(id);\n\t\tif (iId == null) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn iId;\n\t}\n\n\tpublic void removeRouter(int id) {\n\t\t//TODO: isClient without a world is expensive\n\t\tif (!MainProxy.isClient()) {\n\t\t\t_routersServer.set(id, null);\n\t\t}\n\t}\n\n\t@Nonnull\n\tpublic IRouter getOrCreateRouter(UUID UUid, World world, int xCoord, int yCoord, int zCoord) {\n\t\tIRouter r;\n\t\tint id = getIDforUUID(UUid);\n\t\tif (id > 0) {\n\t\t\tgetRouter(id);\n\t\t}\n\t\tif (MainProxy.isClient(world)) {\n\t\t\tsynchronized (_routersClient) {\n\t\t\t\tfor (IRouter r2 : _routersClient) {\n\t\t\t\t\tif (r2.isAt(world.provider.getDimension(), xCoord, yCoord, zCoord)) {\n\t\t\t\t\t\treturn r2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tr = new ClientRouter(UUid, world.provider.getDimension(), xCoord, yCoord, zCoord);\n\t\t\t\t_routersClient.add(r);\n\t\t\t}\n\t\t} else {\n\t\t\tsynchronized (_routersServer) {\n\t\t\t\tfor (IRouter r2 : _routersServer) {\n\t\t\t\t\tif (r2 != null && r2.isAt(world.provider.getDimension(), xCoord, yCoord, zCoord)) {\n\t\t\t\t\t\treturn r2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfinal ServerRouter serverRouter = new ServerRouter(UUid, world.provider.getDimension(), xCoord, yCoord, zCoord);\n\n\t\t\t\tint rId = serverRouter.getSimpleID();\n\t\t\t\tif (_routersServer.size() <= rId) {\n\t\t\t\t\t_routersServer.ensureCapacity(rId + 1);\n\t\t\t\t\twhile (_routersServer.size() <= rId) {\n\t\t\t\t\t\t_routersServer.add(null);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t_routersServer.set(rId, serverRouter);\n\t\t\t\t_uuidMap.put(serverRouter.getId(), serverRouter.getSimpleID());\n\t\t\t\tr = serverRouter;\n\t\t\t}\n\t\t}\n\t\treturn r;\n\t}\n\n\t/**\n\t * This assumes you know what you are doing. expect exceptions to be thrown\n\t * if you pass the wrong side.\n\t *\n\t * @param id\n\t * @param side\n\t *            false for server, true for client.\n\t * @return is this a router for the side.\n\t */\n\tpublic boolean isRouterUnsafe(int id, boolean side) {\n\t\tif (side) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn _routersServer.get(id) != null;\n\t\t}\n\t}\n\n\tpublic List<IRouter> getRouters() {\n\t\tif (MainProxy.isClient()) {\n\t\t\treturn Collections.unmodifiableList(_routersClient);\n\t\t} else {\n\t\t\treturn Collections.unmodifiableList(_routersServer);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasChannelConnection(IRouter router) {\n\t\treturn channelConnectedPipes.stream()\n\t\t\t\t.filter(con -> con.routers.size() > 1)\n\t\t\t\t.anyMatch(con -> con.routers.contains(router.getSimpleID()));\n\t}\n\n\t@Override\n\tpublic boolean addChannelConnection(UUID ident, IRouter router) {\n\t\tif (MainProxy.isClient()) {\n\t\t\treturn false;\n\t\t}\n\t\tint routerSimpleID = router.getSimpleID();\n\t\tchannelConnectedPipes.forEach(con -> con.routers.remove(routerSimpleID));\n\t\tOptional<ChannelConnection> channel = channelConnectedPipes.stream().filter(con -> con.identifier.equals(ident)).findFirst();\n\t\tif (channel.isPresent()) {\n\t\t\tchannel.get().routers.add(routerSimpleID);\n\t\t} else {\n\t\t\tChannelConnection newChannel = new ChannelConnection();\n\t\t\tchannelConnectedPipes.add(newChannel);\n\t\t\tnewChannel.identifier = ident;\n\t\t\tnewChannel.routers.add(routerSimpleID);\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic List<CoreRoutedPipe> getConnectedPipes(IRouter router) {\n\t\tOptional<ChannelConnection> channel = channelConnectedPipes.stream()\n\t\t\t\t.filter(con -> con.routers.contains(router.getSimpleID()))\n\t\t\t\t.findFirst();\n\t\treturn channel.\n\t\t\t\tmap(channelConnection ->\n\t\t\t\t\t\tchannelConnection.routers.stream()\n\t\t\t\t\t\t\t\t.filter(r -> r != router.getSimpleID())\n\t\t\t\t\t\t\t\t.map(this::getRouter).filter(Objects::nonNull)\n\t\t\t\t\t\t\t\t.map(IRouter::getPipe).filter(Objects::nonNull)\n\t\t\t\t\t\t\t\t.collect(Collectors.toList())\n\t\t\t\t)\n\t\t\t\t.orElse(Collections.emptyList());\n\t}\n\n\t@Override\n\tpublic void removeChannelConnection(IRouter router) {\n\t\tif (MainProxy.isClient()) {\n\t\t\treturn;\n\t\t}\n\t\tOptional<ChannelConnection> channel = channelConnectedPipes.stream()\n\t\t\t\t.filter(con -> con.routers.contains(router.getSimpleID()))\n\t\t\t\t.findFirst();\n\t\tchannel.ifPresent(chan -> chan.routers.remove(router.getSimpleID()));\n\t\tif (channel.filter(chan -> chan.routers.isEmpty()).isPresent()) {\n\t\t\tchannelConnectedPipes.remove(channel.get());\n\t\t}\n\t}\n\n\tpublic void serverStopClean() {\n\t\tchannelConnectedPipes.clear();\n\t\t_routersServer.clear();\n\t\t_uuidMap.clear();\n\t\t_security.clear();\n\t}\n\n\tpublic void clearClientRouters() {\n\t\tsynchronized (_routersClient) {\n\t\t\t_routersClient.clear();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void add(LogisticsSecurityTileEntity tile) {\n\t\t_security.put(tile, null);\n\t\tauthorizeUUID(tile.getSecId());\n\t}\n\n\t@Override\n\tpublic LogisticsSecurityTileEntity getStation(UUID id) {\n\t\tif (id == null) {\n\t\t\treturn null;\n\t\t}\n\t\tfor (LogisticsSecurityTileEntity tile : _security.keySet()) {\n\t\t\tif (id.equals(tile.getSecId())) {\n\t\t\t\treturn tile;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void remove(LogisticsSecurityTileEntity tile) {\n\t\t_security.remove(tile);\n\t\tdeauthorizeUUID(tile.getSecId());\n\t}\n\n\tpublic void dimensionUnloaded(int dim) {\n\t\tsynchronized (_routersServer) {\n\t\t\t_routersServer.stream().filter(r -> r != null && r.isInDim(dim)).forEach(r -> {\n\t\t\t\tr.clearPipeCache();\n\t\t\t\tr.clearInterests();\n\t\t\t});\n\t\t}\n\t}\n\n\t@Override\n\tpublic void deauthorizeUUID(UUID id) {\n\t\t_authorized.remove(id.toString());\n\t\tsendClientAuthorizationList();\n\t}\n\n\t@Override\n\tpublic void authorizeUUID(UUID id) {\n\t\tif (!_authorized.contains(id.toString())) {\n\t\t\t_authorized.add(id.toString());\n\t\t}\n\t\tsendClientAuthorizationList();\n\t}\n\n\t@Override\n\tpublic boolean isAuthorized(UUID id) {\n\t\tif (_authorized.isEmpty() || id == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _authorized.contains(id.toString());\n\t}\n\n\t@Override\n\tpublic boolean isAuthorized(String id) {\n\t\tif (_authorized.isEmpty() || id == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _authorized.contains(id);\n\t}\n\n\t@Override\n\tpublic void setClientAuthorizationList(List<String> list) {\n\t\t_authorized = list;\n\t}\n\n\t@Override\n\tpublic void sendClientAuthorizationList() {\n\t\tMainProxy.sendToAllPlayers(PacketHandler.getPacket(SecurityStationAuthorizedList.class).setStringList(_authorized));\n\t}\n\n\t@Override\n\tpublic void sendClientAuthorizationList(EntityPlayer player) {\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(SecurityStationAuthorizedList.class).setStringList(_authorized), player);\n\t}\n\n\tpublic void printAllRouters() {\n\t\t_routersServer.stream().filter(router -> router != null).forEach(router -> System.out.println(router.toString()));\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/ServerRouter.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing;\n\nimport java.lang.ref.WeakReference;\nimport java.util.*;\nimport java.util.Map.Entry;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\nimport java.util.function.BiConsumer;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.DimensionManager;\n\nimport it.unimi.dsi.fastutil.objects.ObjectSets;\nimport lombok.Getter;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.asm.te.ILPTEInformation;\nimport logisticspipes.asm.te.ITileEntityChangeListener;\nimport logisticspipes.asm.te.LPTileEntityObject;\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.IRoutingDebugAdapter;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipes.PipeItemsFirewall;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.request.resources.FluidResource;\nimport logisticspipes.request.resources.IResource;\nimport logisticspipes.request.resources.ItemResource;\nimport logisticspipes.routing.pathfinder.PathFinder;\nimport logisticspipes.ticks.LPTickHandler;\nimport logisticspipes.ticks.RoutingTableUpdateThread;\nimport logisticspipes.utils.CacheHolder;\nimport logisticspipes.utils.OneList;\nimport logisticspipes.utils.StackTraceUtil;\nimport logisticspipes.utils.StackTraceUtil.Info;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Quartet;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class ServerRouter implements IRouter, Comparable<ServerRouter> {\n\n\tpublic static final int REFRESH_TIME = 20;\n\n\tprotected static final ReentrantReadWriteLock SharedLSADatabaseLock = new ReentrantReadWriteLock();\n\tprotected static final Lock SharedLSADatabasereadLock = ServerRouter.SharedLSADatabaseLock.readLock();\n\tprotected static final Lock SharedLSADatabasewriteLock = ServerRouter.SharedLSADatabaseLock.writeLock();\n\tprotected static int[] _lastLSAVersion = new int[0];\n\tprotected static LSA[] SharedLSADatabase = new LSA[0];\n\n\t// things with specific interests -- providers (including crafters)\n\t@Nonnull\n\tprivate static final ConcurrentHashMap<ItemIdentifier, TreeSet<ServerRouter>> globalSpecificInterests = new ConcurrentHashMap<>();\n\n\t// things potentially interested in every item (chassi with generic sinks)\n\t@Nonnull\n\tprivate static TreeSet<ServerRouter> genericInterests = new TreeSet<>();\n\tprivate static final Lock genericInterestsWLock = new ReentrantLock();\n\n\t// things this pipe is interested in (either providing or sinking)\n\t@Nonnull\n\tprivate TreeSet<ItemIdentifier> interests = new TreeSet<>();\n\tprivate final Lock interestsRWLock = new ReentrantLock();\n\n\tstatic int iterated = 0;// used pseudp-random to spread items over the tick range\n\tprivate static int maxLSAUpdateIndex = 0;\n\tprivate static int firstFreeId = 1;\n\tprivate static final BitSet simpleIdUsedSet = new BitSet();\n\n\tpublic final UUID id;\n\tprotected final LSA _myLsa;\n\tprotected final ReentrantReadWriteLock routingTableUpdateLock = new ReentrantReadWriteLock();\n\tprotected final Lock routingTableUpdateWriteLock = routingTableUpdateLock.writeLock();\n\tprotected final int simpleID;\n\t@Getter\n\tprivate final int _xCoord;\n\t@Getter\n\tprivate final int _yCoord;\n\t@Getter\n\tprivate final int _zCoord;\n\t// these are maps, not hashMaps because they are unmodifiable Collections to avoid concurrentModification exceptions.\n\tpublic Map<CoreRoutedPipe, ExitRoute> _adjacent = new HashMap<>();\n\tpublic Map<ServerRouter, ExitRoute> _adjacentRouter = new HashMap<>();\n\tpublic Map<ServerRouter, ExitRoute> _adjacentRouter_Old = new HashMap<>();\n\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> _powerAdjacent = new ArrayList<>();\n\tpublic List<Pair<ISubSystemPowerProvider, List<IFilter>>> _subSystemPowerAdjacent = new ArrayList<>();\n\tpublic boolean[] sideDisconnected = new boolean[6];\n\t/**\n\t * Map of router -> orientation for all known destinations\n\t **/\n\tpublic List<List<ExitRoute>> _routeTable = Collections.unmodifiableList(new ArrayList<>());\n\tpublic List<ExitRoute> _routeCosts = Collections.unmodifiableList(new ArrayList<>());\n\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> _LPPowerTable = Collections.unmodifiableList(new ArrayList<>());\n\tpublic List<Pair<ISubSystemPowerProvider, List<IFilter>>> _SubSystemPowerTable = Collections.unmodifiableList(new ArrayList<>());\n\tprotected int _LSAVersion = 0;\n\tint ticksUntillNextInventoryCheck = 0;\n\tprivate EnumSet<EnumFacing> _routedExits = EnumSet.noneOf(EnumFacing.class);\n\tprivate EnumMap<EnumFacing, Integer> _subPowerExits = new EnumMap<>(EnumFacing.class);\n\tprivate final int _dimension;\n\tprivate WeakReference<CoreRoutedPipe> _myPipeCache = null;\n\tprivate final LinkedList<Pair<Integer, IRouterQueuedTask>> queue = new LinkedList<>();\n\tint connectionNeedsChecking = 0;\n\tprivate final List<DoubleCoordinates> causedBy = new LinkedList<>();\n\tprivate boolean isDestroyed = false;\n\tprivate final ITileEntityChangeListener localChangeListener = new ITileEntityChangeListener() {\n\n\t\t@Override\n\t\tpublic void pipeRemoved(DoubleCoordinates pos) {\n\t\t\tif (connectionNeedsChecking == 0) {\n\t\t\t\tconnectionNeedsChecking = 1;\n\t\t\t}\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tcausedBy.add(pos);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void pipeAdded(DoubleCoordinates pos, EnumFacing side) {\n\t\t\tif (connectionNeedsChecking == 0) {\n\t\t\t\tconnectionNeedsChecking = 1;\n\t\t\t}\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tcausedBy.add(pos);\n\t\t\t}\n\t\t}\n\n\t};\n\tprivate Set<List<ITileEntityChangeListener>> listenedPipes = new HashSet<>();\n\tprivate Set<LPTileEntityObject> oldTouchedPipes = new HashSet<>();\n\n\tpublic ServerRouter(UUID globalID, int dimension, int xCoord, int yCoord, int zCoord) {\n\t\tif (globalID != null) {\n\t\t\tid = globalID;\n\t\t} else {\n\t\t\tid = UUID.randomUUID();\n\t\t}\n\t\t_dimension = dimension;\n\t\t_xCoord = xCoord;\n\t\t_yCoord = yCoord;\n\t\t_zCoord = zCoord;\n\t\tclearPipeCache();\n\t\t_myLsa = new LSA();\n\t\t_myLsa.neighboursWithMetric = new HashMap<>();\n\t\t_myLsa.power = new ArrayList<>();\n\t\tServerRouter.SharedLSADatabasewriteLock.lock(); // any time after we claim the SimpleID, the database could be accessed at that index\n\t\tsimpleID = ServerRouter.claimSimpleID();\n\t\tif (ServerRouter.SharedLSADatabase.length <= simpleID) {\n\t\t\tint newlength = ((int) (simpleID * 1.5)) + 1;\n\t\t\tLSA[] new_SharedLSADatabase = new LSA[newlength];\n\t\t\tSystem.arraycopy(ServerRouter.SharedLSADatabase, 0, new_SharedLSADatabase, 0, ServerRouter.SharedLSADatabase.length);\n\t\t\tServerRouter.SharedLSADatabase = new_SharedLSADatabase;\n\t\t\tint[] new_lastLSAVersion = new int[newlength];\n\t\t\tSystem.arraycopy(ServerRouter._lastLSAVersion, 0, new_lastLSAVersion, 0, ServerRouter._lastLSAVersion.length);\n\t\t\tServerRouter._lastLSAVersion = new_lastLSAVersion;\n\t\t}\n\t\tServerRouter._lastLSAVersion[simpleID] = 0;\n\t\tServerRouter.SharedLSADatabase[simpleID] = _myLsa; // make non-structural change (threadsafe)\n\t\tServerRouter.SharedLSADatabasewriteLock.unlock();\n\t}\n\n\t// called on server shutdown only\n\tpublic static void cleanup() {\n\t\tServerRouter.globalSpecificInterests.clear();\n\t\tServerRouter.genericInterests.clear();\n\t\tServerRouter.SharedLSADatabasewriteLock.lock();\n\t\tServerRouter.SharedLSADatabase = new LSA[0];\n\t\tServerRouter._lastLSAVersion = new int[0];\n\t\tServerRouter.SharedLSADatabasewriteLock.unlock();\n\t\tServerRouter.simpleIdUsedSet.clear();\n\t\tServerRouter.firstFreeId = 1;\n\t}\n\n\tprivate static int claimSimpleID() {\n\t\tint idx = ServerRouter.simpleIdUsedSet.nextClearBit(ServerRouter.firstFreeId);\n\t\tServerRouter.firstFreeId = idx + 1;\n\t\tServerRouter.simpleIdUsedSet.set(idx);\n\t\treturn idx;\n\t}\n\n\tprivate static void releaseSimpleID(int idx) {\n\t\tServerRouter.simpleIdUsedSet.clear(idx);\n\t\tif (idx < ServerRouter.firstFreeId) {\n\t\t\tServerRouter.firstFreeId = idx;\n\t\t}\n\t}\n\n\tpublic static int getBiggestSimpleID() {\n\t\treturn ServerRouter.simpleIdUsedSet.size();\n\t}\n\n\tprivate static void setBitsForItemInterests(@Nonnull final BitSet bitset, @Nonnull final ItemIdentifier itemid) {\n\t\tTreeSet<ServerRouter> specifics = ServerRouter.globalSpecificInterests.get(itemid);\n\t\tif (specifics != null) {\n\t\t\tfor (IRouter r : specifics) {\n\t\t\t\tbitset.set(r.getSimpleID());\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static BitSet getRoutersInterestedIn(ItemIdentifier item) {\n\t\tfinal BitSet s = new BitSet(ServerRouter.getBiggestSimpleID() + 1);\n\t\tfor (IRouter r : ServerRouter.genericInterests) {\n\t\t\ts.set(r.getSimpleID());\n\t\t}\n\t\tif (item != null) {\n\t\t\tStream.of(item, item.getUndamaged(), item.getIgnoringNBT(), item.getUndamaged().getIgnoringNBT(), item.getIgnoringData(), item.getIgnoringData().getIgnoringNBT())\n\t\t\t\t\t.forEach(itemid -> setBitsForItemInterests(s, itemid));\n\t\t}\n\t\treturn s;\n\t}\n\n\tpublic static BitSet getRoutersInterestedIn(IResource item) {\n\t\tif (item instanceof ItemResource) {\n\t\t\treturn ServerRouter.getRoutersInterestedIn(((ItemResource) item).getItem());\n\t\t} else if (item instanceof FluidResource) {\n\t\t\treturn ServerRouter.getRoutersInterestedIn(((FluidResource) item).getFluid().getItemIdentifier());\n\t\t} else if (item instanceof DictResource) {\n\t\t\tDictResource dict = (DictResource) item;\n\t\t\tBitSet s = new BitSet(ServerRouter.getBiggestSimpleID() + 1);\n\t\t\tfor (IRouter r : ServerRouter.genericInterests) {\n\t\t\t\ts.set(r.getSimpleID());\n\t\t\t}\n\t\t\tServerRouter.globalSpecificInterests.entrySet().stream()\n\t\t\t\t\t.filter(entry -> dict.matches(entry.getKey(), IResource.MatchSettings.NORMAL))\n\t\t\t\t\t.flatMap(entry -> entry.getValue().stream())\n\t\t\t\t\t.forEach(router -> s.set(router.simpleID));\n\t\t\treturn s;\n\t\t}\n\t\treturn new BitSet(ServerRouter.getBiggestSimpleID() + 1);\n\t}\n\n\tpublic static void forEachGlobalSpecificInterest(BiConsumer<ItemIdentifier, NavigableSet<ServerRouter>> consumer) {\n\t\tServerRouter.globalSpecificInterests.forEach((itemIdentifier, serverRouters) -> consumer.accept(itemIdentifier, Collections.unmodifiableNavigableSet(serverRouters)));\n\t}\n\n\tpublic static NavigableSet<ServerRouter> getInterestedInGeneral() {\n\t\treturn Collections.unmodifiableNavigableSet(ServerRouter.genericInterests);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn simpleID; // guaranteed to be unique, and uniform distribution over a range.\n\t}\n\n\t@Override\n\tpublic void clearPipeCache() {\n\t\t_myPipeCache = null;\n\t}\n\n\t@Override\n\tpublic int getSimpleID() {\n\t\treturn simpleID;\n\t}\n\n\t@Override\n\tpublic boolean isInDim(int dimension) {\n\t\treturn _dimension == dimension;\n\t}\n\n\t@Override\n\tpublic boolean isAt(int dimension, int xCoord, int yCoord, int zCoord) {\n\t\treturn _dimension == dimension && _xCoord == xCoord && _yCoord == yCoord && _zCoord == zCoord;\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getLPPosition() {\n\t\treturn new DoubleCoordinates(_xCoord, _yCoord, _zCoord);\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getPipe() {\n\t\tCoreRoutedPipe crp = getCachedPipe();\n\t\tif (crp != null) {\n\t\t\treturn crp;\n\t\t}\n\t\tWorld world = DimensionManager.getWorld(_dimension);\n\t\tif (world == null) {\n\t\t\treturn null;\n\t\t}\n\t\tTileEntity tile = world.getTileEntity(new BlockPos(_xCoord, _yCoord, _zCoord));\n\n\t\tif (!(tile instanceof LogisticsTileGenericPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\tLogisticsTileGenericPipe pipe = (LogisticsTileGenericPipe) tile;\n\t\tif (!(pipe.pipe instanceof CoreRoutedPipe)) {\n\t\t\treturn null;\n\t\t}\n\t\t_myPipeCache = new WeakReference<>((CoreRoutedPipe) pipe.pipe);\n\n\t\treturn (CoreRoutedPipe) pipe.pipe;\n\t}\n\n\t@Override\n\tpublic CoreRoutedPipe getCachedPipe() {\n\t\tif (_myPipeCache != null) {\n\t\t\treturn _myPipeCache.get();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean isCacheInvalid() {\n\t\treturn getPipe() == null;\n\t}\n\n\tprivate void lazyUpdateRoutingTable() {\n\t\tif (_LSAVersion > ServerRouter._lastLSAVersion[simpleID]) {\n\t\t\tif (Configs.MULTI_THREAD_NUMBER > 0) {\n\t\t\t\tRoutingTableUpdateThread.add(new UpdateRouterRunnable(this));\n\t\t\t} else {\n\t\t\t\tCreateRouteTable(_LSAVersion);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void ensureLatestRoutingTable() {\n\t\tif (connectionNeedsChecking != 0) {\n\t\t\tboolean blockNeedsUpdate = checkAdjacentUpdate();\n\t\t\tif (blockNeedsUpdate) {\n\t\t\t\tupdateLsa();\n\t\t\t}\n\t\t}\n\t\tif (_LSAVersion > ServerRouter._lastLSAVersion[simpleID]) {\n\t\t\tCreateRouteTable(_LSAVersion);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<List<ExitRoute>> getRouteTable() {\n\t\tensureLatestRoutingTable();\n\t\treturn _routeTable;\n\t}\n\n\t@Override\n\tpublic List<ExitRoute> getIRoutersByCost() {\n\t\tensureLatestRoutingTable();\n\t\treturn _routeCosts;\n\t}\n\n\t@Override\n\tpublic UUID getId() {\n\t\treturn id;\n\t}\n\n\t/**\n\t * Rechecks the piped connection to all adjacent routers as well as discover\n\t * new ones.\n\t */\n\tprivate boolean recheckAdjacent() {\n\t\tconnectionNeedsChecking = 0;\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tcausedBy.clear();\n\t\t}\n\t\tif (getPipe() != null) {\n\t\t\t/*\n\t\t\tif (getPipe().getDebug() != null && getPipe().getDebug().debugThisPipe) {\n\t\t\t\tInfo info = StackTraceUtil.addTraceInformation(\"(\" + getPipe().getX() + \", \" + getPipe().getY() + \", \" + getPipe().getZ() + \")\");\n\t\t\t\tStackTraceUtil.printTrace();\n\t\t\t\tinfo.end();\n\t\t\t}\n\t\t\t*/\n\t\t\tgetPipe().spawnParticle(Particles.LightRedParticle, 5);\n\t\t}\n\n\t\tLPTickHandler.adjChecksDone++;\n\t\tboolean adjacentChanged = false;\n\t\tCoreRoutedPipe thisPipe = getPipe();\n\t\tif (thisPipe == null) {\n\t\t\treturn false;\n\t\t}\n\t\tHashMap<CoreRoutedPipe, ExitRoute> adjacent;\n\t\tList<Pair<ILogisticsPowerProvider, List<IFilter>>> power;\n\t\tList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower;\n\t\tPathFinder finder = new PathFinder(thisPipe.container, Configs.LOGISTICS_DETECTION_COUNT, Configs.LOGISTICS_DETECTION_LENGTH, localChangeListener);\n\t\tpower = finder.powerNodes;\n\t\tsubSystemPower = finder.subPowerProvider;\n\t\tadjacent = finder.result;\n\n\t\tMap<EnumFacing, List<CoreRoutedPipe>> pipeDirections = new HashMap<>();\n\n\t\tfor (Entry<CoreRoutedPipe, ExitRoute> entry : adjacent.entrySet()) {\n\t\t\tList<CoreRoutedPipe> list = pipeDirections.computeIfAbsent(entry.getValue().exitOrientation, k -> new ArrayList<>());\n\t\t\tlist.add(entry.getKey());\n\t\t}\n\n\t\tpipeDirections.entrySet().stream()\n\t\t\t\t.filter(entry -> entry.getValue().size() > Configs.MAX_UNROUTED_CONNECTIONS)\n\t\t\t\t.forEach(entry -> entry.getValue().forEach(adjacent::remove));\n\n\t\tlistenedPipes.stream().filter(list -> !finder.listenedPipes.contains(list)).forEach(list -> list.remove(localChangeListener));\n\t\tlistenedPipes = finder.listenedPipes;\n\n\t\tfor (CoreRoutedPipe pipe : adjacent.keySet()) {\n\t\t\tif (pipe.stillNeedReplace()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tboolean[] oldSideDisconnected = sideDisconnected;\n\t\tsideDisconnected = new boolean[6];\n\t\tcheckSecurity(adjacent);\n\n\t\tboolean changed = false;\n\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tchanged |= sideDisconnected[i] != oldSideDisconnected[i];\n\t\t}\n\t\tif (changed) {\n\t\t\tCoreRoutedPipe pipe = getPipe();\n\t\t\tif (pipe != null) {\n\t\t\t\tpipe.getWorld().markAndNotifyBlock(pipe.getPos(), pipe.getWorld().getChunk(pipe.getPos()), pipe.getWorld().getBlockState(pipe.getPos()), pipe.getWorld().getBlockState(pipe.getPos()), 3);\n\t\t\t\tpipe.refreshConnectionAndRender(false);\n\t\t\t}\n\t\t\tadjacentChanged = true;\n\t\t}\n\n\t\tif (_adjacent.size() != adjacent.size()) {\n\t\t\tadjacentChanged = true;\n\t\t}\n\n\t\tfor (CoreRoutedPipe pipe : _adjacent.keySet()) {\n\t\t\tif (!adjacent.containsKey(pipe)) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (_powerAdjacent != null) {\n\t\t\tif (power == null) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t} else {\n\t\t\t\tfor (Pair<ILogisticsPowerProvider, List<IFilter>> provider : _powerAdjacent) {\n\t\t\t\t\tif (!power.contains(provider)) {\n\t\t\t\t\t\tadjacentChanged = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (power != null) {\n\t\t\tif (_powerAdjacent == null) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t} else {\n\t\t\t\tfor (Pair<ILogisticsPowerProvider, List<IFilter>> provider : power) {\n\t\t\t\t\tif (!_powerAdjacent.contains(provider)) {\n\t\t\t\t\t\tadjacentChanged = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_subSystemPowerAdjacent != null) {\n\t\t\tif (subSystemPower == null) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t} else {\n\t\t\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> provider : _subSystemPowerAdjacent) {\n\t\t\t\t\tif (!subSystemPower.contains(provider)) {\n\t\t\t\t\t\tadjacentChanged = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subSystemPower != null) {\n\t\t\tif (_subSystemPowerAdjacent == null) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t} else {\n\t\t\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> provider : subSystemPower) {\n\t\t\t\t\tif (!_subSystemPowerAdjacent.contains(provider)) {\n\t\t\t\t\t\tadjacentChanged = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (Entry<CoreRoutedPipe, ExitRoute> pipe : adjacent.entrySet()) {\n\t\t\tExitRoute oldExit = _adjacent.get(pipe.getKey());\n\t\t\tif (oldExit == null) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tExitRoute newExit = pipe.getValue();\n\n\t\t\tif (!newExit.equals(oldExit)) {\n\t\t\t\tadjacentChanged = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!oldTouchedPipes.equals(finder.touchedPipes)) {\n\t\t\tCacheHolder.clearCache(oldTouchedPipes);\n\t\t\tCacheHolder.clearCache(finder.touchedPipes);\n\t\t\toldTouchedPipes = finder.touchedPipes;\n\t\t\tBitSet visited = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\t\tvisited.set(getSimpleID());\n\t\t\tact(visited, new floodClearCache());\n\t\t}\n\n\t\tif (adjacentChanged) {\n\t\t\tHashMap<ServerRouter, ExitRoute> adjacentRouter = new HashMap<>();\n\t\t\tEnumSet<EnumFacing> routedexits = EnumSet.noneOf(EnumFacing.class);\n\t\t\tEnumMap<EnumFacing, Integer> subpowerexits = new EnumMap<>(EnumFacing.class);\n\t\t\tfor (Entry<CoreRoutedPipe, ExitRoute> pipe : adjacent.entrySet()) {\n\t\t\t\tadjacentRouter.put((ServerRouter) pipe.getKey().getRouter(), pipe.getValue());\n\t\t\t\tif ((pipe.getValue().connectionDetails.contains(PipeRoutingConnectionType.canRouteTo) || pipe.getValue().connectionDetails.contains(PipeRoutingConnectionType.canRequestFrom) && !routedexits.contains(pipe.getValue().exitOrientation))) {\n\t\t\t\t\troutedexits.add(pipe.getValue().exitOrientation);\n\t\t\t\t}\n\t\t\t\tif (!subpowerexits.containsKey(pipe.getValue().exitOrientation) && pipe.getValue().connectionDetails.contains(PipeRoutingConnectionType.canPowerSubSystemFrom)) {\n\t\t\t\t\tsubpowerexits.put(pipe.getValue().exitOrientation, PathFinder.messureDistanceToNextRoutedPipe(getLPPosition(), pipe.getValue().exitOrientation, pipe.getKey().getWorld()));\n\t\t\t\t}\n\t\t\t}\n\t\t\t_adjacent = Collections.unmodifiableMap(adjacent);\n\t\t\t_adjacentRouter_Old = _adjacentRouter;\n\t\t\t_adjacentRouter = Collections.unmodifiableMap(adjacentRouter);\n\t\t\tif (power != null) {\n\t\t\t\t_powerAdjacent = Collections.unmodifiableList(power);\n\t\t\t} else {\n\t\t\t\t_powerAdjacent = null;\n\t\t\t}\n\t\t\tif (subSystemPower != null) {\n\t\t\t\t_subSystemPowerAdjacent = Collections.unmodifiableList(subSystemPower);\n\t\t\t} else {\n\t\t\t\t_subSystemPowerAdjacent = null;\n\t\t\t}\n\t\t\t_routedExits = routedexits;\n\t\t\t_subPowerExits = subpowerexits;\n\t\t\tSendNewLSA();\n\t\t}\n\t\treturn adjacentChanged;\n\t}\n\n\tprivate void checkSecurity(HashMap<CoreRoutedPipe, ExitRoute> adjacent) {\n\t\tCoreRoutedPipe pipe = getPipe();\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tUUID id = pipe.getSecurityID();\n\t\tif (id != null) {\n\t\t\tfor (Entry<CoreRoutedPipe, ExitRoute> entry : adjacent.entrySet()) {\n\t\t\t\tif (!entry.getValue().connectionDetails.contains(PipeRoutingConnectionType.canRouteTo) && !entry.getValue().connectionDetails.contains(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tUUID thatId = entry.getKey().getSecurityID();\n\t\t\t\tif (!(pipe instanceof PipeItemsFirewall)) {\n\t\t\t\t\tif (thatId == null) {\n\t\t\t\t\t\tentry.getKey().insetSecurityID(id);\n\t\t\t\t\t} else if (!id.equals(thatId)) {\n\t\t\t\t\t\tsideDisconnected[entry.getValue().exitOrientation.ordinal()] = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!(entry.getKey() instanceof PipeItemsFirewall)) {\n\t\t\t\t\t\tif (thatId != null && !id.equals(thatId)) {\n\t\t\t\t\t\t\tsideDisconnected[entry.getValue().exitOrientation.ordinal()] = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tList<CoreRoutedPipe> toRemove = adjacent.entrySet().stream()\n\t\t\t\t\t.filter(entry -> sideDisconnected[entry.getValue().exitOrientation.ordinal()])\n\t\t\t\t\t.map(Entry::getKey)\n\t\t\t\t\t.collect(Collectors.toList());\n\t\t\ttoRemove.forEach(adjacent::remove);\n\t\t}\n\t}\n\n\tprivate void SendNewLSA() {\n\t\tHashMap<IRouter, Quartet<Double, EnumSet<PipeRoutingConnectionType>, List<IFilter>, Integer>> neighboursWithMetric = new HashMap<>();\n\t\tfor (Entry<ServerRouter, ExitRoute> adjacent : _adjacentRouter.entrySet()) {\n\t\t\tneighboursWithMetric.put(adjacent.getKey(), new Quartet<>(adjacent\n\t\t\t\t\t.getValue().distanceToDestination, adjacent.getValue().connectionDetails, adjacent\n\t\t\t\t\t.getValue().filters, adjacent.getValue().blockDistance));\n\t\t}\n\t\tArrayList<Pair<ILogisticsPowerProvider, List<IFilter>>> power = null;\n\t\tif (_powerAdjacent != null) {\n\t\t\tpower = new ArrayList<>(_powerAdjacent);\n\t\t}\n\t\tArrayList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower = null;\n\t\tif (_subSystemPowerAdjacent != null) {\n\t\t\tsubSystemPower = new ArrayList<>(_subSystemPowerAdjacent);\n\t\t}\n\t\tif (Configs.MULTI_THREAD_NUMBER > 0) {\n\t\t\tRoutingTableUpdateThread.add(new LSARouterRunnable(neighboursWithMetric, power, subSystemPower));\n\t\t} else {\n\t\t\tlockAndUpdateLSA(neighboursWithMetric, power, subSystemPower);\n\t\t}\n\t}\n\n\tprivate void lockAndUpdateLSA(HashMap<IRouter, Quartet<Double, EnumSet<PipeRoutingConnectionType>, List<IFilter>, Integer>> neighboursWithMetric, ArrayList<Pair<ILogisticsPowerProvider, List<IFilter>>> power, ArrayList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower) {\n\t\tServerRouter.SharedLSADatabasewriteLock.lock();\n\t\t_myLsa.neighboursWithMetric = neighboursWithMetric;\n\t\t_myLsa.power = power;\n\t\t_myLsa.subSystemPower = subSystemPower;\n\t\tServerRouter.SharedLSADatabasewriteLock.unlock();\n\t}\n\n\tpublic void CreateRouteTable(int version_to_update_to) {\n\t\tCreateRouteTable(version_to_update_to, new DummyRoutingDebugAdapter());\n\t}\n\n\t/**\n\t * Create a route table from the link state database\n\t */\n\tpublic void CreateRouteTable(int version_to_update_to, IRoutingDebugAdapter debug) {\n\n\t\tif (ServerRouter._lastLSAVersion[simpleID] >= version_to_update_to && !debug.independent()) {\n\t\t\treturn; // this update is already done.\n\t\t}\n\n\t\t//Dijkstra!\n\n\t\tdebug.init();\n\n\t\tint routingTableSize = ServerRouter.getBiggestSimpleID();\n\t\tif (routingTableSize == 0) {\n\t\t\troutingTableSize = ServerRouter.SharedLSADatabase.length; // deliberatly ignoring concurrent access, either the old or the version of the size will work, this is just an approximate number.\n\t\t}\n\n\t\t/**\n\t\t * same info as above, but sorted by distance -- sorting is implicit,\n\t\t * because Dijkstra finds the closest routes first.\n\t\t **/\n\t\tList<ExitRoute> routeCosts = new ArrayList<>(routingTableSize);\n\n\t\t//Add the current Router\n\t\trouteCosts.add(new ExitRoute(this, this, null, null, 0, EnumSet.allOf(PipeRoutingConnectionType.class), 0));\n\n\t\tArrayList<Pair<ILogisticsPowerProvider, List<IFilter>>> powerTable;\n\t\tif (_powerAdjacent != null) {\n\t\t\tpowerTable = new ArrayList<>(_powerAdjacent);\n\t\t} else {\n\t\t\tpowerTable = new ArrayList<>(5);\n\t\t}\n\t\tArrayList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower;\n\t\tif (_subSystemPowerAdjacent != null) {\n\t\t\tsubSystemPower = new ArrayList<>(_subSystemPowerAdjacent);\n\t\t} else {\n\t\t\tsubSystemPower = new ArrayList<>(5);\n\t\t}\n\n\t\t//space and time inefficient, a bitset with 3 bits per node would save a lot but makes the main iteration look like a complete mess\n\t\tArrayList<EnumSet<PipeRoutingConnectionType>> closedSet = new ArrayList<>(ServerRouter.getBiggestSimpleID());\n\t\tfor (int i = 0; i < ServerRouter.getBiggestSimpleID(); i++) {\n\t\t\tclosedSet.add(null);\n\t\t}\n\n\t\tArrayList<EnumMap<PipeRoutingConnectionType, List<List<IFilter>>>> filterList = new ArrayList<>(ServerRouter\n\t\t\t\t.getBiggestSimpleID());\n\t\tfor (int i = 0; i < ServerRouter.getBiggestSimpleID(); i++) {\n\t\t\tfilterList.add(null);\n\t\t}\n\n\t\t/** The total cost for the candidate route **/\n\t\tPriorityQueue<ExitRoute> candidatesCost = new PriorityQueue<>((int) Math.sqrt(routingTableSize)); // sqrt nodes is a good guess for the total number of candidate nodes at once.\n\n\t\t//Init candidates\n\t\t// the shortest way to go to an adjacent item is the adjacent item.\n\t\tfor (Entry<ServerRouter, ExitRoute> pipe : _adjacentRouter.entrySet()) {\n\t\t\tExitRoute currentE = pipe.getValue();\n\t\t\tIRouter newRouter = pipe.getKey();\n\t\t\tif (newRouter != null) {\n\t\t\t\tExitRoute newER = new ExitRoute(newRouter, newRouter, currentE.distanceToDestination, currentE.connectionDetails, currentE.filters, new ArrayList<>(0), currentE.blockDistance);\n\t\t\t\tcandidatesCost.add(newER);\n\t\t\t\tdebug.newCanidate(newER);\n\t\t\t}\n\t\t}\n\n\t\tdebug.start(candidatesCost, closedSet, filterList);\n\n\t\tServerRouter.SharedLSADatabasereadLock.lock(); // readlock, not inside the while - too costly to aquire, then release.\n\t\tExitRoute lowestCostNode;\n\t\twhile ((lowestCostNode = candidatesCost.poll()) != null) {\n\t\t\tif (!lowestCostNode.hasActivePipe()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (debug.isDebug()) {\n\t\t\t\tServerRouter.SharedLSADatabasereadLock.unlock();\n\t\t\t}\n\t\t\tdebug.nextPipe(lowestCostNode);\n\t\t\tif (debug.isDebug()) {\n\t\t\t\tServerRouter.SharedLSADatabasereadLock.lock();\n\t\t\t}\n\n\t\t\tfor (ExitRoute e : candidatesCost) {\n\t\t\t\te.debug.isNewlyAddedCanidate = false;\n\t\t\t}\n\n\t\t\t//if the node does not have any flags not in the closed set, check it\n\t\t\tEnumSet<PipeRoutingConnectionType> lowestCostClosedFlags = closedSet.get(lowestCostNode.destination.getSimpleID());\n\t\t\tif (lowestCostClosedFlags == null) {\n\t\t\t\tlowestCostClosedFlags = EnumSet.noneOf(PipeRoutingConnectionType.class);\n\t\t\t}\n\t\t\tif (lowestCostClosedFlags.containsAll(lowestCostNode.getFlagsNoCopy())) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (debug.isDebug()) {\n\t\t\t\tEnumSet<PipeRoutingConnectionType> newFlags = lowestCostNode.getFlags();\n\t\t\t\tnewFlags.removeAll(lowestCostClosedFlags);\n\n\t\t\t\tdebug.newFlagsForPipe(newFlags);\n\t\t\t}\n\n\t\t\tEnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters = filterList.get(lowestCostNode.destination.getSimpleID());\n\n\t\t\tdebug.filterList(filters);\n\n\t\t\tif (filters != null) {\n\t\t\t\tboolean containsNewInfo = false;\n\t\t\t\tfor (PipeRoutingConnectionType type : lowestCostNode.getFlagsNoCopy()) {\n\t\t\t\t\tif (lowestCostClosedFlags.contains(type)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!filters.containsKey(type)) {\n\t\t\t\t\t\tcontainsNewInfo = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tboolean matches = false;\n\t\t\t\t\tList<List<IFilter>> list = filters.get(type);\n\t\t\t\t\tfor (List<IFilter> filter : list) {\n\t\t\t\t\t\tif (lowestCostNode.filters.containsAll(filter)) {\n\t\t\t\t\t\t\tmatches = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!matches) {\n\t\t\t\t\t\tcontainsNewInfo = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!containsNewInfo) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Add new candidates from the newly approved route\n\t\t\tLSA lsa = null;\n\t\t\tif (lowestCostNode.destination.getSimpleID() < ServerRouter.SharedLSADatabase.length) {\n\t\t\t\tlsa = ServerRouter.SharedLSADatabase[lowestCostNode.destination.getSimpleID()];\n\t\t\t}\n\t\t\tif (lsa == null) {\n\t\t\t\tlowestCostNode.removeFlags(lowestCostClosedFlags);\n\t\t\t\tlowestCostClosedFlags.addAll(lowestCostNode.getFlagsNoCopy());\n\t\t\t\tif (lowestCostNode.containsFlag(PipeRoutingConnectionType.canRouteTo) || lowestCostNode.containsFlag(PipeRoutingConnectionType.canRequestFrom)) {\n\t\t\t\t\trouteCosts.add(lowestCostNode);\n\t\t\t\t}\n\t\t\t\tclosedSet.set(lowestCostNode.destination.getSimpleID(), lowestCostClosedFlags);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (lowestCostNode.containsFlag(PipeRoutingConnectionType.canPowerFrom)) {\n\t\t\t\tif (lsa.power != null && !lsa.power.isEmpty()) {\n\t\t\t\t\tfor (Pair<ILogisticsPowerProvider, List<IFilter>> p : lsa.power) {\n\t\t\t\t\t\tPair<ILogisticsPowerProvider, List<IFilter>> entry = p.copy();\n\t\t\t\t\t\tList<IFilter> list = new ArrayList<>();\n\t\t\t\t\t\tlist.addAll(p.getValue2());\n\t\t\t\t\t\tlist.addAll(lowestCostNode.filters);\n\t\t\t\t\t\tentry.setValue2(Collections.unmodifiableList(list));\n\t\t\t\t\t\tif (!powerTable.contains(entry)) {\n\t\t\t\t\t\t\tpowerTable.add(entry);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (lowestCostNode.containsFlag(PipeRoutingConnectionType.canPowerSubSystemFrom)) {\n\t\t\t\tif (lsa.subSystemPower != null && !lsa.subSystemPower.isEmpty()) {\n\t\t\t\t\tfor (Pair<ISubSystemPowerProvider, List<IFilter>> p : lsa.subSystemPower) {\n\t\t\t\t\t\tPair<ISubSystemPowerProvider, List<IFilter>> entry = p.copy();\n\t\t\t\t\t\tList<IFilter> list = new ArrayList<>();\n\t\t\t\t\t\tlist.addAll(p.getValue2());\n\t\t\t\t\t\tlist.addAll(lowestCostNode.filters);\n\t\t\t\t\t\tentry.setValue2(Collections.unmodifiableList(list));\n\t\t\t\t\t\tif (!subSystemPower.contains(entry)) {\n\t\t\t\t\t\t\tsubSystemPower.add(entry);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (Entry<IRouter, Quartet<Double, EnumSet<PipeRoutingConnectionType>, List<IFilter>, Integer>> newCandidate : lsa.neighboursWithMetric.entrySet()) {\n\t\t\t\tdouble candidateCost = lowestCostNode.distanceToDestination + newCandidate.getValue().getValue1();\n\t\t\t\tint blockDistance = lowestCostNode.blockDistance + newCandidate.getValue().getValue4();\n\t\t\t\tEnumSet<PipeRoutingConnectionType> newCT = lowestCostNode.getFlags();\n\t\t\t\tnewCT.retainAll(newCandidate.getValue().getValue2());\n\t\t\t\tif (!newCT.isEmpty()) {\n\t\t\t\t\tExitRoute next = new ExitRoute(lowestCostNode.root, newCandidate.getKey(), candidateCost, newCT, lowestCostNode.filters, newCandidate.getValue().getValue3(), blockDistance);\n\t\t\t\t\tnext.debug.isTraced = lowestCostNode.debug.isTraced;\n\t\t\t\t\tcandidatesCost.add(next);\n\t\t\t\t\tdebug.newCanidate(next);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlowestCostClosedFlags = lowestCostClosedFlags.clone();\n\n\t\t\tlowestCostNode.removeFlags(lowestCostClosedFlags);\n\t\t\tlowestCostClosedFlags.addAll(lowestCostNode.getFlagsNoCopy());\n\t\t\tif (lowestCostNode.containsFlag(PipeRoutingConnectionType.canRouteTo) || lowestCostNode.containsFlag(PipeRoutingConnectionType.canRequestFrom) || lowestCostNode.containsFlag(PipeRoutingConnectionType.canPowerSubSystemFrom)) {\n\t\t\t\trouteCosts.add(lowestCostNode);\n\t\t\t}\n\t\t\tEnumMap<PipeRoutingConnectionType, List<List<IFilter>>> map = filterList.get(lowestCostNode.destination.getSimpleID());\n\t\t\tif (map == null) {\n\t\t\t\tmap = new EnumMap<>(PipeRoutingConnectionType.class);\n\t\t\t\tfilterList.set(lowestCostNode.destination.getSimpleID(), map);\n\t\t\t}\n\t\t\tfor (PipeRoutingConnectionType type : lowestCostNode.getFlagsNoCopy()) {\n\t\t\t\tif (!map.containsKey(type)) {\n\t\t\t\t\tmap.put(type, new ArrayList<>());\n\t\t\t\t}\n\t\t\t\tmap.get(type).add(Collections.unmodifiableList(new ArrayList<>(lowestCostNode.filters)));\n\t\t\t}\n\t\t\tif (lowestCostNode.filters.isEmpty()) {\n\t\t\t\tclosedSet.set(lowestCostNode.destination.getSimpleID(), lowestCostClosedFlags);\n\t\t\t}\n\n\t\t\tif (debug.isDebug()) {\n\t\t\t\tServerRouter.SharedLSADatabasereadLock.unlock();\n\t\t\t}\n\t\t\tdebug.handledPipe();\n\t\t\tif (debug.isDebug()) {\n\t\t\t\tServerRouter.SharedLSADatabasereadLock.lock();\n\t\t\t}\n\t\t}\n\t\tServerRouter.SharedLSADatabasereadLock.unlock();\n\n\t\tdebug.stepOneDone();\n\n\t\t//Build route table\n\t\tArrayList<List<ExitRoute>> routeTable = new ArrayList<>(ServerRouter.getBiggestSimpleID() + 1);\n\t\twhile (simpleID >= routeTable.size()) {\n\t\t\trouteTable.add(null);\n\t\t}\n\t\trouteTable.set(simpleID, new OneList<>(new ExitRoute(this, this, null, null, 0, EnumSet\n\t\t\t\t.allOf(PipeRoutingConnectionType.class), 0)));\n\n\t\tfor (ExitRoute node : routeCosts) {\n\t\t\tIRouter firstHop = node.root;\n\t\t\tExitRoute hop = _adjacentRouter.get(firstHop);\n\t\t\tif (hop == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnode.root = this; // replace the root with this, rather than the first hop.\n\t\t\tnode.exitOrientation = hop.exitOrientation;\n\t\t\twhile (node.destination.getSimpleID() >= routeTable\n\t\t\t\t\t.size()) { // the array will not expand, as it is init'd to contain enough elements\n\t\t\t\trouteTable.add(null);\n\t\t\t}\n\n\t\t\tList<ExitRoute> current = routeTable.get(node.destination.getSimpleID());\n\t\t\tif (current != null && !current.isEmpty()) {\n\t\t\t\tList<ExitRoute> list = new ArrayList<>(current);\n\t\t\t\tlist.add(node);\n\t\t\t\trouteTable.set(node.destination.getSimpleID(), Collections.unmodifiableList(list));\n\t\t\t} else {\n\t\t\t\trouteTable.set(node.destination.getSimpleID(), new OneList<>(node));\n\t\t\t}\n\t\t}\n\t\tdebug.stepTwoDone();\n\t\tif (!debug.independent()) {\n\t\t\troutingTableUpdateWriteLock.lock();\n\t\t\tif (version_to_update_to == _LSAVersion) {\n\t\t\t\tServerRouter.SharedLSADatabasereadLock.lock();\n\n\t\t\t\tif (ServerRouter._lastLSAVersion[simpleID] < version_to_update_to) {\n\t\t\t\t\tServerRouter._lastLSAVersion[simpleID] = version_to_update_to;\n\t\t\t\t\t_LPPowerTable = Collections.unmodifiableList(powerTable);\n\t\t\t\t\t_SubSystemPowerTable = Collections.unmodifiableList(subSystemPower);\n\t\t\t\t\t_routeTable = Collections.unmodifiableList(routeTable);\n\t\t\t\t\t_routeCosts = Collections.unmodifiableList(routeCosts);\n\t\t\t\t}\n\t\t\t\tServerRouter.SharedLSADatabasereadLock.unlock();\n\t\t\t}\n\t\t\troutingTableUpdateWriteLock.unlock();\n\t\t}\n\t\tif (getCachedPipe() != null) {\n\t\t\tgetCachedPipe().spawnParticle(Particles.LightGreenParticle, 5);\n\t\t}\n\n\t\tdebug.done();\n\t}\n\n\t/**\n\t * @param hasBeenProcessed a BitSet flagging which nodes have already been acted on. The router should set the bit for its own id.\n\t */\n\tpublic void act(BitSet hasBeenProcessed, Action actor) {\n\t\tif (hasBeenProcessed.get(simpleID)) {\n\t\t\treturn;\n\t\t}\n\t\thasBeenProcessed.set(simpleID);\n\t\tif (!actor.isInteresting(this)) {\n\t\t\treturn;\n\t\t}\n\n\t\tactor.doTo(this);\n\t\tfor (ServerRouter r : _adjacentRouter.keySet()) {\n\t\t\tr.act(hasBeenProcessed, actor);\n\t\t}\n\t}\n\n\t/**\n\t * Flags the last sent LSA as expired. Each router will be responsible of\n\t * purging it from its database.\n\t */\n\t@Override\n\tpublic void destroy() {\n\t\tServerRouter.SharedLSADatabasewriteLock.lock(); // take a write lock so that we don't overlap with any ongoing route updates\n\t\tif (simpleID < ServerRouter.SharedLSADatabase.length) {\n\t\t\tServerRouter.SharedLSADatabase[simpleID] = null;\n\t\t}\n\t\tServerRouter.SharedLSADatabasewriteLock.unlock();\n\t\tremoveAllInterests();\n\n\t\tclearPipeCache();\n\t\tisDestroyed = true;\n\t\tSimpleServiceLocator.routerManager.removeRouter(simpleID);\n\t\tfor (List<ITileEntityChangeListener> list : listenedPipes) {\n\t\t\tlist.remove(localChangeListener);\n\t\t}\n\t\tupdateAdjacentAndLsa();\n\t\tServerRouter.releaseSimpleID(simpleID);\n\t}\n\n\tprivate void removeAllInterests() {\n\t\tremoveGenericInterest();\n\n\t\tinterestsRWLock.lock();\n\t\ttry {\n\t\t\tinterests.forEach(this::removeGlobalInterest);\n\t\t\tinterests.clear();\n\t\t} finally {\n\t\t\tinterestsRWLock.unlock();\n\t\t}\n\t}\n\n\tpublic boolean checkAdjacentUpdate() {\n\t\tboolean blockNeedsUpdate = recheckAdjacent();\n\t\tif (!blockNeedsUpdate) {\n\t\t\treturn false;\n\t\t}\n\n\t\tCoreRoutedPipe pipe = getPipe();\n\t\tif (pipe == null) {\n\t\t\treturn true;\n\t\t}\n\t\tpipe.refreshRender(true);\n\t\treturn true;\n\t}\n\n\tpublic void flagForRoutingUpdate() {\n\t\t_LSAVersion++;\n\t\t//if(LogisticsPipes.DEBUG)\n\t\t//System.out.println(\"[LogisticsPipes] targeted for routing update to \"+_LSAVersion+\" for Node\" +  simpleID);\n\t}\n\n\tprivate void updateAdjacentAndLsa() {\n\t\t//this already got a checkAdjacentUpdate, so start the recursion with neighbors\n\t\tBitSet visited = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\tAction flood = new floodCheckAdjacent();\n\t\tvisited.set(simpleID);\n\t\t// for all connected updatecurrent and previous\n\t\tfor (ServerRouter r : _adjacentRouter_Old.keySet()) {\n\t\t\tr.act(visited, flood);\n\t\t}\n\t\tfor (ServerRouter r : _adjacentRouter.keySet()) {\n\t\t\tr.act(visited, flood);\n\t\t}\n\t\tupdateLsa();\n\t}\n\n\tvoid updateLsa() {\n\t\t//now increment LSA version in the network\n\t\tBitSet visited = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\tfor (ServerRouter r : _adjacentRouter_Old.keySet()) {\n\t\t\tr.act(visited, new flagForLSAUpdate());\n\t\t}\n\t\t_adjacentRouter_Old = new HashMap<>();\n\t\tact(visited, new flagForLSAUpdate());\n\t}\n\n\t@Override\n\tpublic void update(boolean doFullRefresh, CoreRoutedPipe pipe) {\n\t\tif (connectionNeedsChecking == 2) {\n\t\t\tensureChangeListenerAttachedToPipe(pipe);\n\n\t\t\tfinal Info info = StackTraceUtil.addTraceInformation(causedBy::toString);\n\t\t\tboolean blockNeedsUpdate = checkAdjacentUpdate();\n\t\t\tif (blockNeedsUpdate) {\n\t\t\t\tupdateLsa();\n\t\t\t}\n\t\t\tinfo.end();\n\n\t\t\tensureChangeListenerAttachedToPipe(pipe);\n\t\t}\n\t\tif (connectionNeedsChecking == 1) {\n\t\t\tconnectionNeedsChecking = 2;\n\t\t}\n\t\thandleQueuedTasks(pipe);\n\t\tupdateInterests();\n\t\tif (doFullRefresh) {\n\t\t\tensureChangeListenerAttachedToPipe(pipe);\n\n\t\t\tboolean blockNeedsUpdate = checkAdjacentUpdate();\n\t\t\tif (blockNeedsUpdate) {\n\t\t\t\t//updateAdjacentAndLsa();\n\t\t\t\tupdateLsa();\n\t\t\t}\n\n\t\t\tensureChangeListenerAttachedToPipe(pipe);\n\t\t\tlazyUpdateRoutingTable();\n\t\t} else if (Configs.MULTI_THREAD_NUMBER > 0) {\n\t\t\tlazyUpdateRoutingTable();\n\t\t}\n\t}\n\n\tprivate void ensureChangeListenerAttachedToPipe(CoreRoutedPipe pipe) {\n\t\tif (pipe.container instanceof ILPTEInformation && ((ILPTEInformation) pipe.container).getLPTileEntityObject() != null) {\n\t\t\tif (!((ILPTEInformation) pipe.container).getLPTileEntityObject().changeListeners.contains(localChangeListener)) {\n\t\t\t\t((ILPTEInformation) pipe.container).getLPTileEntityObject().changeListeners.add(localChangeListener);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void handleQueuedTasks(CoreRoutedPipe pipe) {\n\t\twhile (!queue.isEmpty()) {\n\t\t\tPair<Integer, IRouterQueuedTask> element = queue.poll();\n\t\t\tif (element.getValue1() > MainProxy.getGlobalTick()) {\n\t\t\t\telement.getValue2().call(pipe, this);\n\t\t\t}\n\t\t}\n\t}\n\n\t/************* IROUTER *******************/\n\n\t@Override\n\tpublic boolean isRoutedExit(EnumFacing o) {\n\t\treturn _routedExits.contains(o);\n\t}\n\n\t@Override\n\tpublic boolean isSubPoweredExit(EnumFacing o) {\n\t\treturn _subPowerExits.containsKey(o);\n\t}\n\n\t@Override\n\tpublic int getDistanceToNextPowerPipe(EnumFacing dir) {\n\t\treturn _subPowerExits.get(dir);\n\t}\n\n\t@Override\n\tpublic ExitRoute getExitFor(int id, boolean active, ItemIdentifier type) {\n\t\tensureLatestRoutingTable();\n\t\tif (getRouteTable().size() <= id || getRouteTable().get(id) == null) {\n\t\t\treturn null;\n\t\t}\n\t\touter:\n\t\tfor (ExitRoute exit : getRouteTable().get(id)) {\n\t\t\tif (exit.containsFlag(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\t\tfor (IFilter filter : exit.filters) {\n\t\t\t\t\tif (!active) {\n\t\t\t\t\t\tif (filter.blockRouting() || filter.isBlocked() == filter.isFilteredItem(type)) {\n\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ((filter.blockProvider() && filter.blockCrafting()) || filter.isBlocked() == filter.isFilteredItem(type)) {\n\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn exit;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean hasRoute(int id, boolean active, ItemIdentifier type) {\n\t\tif (!SimpleServiceLocator.routerManager.isRouterUnsafe(id, false)) {\n\t\t\treturn false;\n\t\t}\n\t\tensureLatestRoutingTable();\n\t\tif (getRouteTable().size() <= id) {\n\t\t\treturn false;\n\t\t}\n\t\tList<ExitRoute> source = getRouteTable().get(id);\n\t\tif (source == null) {\n\t\t\treturn false;\n\t\t}\n\t\touter:\n\t\tfor (ExitRoute exit : source) {\n\t\t\tif (exit.containsFlag(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\t\tfor (IFilter filter : exit.filters) {\n\t\t\t\t\tif (!active) {\n\t\t\t\t\t\tif (filter.blockRouting() || filter.isBlocked() == filter.isFilteredItem(type)) {\n\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ((filter.blockProvider() && filter.blockCrafting()) || filter.isBlocked() == filter.isFilteredItem(type)) {\n\t\t\t\t\t\t\tcontinue outer;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic LogisticsModule getLogisticsModule() {\n\t\tCoreRoutedPipe pipe = getPipe();\n\t\tif (pipe == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn pipe.getLogisticsModule();\n\t}\n\n\t@Override\n\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> getPowerProvider() {\n\t\treturn _LPPowerTable;\n\t}\n\n\t@Override\n\tpublic List<Pair<ISubSystemPowerProvider, List<IFilter>>> getSubSystemPowerProvider() {\n\t\treturn _SubSystemPowerTable;\n\t}\n\n\t@Override\n\tpublic boolean isSideDisconnected(EnumFacing dir) {\n\t\treturn null != dir && sideDisconnected[dir.ordinal()];\n\t}\n\n\tpublic void updateInterests() {\n\t\tif (--ticksUntillNextInventoryCheck > 0) {\n\t\t\treturn;\n\t\t}\n\t\tticksUntillNextInventoryCheck = ServerRouter.REFRESH_TIME;\n\t\tif (ServerRouter.iterated++ % simpleID == 0) {\n\t\t\tticksUntillNextInventoryCheck++; // randomly wait 1 extra tick - just so that every router doesn't tick at the same time\n\t\t}\n\t\tif (ServerRouter.iterated >= ServerRouter.getBiggestSimpleID()) {\n\t\t\tServerRouter.iterated = 0;\n\t\t}\n\t\tCoreRoutedPipe pipe = getPipe();\n\t\tif (pipe == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (pipe.hasGenericInterests()) {\n\t\t\tdeclareGenericInterest();\n\t\t} else {\n\t\t\tremoveGenericInterest();\n\t\t}\n\t\tTreeSet<ItemIdentifier> newInterests = new TreeSet<>();\n\t\tpipe.collectSpecificInterests(newInterests);\n\n\t\tinterestsRWLock.lock();\n\t\ttry {\n\t\t\tif (newInterests.size() == interests.size() && newInterests.containsAll(interests)) {\n\t\t\t\t// interests are up-to-date\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tinterests.stream().filter(itemid -> !newInterests.contains(itemid)).forEach(this::removeGlobalInterest);\n\t\t\tnewInterests.stream().filter(itemid -> !interests.contains(itemid)).forEach(this::addGlobalInterest);\n\t\t\tinterests = newInterests;\n\t\t} finally {\n\t\t\tinterestsRWLock.unlock();\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void removeGenericInterest() {\n\t\tgenericInterestsWLock.lock();\n\t\ttry {\n\t\t\tfinal TreeSet<ServerRouter> newGenericInterests = (TreeSet<ServerRouter>) ServerRouter.genericInterests.clone();\n\t\t\tif (newGenericInterests.remove(this)) {\n\t\t\t\tServerRouter.genericInterests = newGenericInterests;\n\t\t\t}\n\t\t} finally {\n\t\t\tgenericInterestsWLock.unlock();\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void declareGenericInterest() {\n\t\tgenericInterestsWLock.lock();\n\t\ttry {\n\t\t\tfinal TreeSet<ServerRouter> newGenericInterests = (TreeSet<ServerRouter>) ServerRouter.genericInterests.clone();\n\t\t\tif (newGenericInterests.add(this)) {\n\t\t\t\tServerRouter.genericInterests = newGenericInterests;\n\t\t\t}\n\t\t} finally {\n\t\t\tgenericInterestsWLock.unlock();\n\t\t}\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void addGlobalInterest(ItemIdentifier itemid) {\n\t\tServerRouter.globalSpecificInterests.compute(itemid, (unused, serverRouters) -> {\n\t\t\tfinal TreeSet<ServerRouter> newServerRouters = serverRouters == null ? new TreeSet<>() : (TreeSet<ServerRouter>) serverRouters.clone();\n\t\t\tnewServerRouters.add(this);\n\t\t\treturn newServerRouters;\n\t\t});\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tprivate void removeGlobalInterest(ItemIdentifier itemid) {\n\t\tServerRouter.globalSpecificInterests.computeIfPresent(itemid, (unused, serverRouters) -> {\n\t\t\tif (serverRouters.equals(ObjectSets.singleton(this))) {\n\t\t\t\treturn null;\n\t\t\t} else {\n\t\t\t\tfinal TreeSet<ServerRouter> newServerRouters = (TreeSet<ServerRouter>) serverRouters.clone();\n\t\t\t\tnewServerRouters.remove(this);\n\t\t\t\treturn newServerRouters;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic int compareTo(ServerRouter o) {\n\t\treturn simpleID - o.simpleID;\n\t}\n\n\t@Override\n\tpublic List<ExitRoute> getDistanceTo(IRouter r) {\n\t\tensureLatestRoutingTable();\n\t\tint id = r.getSimpleID();\n\t\tif (_routeTable.size() <= id) {\n\t\t\treturn new ArrayList<>(0);\n\t\t}\n\t\tList<ExitRoute> result = _routeTable.get(id);\n\t\treturn result != null ? result : new ArrayList<>(0);\n\t}\n\n\t@Override\n\tpublic void clearInterests() {\n\t\tremoveAllInterests();\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"ServerRouter: {ID: %d, UUID: %s, AT: (%d, %d, %d, %d), Version: %d), Destroyed: %s}\", simpleID, getId(), _dimension, _xCoord, _yCoord, _zCoord, _LSAVersion, isDestroyed);\n\t}\n\n\t@Override\n\tpublic void forceLsaUpdate() {\n\t\tBitSet visited = new BitSet(ServerRouter.getBiggestSimpleID());\n\t\tact(visited, new flagForLSAUpdate());\n\t}\n\n\t@Override\n\tpublic List<ExitRoute> getRoutersOnSide(EnumFacing direction) {\n\t\treturn _adjacentRouter.values().stream()\n\t\t\t\t.filter(exit -> exit.exitOrientation == direction)\n\t\t\t\t.collect(Collectors.toList());\n\t}\n\n\t@Override\n\tpublic void queueTask(int i, IRouterQueuedTask callable) {\n\t\tqueue.add(new Pair<>(i + MainProxy.getGlobalTick(), callable));\n\t}\n\n\tprotected static class LSA {\n\n\t\tpublic HashMap<IRouter, Quartet<Double, EnumSet<PipeRoutingConnectionType>, List<IFilter>, Integer>> neighboursWithMetric;\n\t\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> power;\n\t\tpublic ArrayList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower;\n\t}\n\n\tprivate abstract static class RouterRunnable implements Comparable<RouterRunnable>, Runnable {\n\n\t\tpublic abstract int getPrority();\n\n\t\tpublic abstract int localCompare(RouterRunnable o);\n\n\t\t@Override\n\t\tpublic int compareTo(RouterRunnable o) {\n\t\t\tif (o.getPrority() == getPrority()) {\n\t\t\t\treturn localCompare(o);\n\t\t\t}\n\t\t\treturn o.getPrority() - getPrority();\n\t\t}\n\t}\n\n\tinterface Action {\n\t\tboolean isInteresting(ServerRouter router);\n\n\t\tvoid doTo(ServerRouter router);\n\t}\n\n\t/**\n\t * Floodfill recheckAdjacent, leave _prevAdjacentRouter around for LSA\n\t * updating\n\t */\n\tstatic class floodCheckAdjacent implements Action {\n\n\t\tpublic boolean isInteresting(ServerRouter router) {\n\t\t\treturn router.checkAdjacentUpdate();\n\t\t}\n\n\t\tpublic void doTo(ServerRouter router) {}\n\t}\n\n\t/**\n\t * Floodfill LSA increment and clean up the _prevAdjacentRouter list left by\n\t * floodCheckAdjacent\n\t */\n\tstatic class flagForLSAUpdate implements Action {\n\n\t\tpublic boolean isInteresting(ServerRouter router) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic void doTo(ServerRouter router) {\n\t\t\trouter.flagForRoutingUpdate();\n\t\t}\n\t}\n\n\tstatic class floodClearCache implements Action {\n\n\t\tpublic boolean isInteresting(ServerRouter router) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic void doTo(ServerRouter router) {\n\t\t\tCacheHolder.clearCache(router.oldTouchedPipes);\n\t\t}\n\t}\n\n\tprivate class UpdateRouterRunnable extends RouterRunnable {\n\n\t\tint newVersion;\n\t\tboolean run;\n\t\tIRouter target;\n\n\t\tUpdateRouterRunnable(IRouter target) {\n\t\t\trun = true;\n\t\t\tnewVersion = _LSAVersion;\n\t\t\tthis.target = target;\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tif (!run) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tCoreRoutedPipe p = target.getCachedPipe();\n\t\t\t\tif (p == null) {\n\t\t\t\t\trun = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t//spinlock during the first tick, we can't touch the routing table, untill Update() has been called on every pipe.\n\t\t\t\tfor (int i = 0; i < 10 && p.stillNeedReplace(); i++) {\n\t\t\t\t\tThread.sleep(10);\n\t\t\t\t}\n\t\t\t\tif (p.stillNeedReplace()) {\n\t\t\t\t\treturn; // drop the pipe update if it still needs replace after 5 ticks.\n\t\t\t\t}\n\t\t\t\tCreateRouteTable(newVersion);\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\trun = false;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getPrority() {\n\t\t\treturn 0;\n\t\t}\n\n\t\t@Override\n\t\tpublic int localCompare(RouterRunnable o) {\n\t\t\tint c = 0;\n\t\t\tif (((UpdateRouterRunnable) o).newVersion <= 0) {\n\t\t\t\tc = newVersion - ((UpdateRouterRunnable) o).newVersion; // negative numbers have priority, more negative first\n\t\t\t}\n\t\t\tif (c != 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tc = target.getSimpleID() - ((UpdateRouterRunnable) o).target.getSimpleID(); // do things in order of router id, to minimize router recursion\n\t\t\tif (c != 0) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tc = ((UpdateRouterRunnable) o).newVersion - newVersion; // higher version first\n\t\t\treturn c;\n\t\t}\n\t}\n\n\tprivate class LSARouterRunnable extends RouterRunnable {\n\n\t\tprivate final int index = ServerRouter.maxLSAUpdateIndex++;\n\t\tHashMap<IRouter, Quartet<Double, EnumSet<PipeRoutingConnectionType>, List<IFilter>, Integer>> neighboursWithMetric;\n\t\tArrayList<Pair<ILogisticsPowerProvider, List<IFilter>>> power;\n\t\tArrayList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower;\n\n\t\tLSARouterRunnable(HashMap<IRouter, Quartet<Double, EnumSet<PipeRoutingConnectionType>, List<IFilter>, Integer>> neighboursWithMetric, ArrayList<Pair<ILogisticsPowerProvider, List<IFilter>>> power, ArrayList<Pair<ISubSystemPowerProvider, List<IFilter>>> subSystemPower) {\n\t\t\tthis.neighboursWithMetric = neighboursWithMetric;\n\t\t\tthis.power = power;\n\t\t\tthis.subSystemPower = subSystemPower;\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tlockAndUpdateLSA(neighboursWithMetric, power, subSystemPower);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getPrority() {\n\t\t\treturn 1;\n\t\t}\n\n\t\t@Override\n\t\tpublic int localCompare(RouterRunnable o) {\n\t\t\treturn index - ((LSARouterRunnable) o).index;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/channels/ChannelConnection.java",
    "content": "package logisticspipes.routing.channels;\n\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport lombok.Data;\n\n@Data\npublic class ChannelConnection {\n\n\tpublic Set<Integer> routers = new HashSet<>();\n\tpublic UUID identifier;\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/channels/ChannelInformation.java",
    "content": "package logisticspipes.routing.channels;\n\nimport java.util.UUID;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\nimport lombok.NonNull;\n\nimport logisticspipes.utils.PlayerIdentifier;\n\n@Data\n@AllArgsConstructor\npublic class ChannelInformation {\n\n\tpublic enum AccessRights {\n\t\tPRIVATE,\n\t\tSECURED,\n\t\tPUBLIC\n\t}\n\n\tprivate String name;\n\t@NonNull\n\tprivate final UUID channelIdentifier;\n\t@NonNull\n\tprivate PlayerIdentifier owner;\n\t@NonNull\n\tprivate AccessRights rights;\n\tprivate UUID responsibleSecurityID;\n\n\tpublic ChannelInformation(NBTTagCompound nbt) {\n\t\tname = nbt.getString(\"name\");\n\t\tchannelIdentifier = UUID.fromString(nbt.getString(\"channelIdentifier\"));\n\t\towner = PlayerIdentifier.readFromNBT(nbt, \"owner\");\n\t\trights = AccessRights.values()[nbt.getInteger(\"rights\")];\n\t\tif (nbt.hasKey(\"responsibleSecurityID\")) {\n\t\t\tresponsibleSecurityID = UUID.fromString(nbt.getString(\"responsibleSecurityID\"));\n\t\t} else {\n\t\t\tresponsibleSecurityID = null;\n\t\t}\n\t}\n\n\tpublic NBTTagCompound writeToNBT(NBTTagCompound compound) {\n\t\tcompound.setString(\"name\", name);\n\t\tcompound.setString(\"channelIdentifier\", channelIdentifier.toString());\n\t\towner.writeToNBT(compound, \"owner\");\n\t\tcompound.setInteger(\"rights\", rights.ordinal());\n\t\tif (responsibleSecurityID != null) {\n\t\t\tcompound.setString(\"responsibleSecurityID\", responsibleSecurityID.toString());\n\t\t}\n\n\t\treturn compound;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/channels/ChannelManager.java",
    "content": "package logisticspipes.routing.channels;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.UUID;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.world.World;\nimport net.minecraft.world.storage.WorldSavedData;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.blocks.LogisticsSecurityTileEntity;\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.ChannelInformationPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.security.SecuritySettings;\nimport logisticspipes.utils.PlayerIdentifier;\n\npublic class ChannelManager implements IChannelManager {\n\n\tprivate static final String DATA_NAME = LPConstants.LP_MOD_ID + \"_ChannelManager_SavedData\";\n\tprivate SavedData savedData;\n\n\tpublic ChannelManager(@Nonnull World world) {\n\t\tsavedData = (SavedData) Objects.requireNonNull(world.getMapStorage()).getOrLoadData(SavedData.class, DATA_NAME);\n\t\tif (savedData == null) {\n\t\t\tsavedData = new SavedData();\n\t\t\tworld.getMapStorage().setData(DATA_NAME, savedData);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<ChannelInformation> getChannels() {\n\t\treturn Collections.unmodifiableList(savedData.channels);\n\t}\n\n\tprivate boolean isChannelAllowedFor(ChannelInformation channel, EntityPlayer player) {\n\t\tswitch (channel.getRights()) {\n\t\t\tcase PUBLIC:\n\t\t\t\treturn true;\n\t\t\tcase SECURED:\n\t\t\t\tfinal UUID secUUID = channel.getResponsibleSecurityID();\n\t\t\t\tfinal LogisticsSecurityTileEntity station = SimpleServiceLocator.securityStationManager.getStation(secUUID);\n\t\t\t\tif (station != null) {\n\t\t\t\t\tfinal SecuritySettings settings = station.getSecuritySettingsForPlayer(player, false);\n\t\t\t\t\tif (settings != null) {\n\t\t\t\t\t\treturn settings.accessRoutingChannels;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase PRIVATE:\n\t\t\t\treturn channel.getOwner().equals(PlayerIdentifier.get(player));\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic List<ChannelInformation> getAllowedChannels(EntityPlayer player) {\n\t\treturn Collections.unmodifiableList(savedData.channels.stream().filter(channel -> isChannelAllowedFor(channel, player)).collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic ChannelInformation createNewChannel(String name, PlayerIdentifier owner, ChannelInformation.AccessRights rights, UUID responsibleSecurityID) {\n\t\tChannelInformation channel = new ChannelInformation(name, UUID.randomUUID(), owner, rights, responsibleSecurityID);\n\t\tsavedData.channels.add(channel);\n\t\tsavedData.markDirty();\n\t\tsendUpdatePacketToClients(channel);\n\t\treturn channel;\n\t}\n\n\t@Override\n\tpublic void updateChannelName(UUID channelIdentifier, String newName) {\n\t\tsavedData.channels.stream().filter(channel -> channel.getChannelIdentifier().equals(channelIdentifier)).forEach(channel -> {\n\t\t\tchannel.setName(newName);\n\t\t\tsendUpdatePacketToClients(channel);\n\t\t});\n\t\tsavedData.markDirty();\n\n\t}\n\n\t@Override\n\tpublic void updateChannelRights(UUID channelIdentifier, ChannelInformation.AccessRights rights, UUID responsibleSecurityID) {\n\t\tsavedData.channels.stream().filter(channel -> channel.getChannelIdentifier().equals(channelIdentifier)).forEach(channel -> {\n\t\t\tchannel.setRights(rights);\n\t\t\tchannel.setResponsibleSecurityID(responsibleSecurityID);\n\t\t\tsendUpdatePacketToClients(channel);\n\t\t});\n\t\tsavedData.markDirty();\n\t}\n\n\t@Override\n\tpublic void removeChannel(UUID channelIdentifier) {\n\t\tOptional<ChannelInformation> optChannel = savedData.channels.stream().filter(channel -> channel.getChannelIdentifier().equals(channelIdentifier)).findFirst();\n\t\tsavedData.channels.removeIf(channel -> channel.getChannelIdentifier().equals(channelIdentifier));\n\t\toptChannel.ifPresent(channelInformation -> sendUpdatePacketToClients(new ChannelInformation(null, channelIdentifier, channelInformation.getOwner(), channelInformation.getRights(), null)));\n\t\tsavedData.markDirty();\n\t}\n\n\tpublic void markDirty() {\n\t\tsavedData.markDirty();\n\t}\n\n\tprivate void sendUpdatePacketToClients(ChannelInformation channel) {\n\t\tMainProxy.sendToAllPlayers(PacketHandler.getPacket(ChannelInformationPacket.class).setInformation(channel).setTargeted(false).setCompressable(true));\n\t}\n\n\tpublic static class SavedData extends WorldSavedData {\n\n\t\tList<ChannelInformation> channels = new ArrayList<>();\n\n\t\tpublic SavedData(String name) {\n\t\t\tsuper(name);\n\t\t}\n\n\t\tpublic SavedData() {\n\t\t\tthis(DATA_NAME);\n\t\t}\n\n\t\t@Override\n\t\tpublic void readFromNBT(NBTTagCompound nbt) {\n\t\t\tchannels = new ArrayList<>();\n\t\t\tfor (int i = 0; i < nbt.getInteger(\"dataSize\"); i++) {\n\t\t\t\tchannels.add(i, new ChannelInformation(nbt.getCompoundTag(\"data\" + i)));\n\t\t\t}\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic NBTTagCompound writeToNBT(NBTTagCompound compound) {\n\t\t\tcompound.setInteger(\"dataSize\", channels.size());\n\t\t\tfor (int i = 0; i < channels.size(); i++) {\n\t\t\t\tChannelInformation channel = channels.get(i);\n\t\t\t\tNBTTagCompound nbt = new NBTTagCompound();\n\t\t\t\tchannel.writeToNBT(nbt);\n\t\t\t\tcompound.setTag(\"data\" + i, nbt);\n\t\t\t}\n\t\t\treturn compound;\n\t\t}\n\n\t\tpublic List<ChannelInformation> getChannels() {\n\t\t\treturn this.channels;\n\t\t}\n\n\t\tpublic SavedData setChannels(List<ChannelInformation> channels) {\n\t\t\tthis.channels = channels;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic boolean equals(final Object o) {\n\t\t\tif (o == this) return true;\n\t\t\tif (!(o instanceof SavedData)) return false;\n\t\t\tfinal SavedData other = (SavedData) o;\n\t\t\tif (!other.canEqual(this)) return false;\n\t\t\tfinal Object this$channels = this.getChannels();\n\t\t\tfinal Object other$channels = other.getChannels();\n\t\t\treturn Objects.equals(this$channels, other$channels);\n\t\t}\n\n\t\tprotected boolean canEqual(final Object other) {\n\t\t\treturn other instanceof SavedData;\n\t\t}\n\n\t\tpublic int hashCode() {\n\t\t\tfinal int PRIME = 59;\n\t\t\tint result = 1;\n\t\t\tfinal Object $channels = this.getChannels();\n\t\t\tresult = result * PRIME + ($channels == null ? 43 : $channels.hashCode());\n\t\t\treturn result;\n\t\t}\n\n\t\tpublic String toString() {\n\t\t\treturn \"ChannelManager.SavedData(channels=\" + this.getChannels() + \")\";\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/channels/ChannelManagerProvider.java",
    "content": "package logisticspipes.routing.channels;\n\nimport java.lang.ref.WeakReference;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.common.MinecraftForge;\nimport net.minecraftforge.event.world.WorldEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\n\nimport logisticspipes.interfaces.routing.IChannelManager;\nimport logisticspipes.interfaces.routing.IChannelManagerProvider;\n\npublic class ChannelManagerProvider implements IChannelManagerProvider {\n\n\tprivate WeakReference<World> worldWeakReference = null;\n\tprivate ChannelManager channelManager = null;\n\n\tpublic ChannelManagerProvider() {\n\t\tMinecraftForge.EVENT_BUS.register(this);\n\t}\n\n\t@Override\n\tpublic IChannelManager getChannelManager(@Nonnull World world) {\n\t\tif (worldWeakReference == null || worldWeakReference.get() == null || channelManager == null) {\n\t\t\tworldWeakReference = new WeakReference<>(world);\n\t\t\tif (channelManager != null) {\n\t\t\t\tchannelManager.markDirty();\n\t\t\t}\n\t\t\tchannelManager = new ChannelManager(world);\n\t\t}\n\t\treturn channelManager;\n\t}\n\n\t@SubscribeEvent\n\tpublic void onWorldUnload(WorldEvent.Unload worldEvent) {\n\t\tif (worldWeakReference != null) {\n\t\t\tif (worldWeakReference.get() == null || worldWeakReference.get() == worldEvent.getWorld()) {\n\t\t\t\tchannelManager = null;\n\t\t\t\tworldWeakReference = null;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/ClientViewController.java",
    "content": "package logisticspipes.routing.debug;\n\nimport java.awt.Color;\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\nimport logisticspipes.interfaces.IDebugHUDProvider;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateCanidatePipe;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDebugCanidateList;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDebugClosedSet;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDebugFilters;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDoneDebug;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateInitDebug;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateSourcePipe;\nimport logisticspipes.pipefxhandlers.Particles;\nimport logisticspipes.pipefxhandlers.PipeFXRenderHandler;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class ClientViewController implements IDebugHUDProvider {\n\n\tprivate static ClientViewController instance;\n\n\tprivate ClientViewController() {}\n\n\tprivate DoubleCoordinates mainPipe = null;\n\tprivate int tick = 0;\n\tprivate final List<DoubleCoordinates> canidates = new ArrayList<>();\n\tprivate DebugWindow debugWindow;\n\n\tprivate List<IHeadUpDisplayRendererProvider> listHUD = new ArrayList<>();\n\tprivate HashMap<DoubleCoordinates, DebugInformation> HUDPositions = new HashMap<>();\n\n\tpublic static class DebugInformation {\n\n\t\tpublic boolean isNew = false;\n\t\tpublic int newIndex = -1;\n\t\tpublic List<Integer> positions = new ArrayList<>();\n\t\tpublic List<ExitRoute> routes = new ArrayList<>();\n\t\tpublic EnumSet<PipeRoutingConnectionType> closedSet;\n\t\tpublic EnumMap<PipeRoutingConnectionType, List<List<DoubleCoordinates>>> filters;\n\t\tpublic EnumSet<PipeRoutingConnectionType> nextFlags;\n\t}\n\n\tpublic static ClientViewController instance() {\n\t\tif (ClientViewController.instance == null) {\n\t\t\tClientViewController.instance = new ClientViewController();\n\t\t}\n\t\treturn ClientViewController.instance;\n\t}\n\n\tprivate DebugInformation getDebugInformation(DoubleCoordinates pos) {\n\t\tDebugInformation info = HUDPositions.get(pos);\n\t\tif (info == null) {\n\t\t\tinfo = new DebugInformation();\n\t\t\tHUDPositions.put(pos, info);\n\t\t}\n\t\treturn info;\n\t}\n\n\tpublic void tick() {\n\t\tif (tick++ % 5 != 0) {\n\t\t\treturn;\n\t\t}\n\t\tif (mainPipe != null) {\n\t\t\tPipeFXRenderHandler.spawnGenericParticle(Particles.WhiteParticle, mainPipe.getXInt(), mainPipe.getYInt(), mainPipe.getZInt(), 1);\n\t\t}\n\t\tfor (DoubleCoordinates pos : canidates) {\n\t\t\tPipeFXRenderHandler.spawnGenericParticle(Particles.OrangeParticle, pos.getXInt(), pos.getYInt(), pos.getZInt(), 1);\n\t\t}\n\t}\n\n\tpublic void clear() {\n\t\tmainPipe = null;\n\t\tcanidates.clear();\n\t\tlistHUD.clear();\n\t\tHUDPositions.clear();\n\t}\n\n\tpublic void handlePacket(RoutingUpdateSourcePipe routingUpdateSourcePipe) {\n\t\tmainPipe = routingUpdateSourcePipe.getExitRoute().destination.getLPPosition();\n\t\tgetDebugInformation(mainPipe).nextFlags = routingUpdateSourcePipe.getExitRoute().getFlags();\n\t}\n\n\tpublic void handlePacket(RoutingUpdateCanidatePipe routingUpdateCanidatePipe) {\n\t\tDoubleCoordinates pos = routingUpdateCanidatePipe.getExitRoute().destination.getLPPosition();\n\t\tcanidates.add(routingUpdateCanidatePipe.getExitRoute().destination.getLPPosition());\n\t\t//listHUD.add(new HUDRoutingTableDebugProvider(new HUDRoutingTableNewCandateUntrace(routingUpdateCanidatePipe.getExitRoute()), pos));\n\t\tgetDebugInformation(pos).isNew = true;\n\t\tgetDebugInformation(pos).newIndex = routingUpdateCanidatePipe.getExitRoute().debug.index;\n\t}\n\n\tpublic void init(RoutingUpdateInitDebug routingUpdateInitDebug) {\n\t\tdebugWindow = new DebugWindow(\"Debug Code\", 500, 250);\n\t\tLogisticsHUDRenderer.instance().debugHUD = this;\n\t}\n\n\tpublic void done(RoutingUpdateDoneDebug routingUpdateDoneDebug) {\n\t\tif (debugWindow != null) {\n\t\t\tdebugWindow.setVisible(false);\n\t\t\tdebugWindow = null;\n\t\t}\n\t\tLogisticsHUDRenderer.instance().debugHUD = null;\n\t\tlistHUD.clear();\n\t\tHUDPositions.clear();\n\t}\n\n\tpublic void handlePacket(RoutingUpdateDebugClosedSet routingUpdateDebugClosedSet) {\n\t\tgetDebugInformation(routingUpdateDebugClosedSet.getPos()).closedSet = routingUpdateDebugClosedSet.getSet();\n\t}\n\n\tpublic void handlePacket(RoutingUpdateDebugFilters routingUpdateDebugFilters) {\n\t\tgetDebugInformation(routingUpdateDebugFilters.getPos()).filters = routingUpdateDebugFilters.getFilterPositions();\n\t}\n\n\tpublic void updateList(RoutingUpdateDebugCanidateList routingUpdateDebugCanidateList) {\n\t\tdebugWindow.clear();\n\t\tint i = 0;\n\t\tfor (ExitRoute exit : routingUpdateDebugCanidateList.getExitRoutes()) {\n\t\t\ti++;\n\t\t\tColor color = Color.BLACK;\n\t\t\tif (exit.debug.isNewlyAddedCanidate) {\n\t\t\t\tcolor = Color.BLUE;\n\t\t\t}\n\t\t\tdebugWindow.showInfo(exit.destination.toString(), color);\n\t\t\tdebugWindow.showInfo(\"\\n\", color);\n\t\t\tfor (int j = 0; j < 2; j++) {\n\t\t\t\tdebugWindow.showInfo(\"\\t\", color);\n\t\t\t}\n\t\t\tdebugWindow.showInfo(exit.debug.toStringNetwork, color);\n\t\t\tdebugWindow.showInfo(\"\\n\", color);\n\t\t\tDoubleCoordinates pos = exit.destination.getLPPosition();\n\t\t\tgetDebugInformation(pos).routes.add(exit);\n\t\t\tgetDebugInformation(pos).positions.add(i);\n\t\t}\n\t\tlistHUD.addAll(HUDPositions.entrySet().stream()\n\t\t\t\t.map(entry -> new HUDRoutingTableDebugProvider(new HUDRoutingTableGeneralInfo(entry.getValue()), entry.getKey()))\n\t\t\t\t.collect(Collectors.toList()));\n\t}\n\n\t@Override\n\tpublic List<IHeadUpDisplayRendererProvider> getHUDs() {\n\t\treturn listHUD;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/DebugController.java",
    "content": "package logisticspipes.routing.debug;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.EnumMap;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.PriorityQueue;\n\nimport net.minecraft.command.ICommandSender;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.commands.chathelper.LPChatListener;\nimport logisticspipes.interfaces.IRoutingDebugAdapter;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.OpenChatGui;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateCanidatePipe;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateClearClient;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDebugCanidateList;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDebugClosedSet;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDebugFilters;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateDoneDebug;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateInitDebug;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateSourcePipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.ServerRouter;\nimport logisticspipes.ticks.QueuedTasks;\n\npublic class DebugController implements IRoutingDebugAdapter {\n\n\tprivate static HashMap<ICommandSender, DebugController> instances = new HashMap<>();\n\tpublic List<WeakReference<ExitRoute>> cachedRoutes = new LinkedList<>();\n\n\tprivate final ICommandSender sender;\n\n\tprivate DebugController(ICommandSender sender) {\n\t\tthis.sender = sender;\n\t}\n\n\tpublic static DebugController instance(ICommandSender sender) {\n\t\tif (DebugController.instances.get(sender) == null) {\n\t\t\tDebugController.instances.put(sender, new DebugController(sender));\n\t\t}\n\t\treturn DebugController.instances.get(sender);\n\t}\n\n\tprivate enum DebugWaitState {\n\t\tLOOP,\n\t\tCONTINUE,\n\t\tNOWAIT\n\t}\n\n\tprivate Thread oldThread = null;\n\tprivate DebugWaitState state;\n\tprivate ExitRoute prevNode = null;\n\tprivate ExitRoute nextNode = null;\n\tprivate boolean pipeHandled = false;\n\tprivate PriorityQueue<ExitRoute> candidatesCost = null;\n\tprivate ArrayList<EnumSet<PipeRoutingConnectionType>> closedSet = null;\n\tprivate ArrayList<EnumMap<PipeRoutingConnectionType, List<List<IFilter>>>> filterList = null;\n\n\tpublic void debug(final ServerRouter serverRouter) {\n\t\tQueuedTasks.queueTask(() -> {\n\t\t\tstate = DebugWaitState.LOOP;\n\t\t\tThread tmp = new Thread() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\twhile (LPChatListener.existTaskFor(sender.getDisplayName().getUnformattedText())) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tThread.sleep(10);\n\t\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\t\te.printStackTrace();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t\t\t\tif (oldThread != null) {\n\t\t\t\t\t\toldThread.stop();\n\t\t\t\t\t}\n\t\t\t\t\toldThread = new RoutingTableDebugUpdateThread() {\n\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\t\tserverRouter.CreateRouteTable(0, DebugController.this);\n\t\t\t\t\t\t\toldThread = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\toldThread.setDaemon(true);\n\t\t\t\t\toldThread.setName(\"RoutingTable update debug Thread\");\n\t\t\t\t\toldThread.start();\n\t\t\t\t}\n\t\t\t};\n\t\t\ttmp.setDaemon(true);\n\t\t\ttmp.start();\n\t\t\treturn null;\n\t\t});\n\t}\n\n\tprivate void sendMsg(String message) {\n\t\tsender.sendMessage(new TextComponentString(message));\n\t}\n\n\tprivate synchronized void wait(final String reson, boolean flag) {\n\t\tif (state == DebugWaitState.NOWAIT) {\n\t\t\treturn;\n\t\t}\n\t\tstate = DebugWaitState.LOOP;\n\t\tQueuedTasks.queueTask(() -> {\n\t\t\tsender.sendMessage(new TextComponentString(reson));\n\t\t\tLPChatListener.addTask(() -> {\n\t\t\t\tstate = DebugWaitState.CONTINUE;\n\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(OpenChatGui.class), (EntityPlayer) sender);\n\t\t\t\treturn true;\n\t\t\t}, sender);\n\t\t\treturn null;\n\t\t});\n\t\tboolean exist = false;\n\t\twhile (state == DebugWaitState.LOOP) {\n\t\t\tif (LPChatListener.existTaskFor(sender.getDisplayName().getUnformattedText())) {\n\t\t\t\texist = true;\n\t\t\t} else {\n\t\t\t\tif (exist) {\n\t\t\t\t\tstate = DebugWaitState.NOWAIT;\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tThread.sleep(10);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void start(PriorityQueue<ExitRoute> candidatesCost, ArrayList<EnumSet<PipeRoutingConnectionType>> closedSet, ArrayList<EnumMap<PipeRoutingConnectionType, List<List<IFilter>>>> filterList) {\n\t\tthis.candidatesCost = candidatesCost;\n\t\tthis.closedSet = closedSet;\n\t\tthis.filterList = filterList;\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugCanidateList.class).setExitRoutes(new ArrayList<>(candidatesCost)), (EntityPlayer) sender);\n\t\twait(\"Start?\", true);\n\t}\n\n\t@Override\n\tpublic void nextPipe(ExitRoute lowestCostNode) {\n\t\tnextNode = lowestCostNode;\n\t\tif (!pipeHandled) {\n\t\t\thandledPipe(true);\n\t\t}\n\t\tpipeHandled = false;\n\t\tprevNode = lowestCostNode;\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateClearClient.class), (EntityPlayer) sender);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateSourcePipe.class).setExitRoute(lowestCostNode), (EntityPlayer) sender);\n\t}\n\n\t@Override\n\tpublic void handledPipe() {\n\t\thandledPipe(false);\n\t}\n\n\tpublic void handledPipe(boolean flag) {\n\t\tfor (int i = 0; i < closedSet.size(); i++) {\n\t\t\tEnumSet<PipeRoutingConnectionType> set = closedSet.get(i);\n\t\t\tif (set != null) {\n\t\t\t\tIRouter router = SimpleServiceLocator.routerManager.getRouter(i);\n\t\t\t\tif (router != null) {\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugClosedSet.class).setPos(router.getLPPosition()).setSet(set), (EntityPlayer) sender);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (int i = 0; i < filterList.size(); i++) {\n\t\t\tEnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters = filterList.get(i);\n\t\t\tif (filters != null) {\n\t\t\t\tIRouter router = SimpleServiceLocator.routerManager.getRouter(i);\n\t\t\t\tif (router != null) {\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugFilters.class).setPos(router.getLPPosition()).setFilters(filters), (EntityPlayer) sender);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tLinkedList<ExitRoute> exitRoutes = new LinkedList<>(candidatesCost);\n\t\tif (flag) {\n\t\t\texitRoutes.addFirst(nextNode);\n\t\t}\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugCanidateList.class).setExitRoutes(exitRoutes), (EntityPlayer) sender);\n\t\tif (prevNode == null || prevNode.debug.isTraced) {\n\t\t\t//Display Information On Client Side\n\n\t\t\twait(\"Continue with next pipe?\", false);\n\t\t}\n\t\tpipeHandled = true;\n\t}\n\n\t@Override\n\tpublic void newCanidate(ExitRoute next) {\n\t\tnext.debug.index = cachedRoutes.size();\n\t\tcachedRoutes.add(new WeakReference<>(next));\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateCanidatePipe.class).setExitRoute(next), (EntityPlayer) sender);\n\t}\n\n\t@Override\n\tpublic void stepOneDone() {\n\t\tsendMsg(\"Step One Finished\");\n\t}\n\n\t@Override\n\tpublic void stepTwoDone() {\n\t\tsendMsg(\"Step Two Finished\");\n\t}\n\n\t@Override\n\tpublic void done() {\n\t\tsendMsg(\"Update Done\");\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateClearClient.class), (EntityPlayer) sender);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDoneDebug.class), (EntityPlayer) sender);\n\t\tcachedRoutes.clear();\n\t}\n\n\t@Override\n\tpublic void init() {\n\t\tsendMsg(\"Initialising variables\");\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateInitDebug.class), (EntityPlayer) sender);\n\t}\n\n\t@Override\n\tpublic void newFlagsForPipe(EnumSet<PipeRoutingConnectionType> newFlags) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\tpublic void filterList(EnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters) {\n\t\t// TODO Auto-generated method stub\n\n\t}\n\n\t@Override\n\tpublic boolean independent() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean isDebug() {\n\t\treturn true;\n\t}\n\n\tpublic void untrace(int integer) {\n\t\tWeakReference<ExitRoute> ref = cachedRoutes.get(integer);\n\t\tif (ref != null && ref.get() != null) {\n\t\t\tref.get().debug.isTraced = false;\n\t\t\tSystem.out.println(\"Did Untrack: \" + ref.get().destination.getLPPosition());\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/DebugWindow.java",
    "content": "package logisticspipes.routing.debug;\n\nimport java.awt.Color;\nimport javax.swing.JFrame;\nimport javax.swing.JScrollPane;\nimport javax.swing.JTextPane;\nimport javax.swing.text.BadLocationException;\nimport javax.swing.text.Document;\nimport javax.swing.text.SimpleAttributeSet;\nimport javax.swing.text.StyleConstants;\n\npublic class DebugWindow extends JFrame {\n\n\tprivate int width;\n\tprivate int height;\n\tprivate JTextPane textArea;\n\n\tpublic DebugWindow(String title, int width, int height) {\n\t\tsuper(title);\n\t\tsetSize(width, height);\n\t\ttextArea = new JTextPane();\n\t\tJScrollPane pane = new JScrollPane(textArea);\n\t\tgetContentPane().add(pane);\n\t\tsetVisible(true);\n\t}\n\n\tpublic void showInfo(String data, Color color) {\n\t\tSimpleAttributeSet attr = new SimpleAttributeSet();\n\t\tStyleConstants.setFontFamily(attr, \"SansSerif\");\n\t\tStyleConstants.setFontSize(attr, 12);\n\t\tStyleConstants.setForeground(attr, color);\n\t\tDocument document = textArea.getDocument();\n\t\tif (document != null) {\n\t\t\ttry {\n\t\t\t\tdocument.insertString(document.getLength(), data, attr);\n\t\t\t} catch (BadLocationException ignored) {}\n\t\t}\n\t\tgetContentPane().validate();\n\t}\n\n\tpublic void clear() {\n\t\ttextArea.setText(\"\");\n\t\tgetContentPane().validate();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/ExitRouteDebug.java",
    "content": "package logisticspipes.routing.debug;\n\nimport java.util.List;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class ExitRouteDebug {\n\n\tpublic List<DoubleCoordinates> filterPosition = null;\n\tpublic String toStringNetwork = null;\n\tpublic boolean isNewlyAddedCanidate = true;\n\tpublic boolean isTraced = true;\n\tpublic int index = -1;\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/HUDRoutingTableDebugProvider.java",
    "content": "package logisticspipes.routing.debug;\n\nimport net.minecraft.world.World;\n\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.interfaces.IHeadUpDisplayRendererProvider;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class HUDRoutingTableDebugProvider implements IHeadUpDisplayRendererProvider {\n\n\tprivate final IHeadUpDisplayRenderer hud;\n\tprivate final DoubleCoordinates pos;\n\n\tHUDRoutingTableDebugProvider(IHeadUpDisplayRenderer hud, DoubleCoordinates pos) {\n\t\tthis.hud = hud;\n\t\tthis.pos = pos;\n\t}\n\n\t@Override\n\tpublic IHeadUpDisplayRenderer getRenderer() {\n\t\treturn hud;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn pos.getXInt();\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn pos.getYInt();\n\t}\n\n\t@Override\n\tpublic int getZ() {\n\t\treturn pos.getZInt();\n\t}\n\n\t@Override\n\tpublic World getWorldForHUD() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void startWatching() {}\n\n\t@Override\n\tpublic void stopWatching() {}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/HUDRoutingTableGeneralInfo.java",
    "content": "package logisticspipes.routing.debug;\n\nimport net.minecraft.client.Minecraft;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.gui.hud.BasicHUDGui;\nimport logisticspipes.interfaces.IHUDConfig;\nimport logisticspipes.interfaces.IHeadUpDisplayRenderer;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.routingdebug.RoutingUpdateUntrace;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.debug.ClientViewController.DebugInformation;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.hud.BasicHUDButton;\n\npublic class HUDRoutingTableGeneralInfo extends BasicHUDGui implements IHeadUpDisplayRenderer {\n\n\tprivate final DebugInformation route;\n\tprivate boolean isQuestion = false;\n\tprivate boolean display = true;\n\tprivate int line;\n\n\tHUDRoutingTableGeneralInfo(DebugInformation route) {\n\t\tthis.route = route;\n\t\tif (route.isNew) {\n\t\t\taddUntraceButtons(route.newIndex);\n\t\t}\n\n\t}\n\n\tprivate void addUntraceButtons(final int index) {\n\t\taddButton(new BasicHUDButton(\"Untrack\", -25, -75, 50, 10) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn !isQuestion && display;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tisQuestion = true;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn !isQuestion && display;\n\t\t\t}\n\t\t});\n\n\t\taddButton(new BasicHUDButton(\"Yes\", -45, -75, 30, 10) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn isQuestion && display;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(RoutingUpdateUntrace.class).setInteger(index));\n\t\t\t\tdisplay = false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn isQuestion && display;\n\t\t\t}\n\t\t});\n\t\taddButton(new BasicHUDButton(\"No\", 15, -75, 30, 10) {\n\n\t\t\t@Override\n\t\t\tpublic boolean shouldRenderButton() {\n\t\t\t\treturn isQuestion && display;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void clicked() {\n\t\t\t\tisQuestion = false;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean buttonEnabled() {\n\t\t\t\treturn isQuestion && display;\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void renderHeadUpDisplay(double distance, boolean day, boolean shifted, Minecraft mc, IHUDConfig config) {\n\t\tif (route.isNew) {\n\t\t\tline = -65;\n\t\t} else {\n\t\t\tline = -75;\n\t\t}\n\t\tGL11.glColor4b((byte) 127, (byte) 127, (byte) 127, (byte) 64);\n\t\tGuiGraphics.drawGuiBackGround(mc, -70, -80, 70, 80, 0, false);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.0005F);\n\t\tsuper.renderHeadUpDisplay(distance, day, shifted, mc, config);\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.0005F);\n\t\twrite(\"Routing Update in: \", mc);\n\t\twrite(route.positions.toString(), mc);\n\t\tif (route.closedSet != null) {\n\t\t\tint left = -55;\n\t\t\tfor (PipeRoutingConnectionType flag : PipeRoutingConnectionType.values) {\n\t\t\t\tif (route.closedSet.contains(flag)) {\n\t\t\t\t\tmc.fontRenderer.drawString(\"+\", left, line, getColorForFlag(flag));\n\t\t\t\t\tleft += mc.fontRenderer.getStringWidth(\"+\");\n\t\t\t\t} else {\n\t\t\t\t\tmc.fontRenderer.drawString(\"-\", left, line, getColorForFlag(flag));\n\t\t\t\t\tleft += mc.fontRenderer.getStringWidth(\"-\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tline += 10;\n\t\t}\n\t\tif (route.routes != null) {\n\t\t\tfor (ExitRoute exit : route.routes) {\n\t\t\t\tmc.fontRenderer.drawString(\"Possible: \", -55, line, 0xffffff);\n\t\t\t\tint left = -55 + mc.fontRenderer.getStringWidth(\"Possible: \");\n\t\t\t\tfor (PipeRoutingConnectionType flag : PipeRoutingConnectionType.values) {\n\t\t\t\t\tif (exit.containsFlag(flag)) {\n\t\t\t\t\t\tmc.fontRenderer.drawString(\"+\", left, line, getColorForFlag(flag));\n\t\t\t\t\t\tleft += mc.fontRenderer.getStringWidth(\"+\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmc.fontRenderer.drawString(\"-\", left, line, getColorForFlag(flag));\n\t\t\t\t\t\tleft += mc.fontRenderer.getStringWidth(\"-\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tline += 10;\n\t\t\t\twrite(\"  \" + exit.debug.filterPosition, mc);\n\t\t\t}\n\t\t}\n\t\tGL11.glTranslatef(0.0F, 0.0F, 0.0010F);\n\t}\n\n\tprivate int getColorForFlag(PipeRoutingConnectionType type) {\n\t\tswitch (type) {\n\t\t\tcase canRouteTo:\n\t\t\t\treturn 0xff0000;\n\t\t\tcase canRequestFrom:\n\t\t\t\treturn 0x00ff00;\n\t\t\tcase canPowerFrom:\n\t\t\t\treturn 0x00ffff;\n\t\t\tcase canPowerSubSystemFrom:\n\t\t\t\treturn 0x0000ff;\n\t\t}\n\t\treturn 0x000000;\n\t}\n\n\tprivate void write(String data, Minecraft mc) {\n\t\tmc.fontRenderer.drawString(data, -55, line, 0xffffff);\n\t\tline += 10;\n\t}\n\n\t@Override\n\tpublic boolean display(IHUDConfig config) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean cursorOnWindow(int x, int y) {\n\t\treturn -70 < x && x < 70 && -80 < y && y < 80;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/debug/RoutingTableDebugUpdateThread.java",
    "content": "package logisticspipes.routing.debug;\n\npublic class RoutingTableDebugUpdateThread extends Thread {\n\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/ClientSideOrderInfo.java",
    "content": "package logisticspipes.routing.order;\n\nimport java.util.List;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.Getter;\n\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@SideOnly(Side.CLIENT)\npublic class ClientSideOrderInfo implements IOrderInfoProvider {\n\n\t@Getter\n\tprivate final ItemIdentifierStack asDisplayItem;\n\t@Getter\n\tprivate final boolean isFinished;\n\t@Getter\n\tprivate final ResourceType type;\n\t@Getter\n\tprivate final boolean inProgress;\n\t@Getter\n\tprivate final int routerId;\n\t@Getter\n\tprivate final boolean isWatched = false;\n\t@Getter\n\tprivate final List<Float> progresses;\n\t@Getter\n\tprivate final byte machineProgress;\n\t@Getter\n\tprivate final DoubleCoordinates targetPosition;\n\t@Getter\n\tprivate final ItemIdentifier targetType;\n\n\tpublic ClientSideOrderInfo(LPDataInput input) {\n\t\tasDisplayItem = input.readItemIdentifierStack();\n\t\trouterId = input.readInt();\n\t\tisFinished = input.readBoolean();\n\t\tinProgress = input.readBoolean();\n\t\ttype = input.readEnum(IOrderInfoProvider.ResourceType.class);\n\t\tprogresses = input.readArrayList(LPDataInput::readFloat);\n\t\tmachineProgress = input.readByte();\n\t\tif (input.readBoolean()) {\n\t\t\ttargetPosition = new DoubleCoordinates(input);\n\t\t\ttargetType = input.readItemIdentifier();\n\t\t} else {\n\t\t\ttargetPosition = null;\n\t\t\ttargetType = null;\n\t\t}\n\t}\n\n\t//Ignore this call\n\t@Override\n\tpublic void setWatched() {}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/DistanceTracker.java",
    "content": "package logisticspipes.routing.order;\n\nimport logisticspipes.proxy.MainProxy;\n\npublic class DistanceTracker implements IDistanceTracker {\n\n\tprivate int currentDistance = 0;\n\tprivate int initialDistance = 0;\n\tprivate boolean endReached = false;\n\tprivate long delay = 0;\n\n\t@Override\n\tpublic void setCurrentDistanceToTarget(int value) {\n\t\tif (initialDistance == 0) {\n\t\t\tinitialDistance = value;\n\t\t}\n\t\tcurrentDistance = value;\n\t}\n\n\t@Override\n\tpublic int getCurrentDistanceToTarget() {\n\t\treturn currentDistance;\n\t}\n\n\t@Override\n\tpublic int getInitialDistanceToTarget() {\n\t\treturn initialDistance;\n\t}\n\n\t@Override\n\tpublic void setDestinationReached() {\n\t\tendReached = true;\n\t}\n\n\t@Override\n\tpublic boolean hasReachedDestination() {\n\t\treturn endReached;\n\t}\n\n\t@Override\n\tpublic void setDelay(long delay) {\n\t\tthis.delay = delay;\n\t}\n\n\t@Override\n\tpublic boolean isTimeout() {\n\t\treturn delay != 0 && delay <= MainProxy.getGlobalTick();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/IDistanceTracker.java",
    "content": "package logisticspipes.routing.order;\n\npublic interface IDistanceTracker {\n\n\tvoid setCurrentDistanceToTarget(int value);\n\n\tint getCurrentDistanceToTarget();\n\n\tint getInitialDistanceToTarget();\n\n\tvoid setDestinationReached();\n\n\tboolean hasReachedDestination();\n\n\tvoid setDelay(long delay);\n\n\tboolean isTimeout();\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/IOrderInfoProvider.java",
    "content": "package logisticspipes.routing.order;\n\nimport java.util.List;\n\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.LPFinalSerializable;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface IOrderInfoProvider extends LPFinalSerializable {\n\n\tboolean isFinished();\n\n\tItemIdentifierStack getAsDisplayItem();\n\n\tResourceType getType();\n\n\tint getRouterId();\n\n\tboolean isInProgress();\n\n\tboolean isWatched();\n\n\tvoid setWatched();\n\n\tList<Float> getProgresses();\n\n\tbyte getMachineProgress();\n\n\tItemIdentifier getTargetType();\n\n\tDoubleCoordinates getTargetPosition();\n\n\t@Override\n\tdefault void write(LPDataOutput output) {\n\t\toutput.writeItemIdentifierStack(getAsDisplayItem());\n\t\toutput.writeInt(getRouterId());\n\t\toutput.writeBoolean(isFinished());\n\t\toutput.writeBoolean(isInProgress());\n\t\toutput.writeEnum(getType());\n\t\toutput.writeCollection(getProgresses(), LPDataOutput::writeFloat);\n\t\toutput.writeByte(getMachineProgress());\n\t\tif (getTargetPosition() != null) {\n\t\t\toutput.writeBoolean(true);\n\t\t\toutput.writeSerializable(getTargetPosition());\n\t\t\toutput.writeItemIdentifier(getTargetType());\n\t\t} else {\n\t\t\toutput.writeBoolean(false);\n\t\t}\n\t}\n\n\tenum ResourceType {\n\t\tPROVIDER,\n\t\tCRAFTING,\n\t\tEXTRA\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LinkedLogisticsOrderList.java",
    "content": "package logisticspipes.routing.order;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.Getter;\n\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.LPFinalSerializable;\n\npublic class LinkedLogisticsOrderList extends ArrayList<IOrderInfoProvider> implements LPFinalSerializable {\n\n\tprivate static final long serialVersionUID = 4328359512757178338L;\n\n\t@Getter\n\tprivate List<LinkedLogisticsOrderList> subOrders = new ArrayList<>();\n\n\tprivate List<IOrderInfoProvider> cachedList = null;\n\tprivate List<Float> cachedProgress = null;\n\n\tpublic LinkedLogisticsOrderList() { }\n\n\tpublic LinkedLogisticsOrderList(LPDataInput input) {\n\t\tList<IOrderInfoProvider> orderInfoProviders = input.readArrayList(ClientSideOrderInfo::new);\n\t\tif (orderInfoProviders == null) {\n\t\t\tthrow new NullPointerException(\"Null order info providers read\");\n\t\t}\n\t\tthis.addAll(orderInfoProviders);\n\n\t\tList<LinkedLogisticsOrderList> orderLists = input.readArrayList(LinkedLogisticsOrderList::new);\n\t\tif (orderLists == null) {\n\t\t\tthrow new NullPointerException(\"Null order lists read\");\n\t\t}\n\t\tsubOrders.addAll(orderLists);\n\t}\n\n\t@Override\n\tpublic void write(LPDataOutput output) {\n\t\toutput.writeCollection(this);\n\t\toutput.writeCollection(subOrders);\n\t}\n\n\tprivate void generateCache() {\n\t\tcachedList = new ArrayList<>();\n\t\tcachedList.addAll(this);\n\t\tfor (LinkedLogisticsOrderList sub : subOrders) {\n\t\t\tcachedList.addAll(sub.getList());\n\t\t}\n\t}\n\n\tpublic List<IOrderInfoProvider> getList() {\n\t\tif (cachedList == null) {\n\t\t\tgenerateCache();\n\t\t}\n\t\treturn cachedList;\n\t}\n\n\tpublic int getTreeRootSize() {\n\t\tint subSize = 0;\n\t\tfor (LinkedLogisticsOrderList sub : subOrders) {\n\t\t\tsubSize += sub.getTreeRootSize();\n\t\t}\n\t\treturn Math.max(size(), subSize);\n\t}\n\n\tpublic int getSubTreeRootSize() {\n\t\tint subSize = 0;\n\t\tfor (LinkedLogisticsOrderList sub : subOrders) {\n\t\t\tsubSize += sub.getTreeRootSize();\n\t\t}\n\t\treturn subSize;\n\t}\n\n\tpublic void setWatched() {\n\t\tthis.forEach(IOrderInfoProvider::setWatched);\n\t\tsubOrders.forEach(LinkedLogisticsOrderList::setWatched);\n\t}\n\n\tprivate void createProgressCache() {\n\t\tcachedProgress = new ArrayList<>();\n\t\tfor (IOrderInfoProvider order : this) {\n\t\t\torder.getProgresses().stream().filter(n -> !cachedProgress.contains(n)).forEach(n -> cachedProgress.add(n));\n\t\t}\n\t}\n\n\tpublic List<Float> getProgresses() {\n\t\tif (cachedProgress == null) {\n\t\t\tcreateProgressCache();\n\t\t}\n\t\treturn cachedProgress;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsFluidOrder.java",
    "content": "package logisticspipes.routing.order;\n\nimport javax.annotation.Nonnull;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class LogisticsFluidOrder extends LogisticsOrder {\n\n\tpublic LogisticsFluidOrder(FluidIdentifier fuild, Integer amount, IRequestFluid destination, ResourceType type, IAdditionalTargetInformation info) {\n\t\tsuper(type, info);\n\t\tif (destination == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\tfluid = fuild;\n\t\tthis.amount = amount;\n\t\tthis.destination = destination;\n\t}\n\n\t@Getter\n\tprivate final FluidIdentifier fluid;\n\t@Getter\n\tprivate int amount;\n\tprivate final IRequestFluid destination;\n\n\t@Override\n\tpublic ItemIdentifierStack getAsDisplayItem() {\n\t\treturn fluid.getItemIdentifier().makeStack(amount);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic IRouter getRouter() {\n\t\treturn destination.getRouter();\n\t}\n\n\t@Override\n\tpublic void sendFailed() {\n\t\tdestination.sendFailed(fluid, amount);\n\t}\n\n\t@Override\n\tpublic void reduceAmountBy(int reduce) {\n\t\tamount -= reduce;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsFluidOrderManager.java",
    "content": "package logisticspipes.routing.order;\n\nimport logisticspipes.interfaces.IChangeListener;\nimport logisticspipes.interfaces.ILPPositionProvider;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestFluid;\nimport logisticspipes.routing.FluidLogisticsPromise;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.FluidIdentifier;\n\npublic class LogisticsFluidOrderManager extends LogisticsOrderManager<LogisticsFluidOrder, FluidIdentifier> {\n\n\tprivate static class IC implements LogisticsOrderLinkedList.IIdentityProvider<LogisticsFluidOrder, FluidIdentifier> {\n\n\t\t@Override\n\t\tpublic FluidIdentifier getIdentity(LogisticsFluidOrder o) {\n\t\t\treturn o.getFluid();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isExtra(LogisticsFluidOrder o) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic LogisticsFluidOrderManager(ILPPositionProvider pos) {\n\t\tsuper(new LogisticsOrderLinkedList<LogisticsFluidOrder, FluidIdentifier>(new IC()), pos);\n\t}\n\n\tpublic LogisticsFluidOrderManager(IChangeListener listener, ILPPositionProvider pos) {\n\t\tsuper(listener, pos, new LogisticsOrderLinkedList<LogisticsFluidOrder, FluidIdentifier>(new IC()));\n\t}\n\n\t@Override\n\tpublic void sendFailed() {\n\t\t_orders.getFirst().sendFailed();\n\t\tsuper.sendFailed();\n\t}\n\n\tpublic LogisticsFluidOrder addOrder(FluidLogisticsPromise promise, IRequestFluid destination, ResourceType type, IAdditionalTargetInformation info) {\n\t\tif (promise.amount < 0) {\n\t\t\tthrow new RuntimeException(\"The amount can't be less than zero\");\n\t\t}\n\t\tLogisticsFluidOrder order = new LogisticsFluidOrder(promise.liquid, promise.amount, destination, type, info);\n\t\t_orders.addLast(order);\n\t\tlisten();\n\t\treturn order;\n\t}\n\n\tpublic Integer totalFluidsCountInOrders(FluidIdentifier fluid) {\n\t\tint itemCount = 0;\n\t\tfor (LogisticsFluidOrder request : _orders) {\n\t\t\tif (!request.getFluid().equals(fluid)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\titemCount += request.getAmount();\n\t\t}\n\t\treturn itemCount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsItemOrder.java",
    "content": "package logisticspipes.routing.order;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class LogisticsItemOrder extends LogisticsOrder {\n\n\tpublic LogisticsItemOrder(DictResource item, IRequestItems destination, ResourceType type, IAdditionalTargetInformation info) {\n\t\tsuper(type, info);\n\t\tif (item == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\tresource = item;\n\t\tthis.destination = destination;\n\t}\n\n\t@Getter\n\tprivate final DictResource resource;\n\t@Getter\n\tprivate final IRequestItems destination;\n\n\t@Override\n\tpublic IRouter getRouter() {\n\t\tif (destination == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn destination.getRouter();\n\t}\n\n\t@Override\n\tpublic void sendFailed() {\n\t\tif (destination == null) {\n\t\t\treturn;\n\t\t}\n\t\tdestination.itemCouldNotBeSend(getResource().stack, getInformation());\n\t}\n\n\t@Override\n\tpublic ItemIdentifierStack getAsDisplayItem() {\n\t\treturn resource.stack;\n\t}\n\n\t@Override\n\tpublic int getAmount() {\n\t\treturn resource.stack.getStackSize();\n\t}\n\n\t@Override\n\tpublic void reduceAmountBy(int amount) {\n\t\tresource.stack.setStackSize(resource.stack.getStackSize() - amount);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsItemOrderManager.java",
    "content": "package logisticspipes.routing.order;\n\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport logisticspipes.interfaces.IChangeListener;\nimport logisticspipes.interfaces.ILPPositionProvider;\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequestItems;\nimport logisticspipes.request.resources.DictResource;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class LogisticsItemOrderManager extends LogisticsOrderManager<LogisticsItemOrder, DictResource.Identifier> {\n\n\tprivate static class IC implements LogisticsOrderLinkedList.IIdentityProvider<LogisticsItemOrder, DictResource.Identifier> {\n\n\t\t@Override\n\t\tpublic DictResource.Identifier getIdentity(LogisticsItemOrder o) {\n\t\t\tif (o == null || o.getResource() == null) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn o.getResource().getIdentifier();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isExtra(LogisticsItemOrder o) {\n\t\t\treturn o instanceof LogisticsItemOrderExtra;\n\t\t}\n\t}\n\n\tprivate static class LogisticsItemOrderExtra extends LogisticsItemOrder {\n\n\t\tpublic LogisticsItemOrderExtra(DictResource item, IRequestItems destination, ResourceType type, IAdditionalTargetInformation info) {\n\t\t\tsuper(item, destination, type, info);\n\t\t}\n\t}\n\n\tpublic LogisticsItemOrderManager(ILPPositionProvider pos) {\n\t\tsuper(new LogisticsOrderLinkedList<LogisticsItemOrder, DictResource.Identifier>(new IC()), pos);\n\t}\n\n\tpublic LogisticsItemOrderManager(IChangeListener listener, ILPPositionProvider pos) {\n\t\tsuper(listener, pos, new LogisticsOrderLinkedList<LogisticsItemOrder, DictResource.Identifier>(new IC()));\n\t}\n\n\t@Override\n\tpublic void sendFailed() {\n\t\t_orders.getFirst().sendFailed();\n\t\tsuper.sendFailed();\n\t}\n\n\tpublic LogisticsItemOrder addOrder(ItemIdentifierStack stack, IRequestItems requester, ResourceType type, IAdditionalTargetInformation info) {\n\t\tLogisticsItemOrder order = new LogisticsItemOrder(new DictResource(stack, null), requester, type, info);\n\t\t_orders.addLast(order);\n\t\tlisten();\n\t\treturn order;\n\t}\n\n\tpublic LogisticsItemOrder addOrder(DictResource stack, IRequestItems requester, ResourceType type, IAdditionalTargetInformation info) {\n\t\tLogisticsItemOrder order = new LogisticsItemOrder(stack, requester, type, info);\n\t\t_orders.addLast(order);\n\t\tlisten();\n\t\treturn order;\n\t}\n\n\tpublic LogisticsItemOrderExtra addExtra(DictResource stack) {\n\t\tLogisticsItemOrderExtra order = new LogisticsItemOrderExtra(stack, null, ResourceType.EXTRA, null);\n\t\t_orders.addLast(order);\n\t\tlisten();\n\t\treturn order;\n\t}\n\n\tpublic void removeExtras(DictResource resource) {\n\t\tint itemsToRemove = resource.getRequestedAmount();\n\t\tDictResource.Identifier ident = resource.getIdentifier();\n\t\tIterator<LogisticsItemOrder> iter = _orders.iterator();\n\t\tList<LogisticsItemOrder> toRemove = new LinkedList<LogisticsItemOrder>();\n\t\twhile (iter.hasNext()) {\n\t\t\tLogisticsItemOrder order = iter.next();\n\t\t\tif (order.getType() != ResourceType.EXTRA) continue;\n\t\t\tif (order.getResource().getIdentifier().equals(ident)) {\n\t\t\t\tif (itemsToRemove >= order.getAmount()) {\n\t\t\t\t\titemsToRemove -= order.getAmount();\n\t\t\t\t\ttoRemove.add(order);\n\t\t\t\t\tif (itemsToRemove == 0) {\n\t\t\t\t\t\t_orders.removeAll(toRemove);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\torder.getResource().getItemStack().setStackSize(order.getAmount() - itemsToRemove);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t_orders.removeAll(toRemove);\n\t}\n\n\tpublic int totalItemsCountInOrders(ItemIdentifier item) {\n\t\tint itemCount = 0;\n\t\tfor (LogisticsItemOrder request : _orders) {\n\t\t\tif (!request.getResource().getItem().equals(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\titemCount += request.getResource().stack.getStackSize();\n\t\t}\n\t\treturn itemCount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsOrder.java",
    "content": "package logisticspipes.routing.order;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.Getter;\nimport lombok.Setter;\nimport lombok.experimental.Accessors;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n@Accessors(chain = true)\npublic abstract class LogisticsOrder implements IOrderInfoProvider {\n\n\tprivate static final int MIN_DISTANCE_TO_DISPLAY = 4;\n\n\t@Getter\n\tprivate final IAdditionalTargetInformation information;\n\t@Getter\n\t@Setter\n\tprivate boolean isFinished = false;\n\n\t/*\n\t * Display Information\n\t */\n\t@Getter\n\tprivate final ResourceType type;\n\t@Getter\n\t@Setter\n\tprivate boolean inProgress;\n\t@Getter\n\tprivate boolean isWatched = false;\n\t@Getter\n\t@Setter\n\tprivate byte machineProgress = 0;\n\tprivate List<IDistanceTracker> trackers = new ArrayList<>();\n\n\tpublic LogisticsOrder(ResourceType type, IAdditionalTargetInformation info) {\n\t\tif (type == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\tthis.type = type;\n\t\tinformation = info;\n\t}\n\n\t@Override\n\tpublic int getRouterId() {\n\t\tif (getRouter() == null) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn getRouter().getSimpleID();\n\t}\n\n\tpublic abstract IRouter getRouter();\n\n\t@Override\n\tpublic void setWatched() {\n\t\tisWatched = true;\n\t}\n\n\tpublic void addDistanceTracker(IDistanceTracker tracker) {\n\t\ttrackers.add(tracker);\n\t}\n\n\t@Override\n\tpublic List<Float> getProgresses() {\n\t\tList<Float> progresses = new ArrayList<>();\n\t\tfor (IDistanceTracker tracker : trackers) {\n\t\t\tif (!tracker.hasReachedDestination() && !tracker.isTimeout()) {\n\t\t\t\tfloat f;\n\t\t\t\tif (tracker.getInitialDistanceToTarget() != 0) {\n\t\t\t\t\tf = ((float) tracker.getCurrentDistanceToTarget()) / ((float) tracker.getInitialDistanceToTarget());\n\t\t\t\t} else {\n\t\t\t\t\tf = 1.0F;\n\t\t\t\t}\n\t\t\t\tif (!progresses.contains(f)) {\n\t\t\t\t\tif (tracker.getInitialDistanceToTarget() > LogisticsOrder.MIN_DISTANCE_TO_DISPLAY || tracker.getInitialDistanceToTarget() == 0) {\n\t\t\t\t\t\tprogresses.add(f);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn progresses;\n\t}\n\n\tpublic abstract void sendFailed();\n\n\tpublic abstract int getAmount();\n\n\tpublic abstract void reduceAmountBy(int amount);\n\n\t@Override\n\tpublic ItemIdentifier getTargetType() {\n\t\tif (getRouter() == null || getRouter().getPipe() == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn ItemIdentifier.get(getRouter().getPipe().item, 0, null);\n\t}\n\n\t@Override\n\tpublic DoubleCoordinates getTargetPosition() {\n\t\tif (getRouter() == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn getRouter().getLPPosition();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsOrderLinkedList.java",
    "content": "package logisticspipes.routing.order;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport javax.annotation.Nonnull;\n\npublic class LogisticsOrderLinkedList<E extends LogisticsOrder, I> implements Iterable<E> {\n\n\tprivate final IIdentityProvider<E, I> identifyer;\n\tprivate Map<I, Integer> extraSize = new HashMap<I, Integer>();\n\tprivate LinkedList<E> list = new LinkedList<E>();\n\tprivate List<E> unmodifiable = Collections.unmodifiableList(list);\n\tprivate int globalExtraCount = 0;\n\n\tpublic LogisticsOrderLinkedList(IIdentityProvider<E, I> identifyer) {\n\t\tthis.identifyer = identifyer;\n\t}\n\n\tpublic E getFirst() {\n\t\treturn list.getFirst();\n\t}\n\n\tpublic void addLast(E order) {\n\t\tlist.addLast(order);\n\t\tI ident = identifyer.getIdentity(order);\n\t\tif (identifyer.isExtra(order)) {\n\t\t\tint prev = 0;\n\t\t\tif (extraSize.containsKey(ident)) {\n\t\t\t\tprev = extraSize.get(ident);\n\t\t\t}\n\t\t\textraSize.put(ident, prev + 1);\n\t\t\tglobalExtraCount++;\n\t\t} else if (extraSize.containsKey(ident) && extraSize.get(ident) > 0) {\n\t\t\tList<E> toMove = new LinkedList<E>();\n\t\t\tfor (E lElem : list) {\n\t\t\t\tif (identifyer.isExtra(lElem) && ident.equals(identifyer.getIdentity(lElem))) {\n\t\t\t\t\ttoMove.add(lElem);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (E move : toMove) {\n\t\t\t\tlist.remove(move);\n\t\t\t\tlist.addLast(move);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void removeAll(List<E> orders) {\n\t\tlist.removeAll(orders);\n\t\tfor (E order : orders) {\n\t\t\telemRemove(order);\n\t\t}\n\t}\n\n\tprivate void elemRemove(E elem) {\n\t\tif (identifyer.isExtra(elem)) {\n\t\t\tI ident = identifyer.getIdentity(elem);\n\t\t\tint prev = 0;\n\t\t\tif (extraSize.containsKey(ident)) {\n\t\t\t\tprev = extraSize.get(ident);\n\t\t\t}\n\t\t\tif (prev > 0) {\n\t\t\t\textraSize.put(ident, prev - 1);\n\t\t\t}\n\t\t\tglobalExtraCount--;\n\t\t}\n\t}\n\n\tpublic int size() {\n\t\treturn list.size();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterator<E> iterator() {\n\t\treturn unmodifiable.iterator();\n\t}\n\n\tpublic boolean hasExtras() {\n\t\treturn globalExtraCount != 0;\n\t}\n\n\tpublic E removeFirst() {\n\t\tE elem = list.removeFirst();\n\t\telemRemove(elem);\n\t\treturn elem;\n\t}\n\n\tpublic boolean isEmpty() {\n\t\treturn list.isEmpty();\n\t}\n\n\tpublic interface IIdentityProvider<A, B> {\n\n\t\tB getIdentity(A o);\n\n\t\tboolean isExtra(A o);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/order/LogisticsOrderManager.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing.order;\n\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.world.World;\n\nimport logisticspipes.interfaces.IChangeListener;\nimport logisticspipes.interfaces.ILPPositionProvider;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.PipeManagerContentPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.routing.order.IOrderInfoProvider.ResourceType;\nimport logisticspipes.utils.PlayerCollectionList;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic abstract class LogisticsOrderManager<T extends LogisticsOrder, I> implements Iterable<T> {\n\n\tprotected final LogisticsOrderLinkedList<T, I> _orders;\n\tprotected IChangeListener listener = null;\n\tprotected PlayerCollectionList watchingPlayers = new PlayerCollectionList();\n\tprivate ILPPositionProvider pos;\n\n\tpublic LogisticsOrderManager(LogisticsOrderLinkedList<T, I> orders, ILPPositionProvider pos) {\n\t\t_orders = orders;\n\t\tthis.pos = pos;\n\t}\n\n\tpublic LogisticsOrderManager(IChangeListener listener, ILPPositionProvider pos, LogisticsOrderLinkedList<T, I> orders) {\n\t\tthis(orders, pos);\n\t\tthis.listener = listener;\n\t}\n\n\tprivate static void addToList(ItemIdentifierStack stack, LinkedList<ItemIdentifierStack> list) {\n\t\tfor (ItemIdentifierStack ident : list) {\n\t\t\tif (ident.getItem().equals(stack.getItem())) {\n\t\t\t\tident.setStackSize(ident.getStackSize() + stack.getStackSize());\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tlist.addLast(new ItemIdentifierStack(stack));\n\t}\n\n\tprotected void listen() {\n\t\tchanged();\n\t\tif (listener != null) {\n\t\t\tlistener.listenedChanged();\n\t\t}\n\t}\n\n\tpublic void dump(StringBuilder sb) {\n\t\tfor (T s : _orders) {\n\t\t\tsb.append(s.getAsDisplayItem())\n\t\t\t\t\t.append(\" / \")\n\t\t\t\t\t.append(s.getAmount())\n\t\t\t\t\t.append(\" / \")\n\t\t\t\t\t.append(s.getType().name())\n\t\t\t\t\t.append('\\n');\n\t\t}\n\t}\n\n\tpublic LinkedList<ItemIdentifierStack> getContentList(World world) {\n\t\tif (MainProxy.isClient(world) || _orders.size() == 0) {\n\t\t\treturn new LinkedList<>();\n\t\t}\n\t\tLinkedList<ItemIdentifierStack> list = new LinkedList<>();\n\t\tfor (LogisticsOrder request : _orders) {\n\t\t\tLogisticsOrderManager.addToList(request.getAsDisplayItem(), list);\n\t\t}\n\t\treturn list;\n\t}\n\n\tpublic boolean hasOrders(ResourceType... type) {\n\t\treturn peekAtTopRequest(type) != null;\n\t}\n\n\t/* only multi-access SAFE when type is null; all other access patterns may change the state of the stack so the returned element is on top*/\n\t@SuppressWarnings(\"unchecked\")\n\tpublic T peekAtTopRequest(ResourceType... type) {\n\t\tList<ResourceType> typeList = Arrays.asList(type);\n\t\tif (_orders.size() == 0) {\n\t\t\treturn null;\n\t\t}\n\t\tT top = (T) _orders.getFirst().setInProgress(true);\n\t\tint loopCount = 0;\n\t\twhile (!typeList.contains(top.getType())) {\n\t\t\tloopCount++;\n\t\t\tif (loopCount > _orders.size()) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tdeferSend(); // sets the new top to InProgress\n\t\t\ttop = _orders.getFirst();\n\t\t}\n\t\treturn top;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void sendSuccessfull(int number, boolean defersend, IRoutedItem item) {\n\t\t_orders.getFirst().reduceAmountBy(number);\n\t\tif (_orders.getFirst().isWatched() && item != null) {\n\t\t\tIDistanceTracker tracker = new DistanceTracker();\n\t\t\titem.setDistanceTracker(tracker);\n\t\t\t_orders.getFirst().addDistanceTracker(tracker);\n\t\t}\n\t\tint destination = _orders.getFirst().getRouterId();\n\t\tif (_orders.getFirst().getAmount() <= 0) {\n\t\t\tLogisticsOrder order = _orders.removeFirst();\n\t\t\torder.setFinished(true);\n\t\t\torder.setInProgress(false);\n\t\t}\n\t\tif (!_orders.isEmpty()) {\n\t\t\tLogisticsOrder start = _orders.getFirst();\n\t\t\tif (defersend && destination == start.getRouterId()) {\n\t\t\t\t_orders.addLast((T) _orders.removeFirst().setInProgress(false));\n\t\t\t\twhile (start != _orders.getFirst() && destination == _orders.getFirst().getRouterId()) {\n\t\t\t\t\t_orders.addLast(_orders.removeFirst());\n\t\t\t\t}\n\t\t\t\tif (start == _orders.getFirst()) {\n\t\t\t\t\t_orders.addLast(_orders.removeFirst());\n\t\t\t\t}\n\t\t\t\t_orders.getFirst().setInProgress(true);\n\t\t\t}\n\t\t}\n\t\tlisten();\n\t}\n\n\tpublic void sendFailed() {\n\t\tif (!_orders.isEmpty()) {\n\t\t\tLogisticsOrder order = _orders.removeFirst();\n\t\t\torder.setFinished(true);\n\t\t\torder.setInProgress(false);\n\t\t}\n\t\tif (!_orders.isEmpty()) {\n\t\t\t_orders.getFirst().setInProgress(true);\n\t\t}\n\t\tlisten();\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic void deferSend() {\n\t\t_orders.addLast((T) _orders.removeFirst().setInProgress(false));\n\t\t_orders.getFirst().setInProgress(true);\n\t\tlisten();\n\t}\n\n\tpublic int totalAmountCountInAllOrders() {\n\t\tint amount = 0;\n\t\tfor (LogisticsOrder request : _orders) {\n\t\t\tamount += request.getAmount();\n\t\t}\n\t\treturn amount;\n\t}\n\n\tpublic void setMachineProgress(byte progress) {\n\t\tif (_orders.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\t_orders.getFirst().setMachineProgress(progress);\n\t\tchanged();\n\t}\n\n\tpublic boolean isFirstOrderWatched() {\n\t\tif (_orders.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _orders.getFirst().isWatched();\n\t}\n\n\tpublic void startWatching(EntityPlayer player) {\n\t\twatchingPlayers.add(player);\n\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(PipeManagerContentPacket.class).setManager(this).setLPPos(pos.getLPPosition()), player);\n\t}\n\n\tpublic void stopWatching(EntityPlayer player) {\n\t\twatchingPlayers.remove(player);\n\t}\n\n\tpublic boolean hasExtras() {\n\t\treturn _orders.hasExtras();\n\t}\n\n\tprivate void changed() {\n\t\tif (watchingPlayers.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\t//if(!oldOrders.equals(_orders)) {\n\t\t//\toldOrders.clear();\n\t\t//\toldOrders.addAll(_orders);\n\t\tMainProxy.sendToPlayerList(PacketHandler.getPacket(PipeManagerContentPacket.class).setManager(this).setLPPos(pos.getLPPosition()), watchingPlayers);\n\t\t//}\n\t}\n\n\t/**\n\t * DON'T MODIFY TROUGH THIS ONLY READ THE VALUES\n\t */\n\t@Nonnull\n\t@Override\n\tpublic Iterator<T> iterator() {\n\t\treturn this._orders.iterator();\n\t}\n\n\tpublic int size() {\n\t\treturn _orders.size();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/pathfinder/IPipeInformationProvider.java",
    "content": "package logisticspipes.routing.pathfinder;\n\nimport java.util.List;\nimport java.util.stream.Stream;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.connection.ConnectionType;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic interface IPipeInformationProvider {\n\n\tboolean isCorrect(ConnectionType type);\n\n\tint getX();\n\n\tint getY();\n\n\tint getZ();\n\n\tWorld getWorld();\n\n\tboolean isRouterInitialized();\n\n\tboolean isRoutingPipe();\n\n\tCoreRoutedPipe getRoutingPipe();\n\n\tTileEntity getNextConnectedTile(EnumFacing direction);\n\n\tboolean isFirewallPipe();\n\n\tIFilter getFirewallFilter();\n\n\tTileEntity getTile();\n\n\tboolean divideNetwork();\n\n\tboolean powerOnly();\n\n\tboolean isOnewayPipe();\n\n\tboolean isOutputClosed(EnumFacing direction);\n\n\tboolean canConnect(TileEntity to, EnumFacing direction, boolean flag);\n\n\tdouble getDistance();\n\n\tdouble getDistanceWeight();\n\n\tboolean isItemPipe();\n\n\tboolean isFluidPipe();\n\n\tboolean isPowerPipe();\n\n\tdouble getDistanceTo(int destinationint, EnumFacing ignore, ItemIdentifier ident, boolean isActive, double travled, double max, List<DoubleCoordinates> visited);\n\n\tboolean acceptItem(LPTravelingItem item, TileEntity from);\n\n\tvoid refreshTileCacheOnSide(EnumFacing side);\n\n\tboolean isMultiBlock();\n\n\tStream<TileEntity> getPartsOfPipe();\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/pathfinder/IRouteProvider.java",
    "content": "package logisticspipes.routing.pathfinder;\n\nimport java.util.List;\n\nimport net.minecraft.util.EnumFacing;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\npublic interface IRouteProvider {\n\n\t@Data\n\t@AllArgsConstructor\n\tclass RouteInfo {\n\n\t\tprivate IPipeInformationProvider pipe;\n\t\tprivate int length;\n\t\tprivate EnumFacing exitOrientation;\n\t}\n\n\tList<RouteInfo> getConnectedPipes(EnumFacing from);\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/pathfinder/ISubMultiBlockPipeInformationProvider.java",
    "content": "package logisticspipes.routing.pathfinder;\n\npublic interface ISubMultiBlockPipeInformationProvider {\n\n\tIPipeInformationProvider getMainTile();\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/pathfinder/PathFinder.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.routing.pathfinder;\n\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map.Entry;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.asm.te.ILPTEInformation;\nimport logisticspipes.asm.te.ITileEntityChangeListener;\nimport logisticspipes.asm.te.LPTileEntityObject;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.IChannelRoutingConnection;\nimport logisticspipes.interfaces.routing.IFilter;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.specialconnection.SpecialPipeConnection.ConnectionInformation;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.IPaintPath;\nimport logisticspipes.routing.LaserData;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.routing.pathfinder.IRouteProvider.RouteInfo;\nimport logisticspipes.utils.OneList;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Quartet;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n/**\n * Examines all pipe connections and their forks to locate all connected routers\n */\npublic class PathFinder {\n\n\t/**\n\t * Recurse through all exists of a pipe to find instances of\n\t * PipeItemsRouting. maxVisited and maxLength are safeguards for recursion\n\t * runaways.\n\t *\n\t * @param startPipe\n\t *            - The TileEntity to start the search from\n\t * @param maxVisited\n\t *            - The maximum number of pipes to visit, regardless of\n\t *            recursion level\n\t * @param maxLength\n\t *            - The maximum recurse depth, i.e. the maximum length pipe that\n\t *            is supported\n\t */\n\tpublic static HashMap<CoreRoutedPipe, ExitRoute> paintAndgetConnectedRoutingPipes(TileEntity startPipe, EnumFacing startOrientation, int maxVisited, int maxLength, IPaintPath pathPainter, EnumSet<PipeRoutingConnectionType> connectionType) {\n\t\tIPipeInformationProvider startProvider = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(startPipe);\n\t\tif (startProvider == null) {\n\t\t\treturn new HashMap<>();\n\t\t}\n\t\tPathFinder newSearch = new PathFinder(maxVisited, maxLength, pathPainter);\n\t\tDoubleCoordinates p = new DoubleCoordinates(startProvider);\n\t\tnewSearch.setVisited.add(p);\n\t\tCoordinateUtils.add(p, startOrientation);\n\t\tTileEntity entity = p.getTileEntity(startProvider.getWorld());\n\t\tIPipeInformationProvider provider = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(entity);\n\t\tif (provider == null) {\n\t\t\treturn new HashMap<>();\n\t\t}\n\t\treturn newSearch.getConnectedRoutingPipes(provider, connectionType, startOrientation);\n\t}\n\n\tpublic PathFinder(IPipeInformationProvider startPipe, int maxVisited, int maxLength, ITileEntityChangeListener changeListener) {\n\t\tthis(maxVisited, maxLength, null);\n\t\tif (startPipe == null) {\n\t\t\tresult = new HashMap<>();\n\t\t\treturn;\n\t\t}\n\t\tthis.changeListener = changeListener;\n\t\tresult = getConnectedRoutingPipes(startPipe, EnumSet.allOf(PipeRoutingConnectionType.class), null);\n\t}\n\n\tpublic PathFinder(IPipeInformationProvider startPipe, int maxVisited, int maxLength, EnumFacing side) {\n\t\tthis(maxVisited, maxLength, null);\n\t\tresult = getConnectedRoutingPipes(startPipe, EnumSet.allOf(PipeRoutingConnectionType.class), side);\n\t}\n\n\tprivate PathFinder(int maxVisited, int maxLength, IPaintPath pathPainter) {\n\t\tthis.maxVisited = maxVisited;\n\t\tthis.maxLength = maxLength;\n\t\tsetVisited = new HashSet<>();\n\t\tdistances = new HashMap<>();\n\t\tthis.pathPainter = pathPainter;\n\t}\n\n\tprivate final int maxVisited;\n\tprivate final int maxLength;\n\tprivate final HashSet<DoubleCoordinates> setVisited;\n\tprivate final HashMap<DoubleCoordinates, Double> distances;\n\tprivate final IPaintPath pathPainter;\n\tprivate double pipesVisited;\n\n\tpublic List<Pair<ILogisticsPowerProvider, List<IFilter>>> powerNodes;\n\tpublic List<Pair<ISubSystemPowerProvider, List<IFilter>>> subPowerProvider;\n\tpublic HashMap<CoreRoutedPipe, ExitRoute> result;\n\n\tpublic ITileEntityChangeListener changeListener;\n\tpublic Set<List<ITileEntityChangeListener>> listenedPipes = new HashSet<>();\n\tpublic Set<LPTileEntityObject> touchedPipes = new HashSet<>();\n\n\tprivate HashMap<CoreRoutedPipe, ExitRoute> getConnectedRoutingPipes(IPipeInformationProvider startPipe, EnumSet<PipeRoutingConnectionType> connectionFlags, EnumFacing side) {\n\t\tHashMap<CoreRoutedPipe, ExitRoute> foundPipes = new HashMap<>();\n\n\t\tfinal int setVisitedSize = setVisited.size();\n\n\t\tboolean root = setVisitedSize == 0;\n\n\t\t//Reset visited count at top level\n\t\tif (setVisitedSize == 1) {\n\t\t\tpipesVisited = 0;\n\t\t}\n\n\t\t//Break recursion if we have visited a set number of pipes, to prevent client hang if pipes are weirdly configured\n\t\tpipesVisited += startPipe.getDistanceWeight() > 0 ? startPipe.getDistanceWeight() : 1;\n\t\tif (pipesVisited > maxVisited) {\n\t\t\treturn foundPipes;\n\t\t}\n\n\t\t//Break recursion after certain amount of nodes visited\n\t\tif (setVisitedSize > maxLength * 10) {\n\t\t\treturn foundPipes;\n\t\t}\n\n\t\t//Break recursion after certain length of nodes visited\n\t\t//Maximize to 1 so we don't stop at routes with resistor pipes\n\t\t//Check size of setVisited first to speed up the process, so we don't sum the distances all the time\n\t\tif (setVisitedSize > maxLength && distances.values().stream().mapToDouble(i -> Math.max(Math.min(i, 1), 0)).sum() > maxLength) {\n\t\t\treturn foundPipes;\n\t\t}\n\n\t\tif (!startPipe.isRouterInitialized()) {\n\t\t\treturn foundPipes;\n\t\t}\n\n\t\t//Break recursion if we end up on a routing pipe, unless its the first one. Will break if matches the first call\n\t\tif (startPipe.isRoutingPipe() && setVisitedSize != 0) {\n\t\t\tCoreRoutedPipe rp = startPipe.getRoutingPipe();\n\t\t\tif (rp.stillNeedReplace()) {\n\t\t\t\treturn foundPipes;\n\t\t\t}\n\t\t\tdouble size = 0;\n\t\t\tfor (Double dis : distances.values()) {\n\t\t\t\tsize += dis;\n\t\t\t}\n\n\t\t\tif (!rp.getUpgradeManager().hasPowerPassUpgrade()) {\n\t\t\t\tconnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);\n\t\t\t}\n\n\t\t\tfoundPipes.put(rp, new ExitRoute(null, rp.getRouter(), null, side.getOpposite(), Math.max(1, size), connectionFlags, distances.size()));\n\n\t\t\treturn foundPipes;\n\t\t}\n\n\t\t//Visited is checked after, so we can reach the same target twice to allow to keep the shortest path\n\t\tsetVisited.add(new DoubleCoordinates(startPipe));\n\t\tdistances.put(new DoubleCoordinates(startPipe), startPipe.getDistance() * startPipe.getDistanceWeight());\n\n\t\t// first check specialPipeConnections (tesseracts, teleports, other connectors)\n\t\tList<ConnectionInformation> pipez = SimpleServiceLocator.specialpipeconnection.getConnectedPipes(startPipe, connectionFlags, side);\n\t\tfor (ConnectionInformation specialConnection : pipez) {\n\t\t\tif (setVisited.contains(new DoubleCoordinates(specialConnection.getConnectedPipe()))) {\n\t\t\t\t//Don't go where we have been before\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tdistances.put(new DoubleCoordinates(startPipe).center(), specialConnection.getDistance());\n\t\t\tHashMap<CoreRoutedPipe, ExitRoute> result = getConnectedRoutingPipes(specialConnection.getConnectedPipe(), specialConnection.getConnectionFlags(), specialConnection.getInsertOrientation());\n\t\t\tdistances.remove(new DoubleCoordinates(startPipe).center());\n\t\t\tfor (Entry<CoreRoutedPipe, ExitRoute> pipe : result.entrySet()) {\n\t\t\t\tpipe.getValue().exitOrientation = specialConnection.getExitOrientation();\n\t\t\t\tExitRoute foundPipe = foundPipes.get(pipe.getKey());\n\t\t\t\tif (foundPipe == null || (pipe.getValue().distanceToDestination < foundPipe.distanceToDestination)) {\n\t\t\t\t\t// New path OR \tIf new path is better, replace old path\n\t\t\t\t\tfoundPipes.put(pipe.getKey(), pipe.getValue());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tArrayDeque<Quartet<TileEntity, EnumFacing, Integer, Boolean>> connections = new ArrayDeque<>();\n\n\t\t//Recurse in all directions\n\t\tfor (EnumFacing direction : EnumFacing.VALUES) {\n\t\t\tif (root && side != null && !direction.equals(side)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// tile may be up to 1 second old, but any neighbour pipe change will cause an immidiate update here, so we know that if it has changed, it isn't a pipe that has done so.\n\t\t\tTileEntity tile = startPipe.getNextConnectedTile(direction);\n\n\t\t\tif (tile == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (root && (direction.getAxis() == EnumFacing.Axis.X || direction.getAxis() == EnumFacing.Axis.Z)) {\n\t\t\t\tif (tile instanceof ILogisticsPowerProvider) {\n\t\t\t\t\tif (powerNodes == null) {\n\t\t\t\t\t\tpowerNodes = new ArrayList<>();\n\t\t\t\t\t}\n\t\t\t\t\t//If we are a FireWall pipe add our filter to the pipes\n\t\t\t\t\tif (startPipe.isFirewallPipe()) {\n\t\t\t\t\t\tpowerNodes.add(new Pair<>((ILogisticsPowerProvider) tile, new OneList<>(startPipe.getFirewallFilter())));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpowerNodes.add(new Pair<>((ILogisticsPowerProvider) tile, Collections.unmodifiableList(new ArrayList<>(0))));\n\t\t\t\t\t}\n\t\t\t\t} else if (tile instanceof ISubSystemPowerProvider) {\n\t\t\t\t\tif (subPowerProvider == null) {\n\t\t\t\t\t\tsubPowerProvider = new ArrayList<>();\n\t\t\t\t\t}\n\t\t\t\t\t//If we are a FireWall pipe add our filter to the pipes\n\t\t\t\t\tif (startPipe.isFirewallPipe()) {\n\t\t\t\t\t\tsubPowerProvider.add(new Pair<>((ISubSystemPowerProvider) tile, new OneList<>(startPipe.getFirewallFilter())));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsubPowerProvider.add(new Pair<>((ISubSystemPowerProvider) tile, Collections.unmodifiableList(new ArrayList<>(0))));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tconnections.add(new Quartet<>(tile, direction, 0, false));\n\t\t}\n\n\t\twhile (!connections.isEmpty()) {\n\t\t\tQuartet<TileEntity, EnumFacing, Integer, Boolean> quartet = connections.pollFirst();\n\t\t\tTileEntity tile = quartet.getValue1();\n\t\t\tEnumFacing direction = quartet.getValue2();\n\t\t\tint resistance = quartet.getValue3();\n\t\t\tboolean isDirectConnection = quartet.getValue4();\n\t\t\tEnumSet<PipeRoutingConnectionType> nextConnectionFlags = EnumSet.copyOf(connectionFlags);\n\n\t\t\tif (root) {\n\t\t\t\tCollection<TileEntity> list = SimpleServiceLocator.specialtileconnection.getConnectedPipes(tile);\n\t\t\t\tif (!list.isEmpty()) {\n\t\t\t\t\tconnections.addAll(list.stream().map(pipe -> new Quartet<>(pipe, direction, 0, false)).collect(Collectors.toList()));\n\t\t\t\t\tlistTileEntity(tile);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!startPipe.getRoutingPipe().getUpgradeManager().hasPowerPassUpgrade()) {\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!SimpleServiceLocator.pipeInformationManager.isPipe(tile) && tile.hasCapability(LogisticsPipes.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) && startPipe.isRoutingPipe() && startPipe.getRoutingPipe() instanceof IChannelRoutingConnection && startPipe.canConnect(tile, direction, false)) {\n\t\t\t\tif (SimpleServiceLocator.connectionManager.hasChannelConnection(startPipe.getRoutingPipe().getRouter())) {\n\t\t\t\t\tList<CoreRoutedPipe> connectedPipes = SimpleServiceLocator.connectionManager.getConnectedPipes(startPipe.getRoutingPipe().getRouter());\n\t\t\t\t\tconnections.addAll(connectedPipes.stream().map(pipe -> new Quartet<>((TileEntity) pipe.container, direction, ((IChannelRoutingConnection) startPipe.getRoutingPipe()).getConnectionResistance(), true)).collect(Collectors.toList()));\n\t\t\t\t\tif (!connectedPipes.isEmpty()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (tile == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tIPipeInformationProvider currentPipe = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile);\n\n\t\t\tif (currentPipe != null && currentPipe.isRouterInitialized() && (isDirectConnection || SimpleServiceLocator.pipeInformationManager.canConnect(startPipe, currentPipe, direction, true))) {\n\n\t\t\t\tlistTileEntity(tile);\n\n\t\t\t\tif (currentPipe.isMultiBlock()) {\n\t\t\t\t\tcurrentPipe.getPartsOfPipe().forEach(this::listTileEntity);\n\t\t\t\t}\n\n\t\t\t\tif (setVisited.contains(new DoubleCoordinates(currentPipe))) {\n\t\t\t\t\t//Don't go where we have been before\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (side != direction && !root) { //Only straight connections for subsystem power\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);\n\t\t\t\t}\n\t\t\t\tif (isDirectConnection) { //ISC doesn't pass power\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canPowerFrom);\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);\n\t\t\t\t}\n\t\t\t\t//Iron, obsidean and liquid pipes will separate networks\n\t\t\t\tif (currentPipe.divideNetwork()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (currentPipe.powerOnly()) {\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canRouteTo);\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canRequestFrom);\n\t\t\t\t}\n\t\t\t\tif (startPipe.isOnewayPipe()) {\n\t\t\t\t\tif (startPipe.isOutputClosed(direction)) {\n\t\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canRouteTo);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (currentPipe.isOnewayPipe()) {\n\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canPowerSubSystemFrom);\n\t\t\t\t\tif (currentPipe.isOutputClosed(direction.getOpposite())) {\n\t\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canRequestFrom);\n\t\t\t\t\t\tnextConnectionFlags.remove(PipeRoutingConnectionType.canPowerFrom);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (nextConnectionFlags.isEmpty()) { //don't bother going somewhere we can't do anything with\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tint beforeRecurseCount = foundPipes.size();\n\t\t\t\tHashMap<CoreRoutedPipe, ExitRoute> result = null;\n\t\t\t\tif (currentPipe instanceof IRouteProvider) {\n\t\t\t\t\tList<RouteInfo> list = ((IRouteProvider) currentPipe).getConnectedPipes(direction.getOpposite());\n\t\t\t\t\tif (list != null) {\n\t\t\t\t\t\tresult = new HashMap<>();\n\t\t\t\t\t\tDoubleCoordinates pos = new DoubleCoordinates(currentPipe);\n\t\t\t\t\t\tfor (RouteInfo info : list) {\n\t\t\t\t\t\t\tif (info.getPipe() == startPipe) continue;\n\t\t\t\t\t\t\tif (setVisited.contains(new DoubleCoordinates(info.getPipe()))) {\n\t\t\t\t\t\t\t\t//Don't go where we have been before\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdistances.put(pos, (currentPipe.getDistance() * currentPipe.getDistanceWeight()) + info.getLength());\n\t\t\t\t\t\t\tresult.putAll(getConnectedRoutingPipes(info.getPipe(), nextConnectionFlags, direction));\n\t\t\t\t\t\t\tdistances.remove(pos);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result == null) {\n\t\t\t\t\tresult = getConnectedRoutingPipes(currentPipe, nextConnectionFlags, direction);\n\t\t\t\t}\n\t\t\t\tfor (Entry<CoreRoutedPipe, ExitRoute> pipeEntry : result.entrySet()) {\n\t\t\t\t\t//Update Result with the direction we took\n\t\t\t\t\tpipeEntry.getValue().exitOrientation = direction;\n\t\t\t\t\tExitRoute foundPipe = foundPipes.get(pipeEntry.getKey());\n\t\t\t\t\tif (foundPipe == null) {\n\t\t\t\t\t\t// New path\n\t\t\t\t\t\tfoundPipes.put(pipeEntry.getKey(), pipeEntry.getValue());\n\t\t\t\t\t\t//Add resistance\n\t\t\t\t\t\tpipeEntry.getValue().distanceToDestination += resistance;\n\t\t\t\t\t} else if (pipeEntry.getValue().distanceToDestination + resistance < foundPipe.distanceToDestination) {\n\t\t\t\t\t\t//If new path is better, replace old path, otherwise do nothing\n\t\t\t\t\t\tfoundPipes.put(pipeEntry.getKey(), pipeEntry.getValue());\n\t\t\t\t\t\t//Add resistance\n\t\t\t\t\t\tpipeEntry.getValue().distanceToDestination += resistance;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (foundPipes.size() > beforeRecurseCount && pathPainter != null) {\n\t\t\t\t\tpathPainter.addLaser(startPipe.getWorld(), new LaserData(startPipe.getX(), startPipe.getY(), startPipe.getZ(), direction, connectionFlags));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsetVisited.remove(new DoubleCoordinates(startPipe));\n\t\tdistances.remove(new DoubleCoordinates(startPipe));\n\t\tif (startPipe.isRoutingPipe()) { // ie, has the recursion returned to the pipe it started from?\n\t\t\tfor (ExitRoute e : foundPipes.values()) {\n\t\t\t\te.root = (startPipe.getRoutingPipe()).getRouter();\n\t\t\t}\n\t\t}\n\t\t//If we are a FireWall pipe add our filter to the pipes\n\t\tif (startPipe.isFirewallPipe() && root) {\n\t\t\tfor (ExitRoute e : foundPipes.values()) {\n\t\t\t\te.filters = new OneList<>(startPipe.getFirewallFilter());\n\t\t\t}\n\t\t}\n\t\treturn foundPipes;\n\t}\n\n\tprivate void listTileEntity(TileEntity tile) {\n\t\tif (changeListener != null && tile instanceof ILPTEInformation && ((ILPTEInformation) tile).getLPTileEntityObject() != null) {\n\t\t\tif (!((ILPTEInformation) tile).getLPTileEntityObject().changeListeners.contains(changeListener)) {\n\t\t\t\t((ILPTEInformation) tile).getLPTileEntityObject().changeListeners.add(changeListener);\n\t\t\t}\n\t\t\tlistenedPipes.add(((ILPTEInformation) tile).getLPTileEntityObject().changeListeners);\n\t\t\ttouchedPipes.add(((ILPTEInformation) tile).getLPTileEntityObject());\n\t\t}\n\t}\n\n\tpublic static int messureDistanceToNextRoutedPipe(DoubleCoordinates lpPosition, EnumFacing exitOrientation, World world) {\n\t\tint dis = 1;\n\t\tTileEntity tile = lpPosition.getTileEntity(world);\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\ttile = ((LogisticsTileGenericPipe) tile).getNextConnectedTile(exitOrientation);\n\t\t}\n\t\tif (tile == null) {\n\t\t\treturn 0;\n\t\t}\n\t\tIPipeInformationProvider info = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile);\n\t\twhile (info != null && !info.isRoutingPipe()) {\n\t\t\ttile = info.getNextConnectedTile(exitOrientation);\n\t\t\tif (tile == null) {\n\t\t\t\tinfo = null;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tinfo = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile);\n\t\t\tdis++;\n\t\t}\n\t\treturn dis;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/pathfinder/PipeInformationManager.java",
    "content": "package logisticspipes.routing.pathfinder;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport network.rs485.logisticspipes.connection.ConnectionType;\n\npublic class PipeInformationManager {\n\n\tprivate Map<Class<?> /*TileEntity*/, Class<? extends IPipeInformationProvider>> infoProvider = new HashMap<>();\n\n\tpublic IPipeInformationProvider getInformationProviderFor(TileEntity tile) {\n\t\tif (tile == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (tile instanceof IPipeInformationProvider) {\n\t\t\treturn (IPipeInformationProvider) tile;\n\t\t} else if (tile instanceof ISubMultiBlockPipeInformationProvider) {\n\t\t\treturn ((ISubMultiBlockPipeInformationProvider) tile).getMainTile();\n\t\t} else {\n\t\t\tfor (Class<?> type : infoProvider.keySet()) {\n\t\t\t\tif (type.isAssignableFrom(tile.getClass())) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tIPipeInformationProvider provider = infoProvider.get(type).getDeclaredConstructor(type).newInstance(type.cast(tile));\n\t\t\t\t\t\tif (provider.isCorrect(ConnectionType.UNDEFINED)) {\n\t\t\t\t\t\t\treturn provider;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (InstantiationException | IllegalAccessException | InvocationTargetException | IllegalArgumentException | SecurityException | NoSuchMethodException e) {\n\t\t\t\t\t\te.printStackTrace();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tpublic void registerProvider(Class<?> source, Class<? extends IPipeInformationProvider> provider) {\n\t\ttry {\n\t\t\tprovider.getDeclaredConstructor(source);\n\t\t} catch (NoSuchMethodException | SecurityException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tinfoProvider.put(source, provider);\n\t}\n\n\tpublic boolean canConnect(IPipeInformationProvider startPipe, IPipeInformationProvider provider, EnumFacing direction, boolean flag) {\n\t\treturn startPipe.canConnect(provider.getTile(), direction, flag) && provider.canConnect(startPipe.getTile(), direction.getOpposite(), flag);\n\t}\n\n\tpublic boolean isItemPipe(TileEntity tile) {\n\t\treturn isPipe(tile, true, ConnectionType.ITEM);\n\t}\n\n\tpublic boolean isPipe(TileEntity tile) {\n\t\treturn isPipe(tile, true, ConnectionType.UNDEFINED);\n\t}\n\n\tpublic boolean isPipe(TileEntity tile, boolean check, ConnectionType pipeType) {\n\t\tif (tile == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (tile instanceof IPipeInformationProvider) {\n\t\t\treturn true;\n\t\t} else if (tile instanceof ISubMultiBlockPipeInformationProvider) {\n\t\t\treturn pipeType == ConnectionType.MULTIBLOCK;\n\t\t} else {\n\t\t\tfor (Class<?> type : infoProvider.keySet()) {\n\t\t\t\tif (type.isAssignableFrom(tile.getClass())) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tIPipeInformationProvider provider = infoProvider.get(type).getDeclaredConstructor(type).newInstance(type.cast(tile));\n\t\t\t\t\t\tif (!check || provider.isCorrect(pipeType)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (InstantiationException | IllegalAccessException | InvocationTargetException | IllegalArgumentException | NoSuchMethodException | SecurityException e) {\n\t\t\t\t\t\te.printStackTrace();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic boolean isNotAPipe(TileEntity tile) {\n\t\tif (tile instanceof IPipeInformationProvider) {\n\t\t\treturn false;\n\t\t} else if (tile instanceof ISubMultiBlockPipeInformationProvider) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\tfor (Class<?> type : infoProvider.keySet()) {\n\t\t\t\tif (type.isAssignableFrom(tile.getClass())) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic boolean isFluidPipe(TileEntity tile) {\n\t\tIPipeInformationProvider info = getInformationProviderFor(tile);\n\t\tif (info == null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn info.isFluidPipe();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/routing/pathfinder/changedetection/TEControl.java",
    "content": "package logisticspipes.routing.pathfinder.changedetection;\n\nimport java.util.ArrayList;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport logisticspipes.asm.te.ILPTEInformation;\nimport logisticspipes.asm.te.ITileEntityChangeListener;\nimport logisticspipes.asm.te.LPTileEntityObject;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.ticks.LPTickHandler;\nimport logisticspipes.ticks.QueuedTasks;\nimport network.rs485.logisticspipes.connection.ConnectionType;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class TEControl {\n\n\tpublic static void validate(final TileEntity tile) {\n\t\tfinal World world = tile.getWorld();\n\t\tif (!MainProxy.isServer(world)) {\n\t\t\treturn;\n\t\t}\n\t\tif (tile.getClass().getName().startsWith(\"net.minecraft.tileentity\")) {\n\t\t\treturn;\n\t\t}\n\n\t\tfinal DoubleCoordinates pos = new DoubleCoordinates(tile);\n\t\tif (pos.getXInt() == 0 && pos.getYInt() <= 0 && pos.getZInt() == 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (SimpleServiceLocator.pipeInformationManager.isPipe(tile, false, ConnectionType.UNDEFINED) || SimpleServiceLocator.specialtileconnection.isType(tile)) {\n\t\t\t((ILPTEInformation) tile).setLPTileEntityObject(new LPTileEntityObject());\n\t\t\t((ILPTEInformation) tile).getLPTileEntityObject().initialised = LPTickHandler.getWorldInfo(world).getWorldTick();\n\t\t\tif (((ILPTEInformation) tile).getLPTileEntityObject().initialised < 5) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tQueuedTasks.queueTask(() -> {\n\t\t\t\tif (!SimpleServiceLocator.pipeInformationManager.isPipe(tile, true, ConnectionType.UNDEFINED)) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\t\tDoubleCoordinates newPos = CoordinateUtils.sum(pos, dir);\n\t\t\t\t\tif (!newPos.blockExists(world)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tTileEntity nextTile = newPos.getTileEntity(world);\n\t\t\t\t\tif (nextTile != null && ((ILPTEInformation) nextTile).getLPTileEntityObject() != null) {\n\t\t\t\t\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(nextTile)) {\n\t\t\t\t\t\t\tSimpleServiceLocator.pipeInformationManager.getInformationProviderFor(nextTile).refreshTileCacheOnSide(dir.getOpposite());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\t\t\t\t\tSimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile).refreshTileCacheOnSide(dir);\n\t\t\t\t\t\t\tSimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile).refreshTileCacheOnSide(dir.getOpposite());\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (ITileEntityChangeListener listener : new ArrayList<>(((ILPTEInformation) nextTile).getLPTileEntityObject().changeListeners)) {\n\t\t\t\t\t\t\tlistener.pipeAdded(pos, dir.getOpposite());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic static void invalidate(final TileEntity tile) {\n\t\tfinal World world = tile.getWorld();\n\t\tif (!MainProxy.isServer(world)) {\n\t\t\treturn;\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).isRoutingPipe()) {\n\t\t\treturn;\n\t\t}\n\t\tif (((ILPTEInformation) tile).getLPTileEntityObject() != null) {\n\t\t\tQueuedTasks.queueTask(() -> {\n\t\t\t\tDoubleCoordinates pos = new DoubleCoordinates(tile);\n\t\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\t\tDoubleCoordinates newPos = CoordinateUtils.sum(pos, dir);\n\t\t\t\t\tif (!newPos.blockExists(world)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tTileEntity nextTile = newPos.getTileEntity(world);\n\t\t\t\t\tif (nextTile != null && ((ILPTEInformation) nextTile).getLPTileEntityObject() != null) {\n\t\t\t\t\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(nextTile)) {\n\t\t\t\t\t\t\tSimpleServiceLocator.pipeInformationManager.getInformationProviderFor(nextTile).refreshTileCacheOnSide(dir.getOpposite());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (ITileEntityChangeListener listener : new ArrayList<>(((ILPTEInformation) tile).getLPTileEntityObject().changeListeners)) {\n\t\t\t\t\tlistener.pipeRemoved(pos);\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/security/PermissionException.java",
    "content": "package logisticspipes.security;\n\npublic class PermissionException extends RuntimeException {\n\n\tprivate static final long serialVersionUID = 7761142652210614117L;\n\n\tpublic PermissionException() {\n\t\tsuper(\"Permission denied\");\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/security/SecuritySettings.java",
    "content": "package logisticspipes.security;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport network.rs485.logisticspipes.IStore;\n\npublic class SecuritySettings implements IStore {\n\n\tpublic String name;\n\tpublic boolean openGui = false;\n\tpublic boolean openRequest = false;\n\tpublic boolean openUpgrades = false;\n\tpublic boolean openNetworkMonitor = false;\n\tpublic boolean removePipes = false;\n\tpublic boolean accessRoutingChannels = false;\n\n\tpublic SecuritySettings(String name) {\n\t\tthis.name = name;\n\t}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\tString prev = name;\n\t\tname = nbttagcompound.getString(\"name\");\n\t\tif (name.equals(\"\")) {\n\t\t\tname = prev;\n\t\t}\n\t\topenGui = nbttagcompound.getBoolean(\"openGui\");\n\t\topenRequest = nbttagcompound.getBoolean(\"openRequest\");\n\t\topenUpgrades = nbttagcompound.getBoolean(\"openUpgrades\");\n\t\topenNetworkMonitor = nbttagcompound.getBoolean(\"openNetworkMonitor\");\n\t\tremovePipes = nbttagcompound.getBoolean(\"removePipes\");\n\t\taccessRoutingChannels = nbttagcompound.getBoolean(\"accessRoutingChannels\");\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\tif (name == null || name.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tnbttagcompound.setString(\"name\", name);\n\t\tnbttagcompound.setBoolean(\"openGui\", openGui);\n\t\tnbttagcompound.setBoolean(\"openRequest\", openRequest);\n\t\tnbttagcompound.setBoolean(\"openUpgrades\", openUpgrades);\n\t\tnbttagcompound.setBoolean(\"openNetworkMonitor\", openNetworkMonitor);\n\t\tnbttagcompound.setBoolean(\"removePipes\", removePipes);\n\t\tnbttagcompound.setBoolean(\"accessRoutingChannels\", accessRoutingChannels);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/textures/Textures.java",
    "content": "package logisticspipes.textures;\n\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.renderer.IIconProvider;\nimport logisticspipes.textures.provider.LPActionTriggerIconProvider;\nimport logisticspipes.textures.provider.LPPipeIconProvider;\nimport logisticspipes.textures.provider.LPPipeIconTransformerProvider;\n\npublic class Textures {\n\n\tpublic static TextureType empty = new TextureType();\n\tpublic static TextureType empty_1 = new TextureType();\n\tpublic static TextureType empty_2 = new TextureType();\n\tpublic static SmallTextureType smallEmpty = new SmallTextureType();\n\tpublic static TextureType LOGISTICSPIPE_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_PROVIDER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_REQUESTER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CRAFTER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_SATELLITE_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_SUPPLIER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUIDSUPPLIER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUIDSUPPLIER_MK2_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_ROUTED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_NOTROUTED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_ROUTED_POWERED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_POWERED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_DIRECTION_POWERED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_SUBPOWER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_POWERED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_POWERED_POWERED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_SECURITY_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI_ROUTED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI1_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI2_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI3_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI4_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CHASSI5_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CRAFTERMK2_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_REQUESTERMK2_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_PROVIDERMK2_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_REMOTE_ORDERER_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_INVSYSCON_CON_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_INVSYSCON_DIS_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_INVSYSCON_MIS_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_ENTRANCE_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_DESTINATION_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_CRAFTERMK3_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_FIREWALL_TEXTURE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_BASIC = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_INSERTION = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_PROVIDER = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_REQUEST = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_EXTRACTOR = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_SATELLITE = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_LIQUID_TERMINUS = Textures.empty;\n\tpublic static TextureType LOGISTICSPIPE_OPAQUE_TEXTURE = Textures.empty;\n\tpublic static SmallTextureType LOGISTICSPIPE_BASIC_TRANSPORT_TEXTURE = Textures.smallEmpty;\n\n\tpublic static Object[] LOGISTICS_REQUEST_TABLE = new Object[0];\n\tpublic static Object LOGISTICS_REQUEST_TABLE_NEW = null;\n\tpublic static Object LOGISTICS_REQUEST_TABLE_NEW_ROUTED = null;\n\tpublic static Object LOGISTICS_REQUEST_TABLE_NEW_UNROUTED = null;\n\tpublic static Object LOGISTICS_REQUEST_TABLE_NEW_EMPTY = null;\n\n\tpublic static int LOGISTICSPIPE_LIQUID_CONNECTOR = 0;\n\t/*\tpublic static TextureAtlasSprite LOGISTICSACTIONTRIGGERS_DISABLED;\n\t\tpublic static TextureAtlasSprite LOGISTICSACTIONTRIGGERS_CRAFTING_ICON;\n\t\tpublic static TextureAtlasSprite LOGISTICSACTIONTRIGGERS_TEXTURE_FILE;\n\t\tpublic static TextureAtlasSprite LOGISTICSACTIONTRIGGERS_NEEDS_POWER_ICON;\n\t\tpublic static TextureAtlasSprite LOGISTICSACTIONTRIGGERS_SUPPLIER_FAILED_ICON;\n\t\tpublic static TextureAtlasSprite[] LOGISTICS_UPGRADES_DISCONECT_ICONINDEX;\n\t\tpublic static TextureAtlasSprite[] LOGISTICS_UPGRADES_SNEAKY_ICONINDEX;\n\t\tpublic static TextureAtlasSprite[] LOGISTICS_UPGRADES_ICONINDEX;\n\t\tpublic static TextureAtlasSprite LOGISTICSITEMS_ITEMHUD_ICON;\n\t\tpublic static TextureAtlasSprite LOGISTICSITEMTEXTURE_FOR_DISK;*/\n\tpublic static Object LOGISTICS_SIDE_SELECTION;\n\n\t// Standalone pipes\n\tpublic static String LOGISTICSPIPE_TEXTURE_FILE = \"pipes/basic\";\n\tpublic static String LOGISTICSPIPE_PROVIDER_TEXTURE_FILE = \"pipes/provider\";\n\tpublic static String LOGISTICSPIPE_PROVIDERMK2_TEXTURE_FILE = \"pipes/provider_mk2\";\n\tpublic static String LOGISTICSPIPE_REQUESTER_TEXTURE_FILE = \"pipes/request\";\n\tpublic static String LOGISTICSPIPE_REQUESTERMK2_TEXTURE_FILE = \"pipes/request_mk2\";\n\tpublic static String LOGISTICSPIPE_CRAFTER_TEXTURE_FILE = \"pipes/crafting\";\n\tpublic static String LOGISTICSPIPE_CRAFTERMK2_TEXTURE_FILE = \"pipes/crafting_mk2\";\n\tpublic static String LOGISTICSPIPE_SATELLITE_TEXTURE_FILE = \"pipes/satellite\";\n\tpublic static String LOGISTICSPIPE_SUPPLIER_TEXTURE_FILE = \"pipes/supplier\";\n\tpublic static String LOGISTICSPIPE_LIQUIDSUPPLIER_TEXTURE_FILE = \"pipes/liquid_supplier\";\n\tpublic static String LOGISTICSPIPE_LIQUIDSUPPLIER_MK2_TEXTURE_FILE = \"pipes/liquid_supplier_mk2\";\n\tpublic static String LOGISTICSPIPE_REMOTE_ORDERER_TEXTURE_FILE = \"pipes/remote_orderer\";\n\tpublic static String LOGISTICSPIPE_INVSYSCON_CON_TEXTURE_FILE = \"pipes/invsyscon_con\";\n\tpublic static String LOGISTICSPIPE_INVSYSCON_DIS_TEXTURE_FILE = \"pipes/invsyscon_dis\";\n\tpublic static String LOGISTICSPIPE_INVSYSCON_MIS_TEXTURE_FILE = \"pipes/invsyscon_mis\";\n\tpublic static String LOGISTICSPIPE_ENTRANCE_TEXTURE_FILE = \"pipes/entrance\";\n\tpublic static String LOGISTICSPIPE_DESTINATION_TEXTURE_FILE = \"pipes/destination\";\n\tpublic static String LOGISTICSPIPE_CRAFTERMK3_TEXTURE_FILE = \"pipes/crafting_mk3\";\n\tpublic static String LOGISTICSPIPE_FIREWALL_TEXTURE_FILE = \"pipes/firewall\";\n\t// Fluid Pipes\n\tpublic static String LOGISTICSPIPE_LIQUID_CONNECTOR_TEXTURE_FILE = \"pipes/liquid_connector\";\n\tpublic static String LOGISTICSPIPE_LIQUID_BASIC_FILE = \"pipes/liquid_basic\";\n\tpublic static String LOGISTICSPIPE_LIQUID_INSERTION_FILE = \"pipes/liquid_insertion\";\n\tpublic static String LOGISTICSPIPE_LIQUID_PROVIDER_FILE = \"pipes/liquid_provider\";\n\tpublic static String LOGISTICSPIPE_LIQUID_REQUEST_FILE = \"pipes/liquid_request\";\n\tpublic static String LOGISTICSPIPE_LIQUID_EXTRACTOR_FILE = \"pipes/liquid_extractor\";\n\tpublic static String LOGISTICSPIPE_LIQUID_SATELLITE_FILE = \"pipes/liquid_satellite\";\n\tpublic static String LOGISTICSPIPE_LIQUID_TERMINUS_FILE = \"pipes/liquid_terminus\";\n\t// Status overlay\n\tpublic static String LOGISTICSPIPE_ROUTED_TEXTURE_FILE = \"pipes/status_overlay/routed\";\n\tpublic static String LOGISTICSPIPE_NOTROUTED_TEXTURE_FILE = \"pipes/status_overlay/not_routed\";\n\tpublic static String LOGISTICSPIPE_LIQUID_TEXTURE_FILE = \"pipes/status_overlay/liquid_connection\";\n\tpublic static String LOGISTICSPIPE_ROUTED_POWERED_TEXTURE_FILE = \"pipes/status_overlay/routed_powered\";\n\tpublic static String LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE_FILE = \"pipes/status_overlay/not_routed_powered\";\n\tpublic static String LOGISTICSPIPE_LIQUID_POWERED_TEXTURE_FILE = \"pipes/status_overlay/liquid_connection_powered\";\n\tpublic static String LOGISTICSPIPE_POWERED_TEXTURE_FILE = \"pipes/status_overlay/powered\";\n\tpublic static String LOGISTICSPIPE_POWERED_POWERED_TEXTURE_FILE = \"pipes/status_overlay/powered_powered\";\n\tpublic static String LOGISTICSPIPE_DIRECTION_POWERED_TEXTURE_FILE = \"pipes/status_overlay/direction_powered\";\n\tpublic static String LOGISTICSPIPE_SECURITY_TEXTURE_FILE = \"pipes/status_overlay/security\";\n\tpublic static String LOGISTICSPIPE_SUBPOWER_TEXTURE_FILE = \"pipes/status_overlay/subpower\";\n\tpublic static String LOGISTICSPIPE_OPAQUE_TEXTURE_FILE = \"pipes/status_overlay/opaque\";\n\t// Chassi pipes\n\tpublic static String LOGISTICSPIPE_CHASSI1_TEXTURE_FILE = \"pipes/chassi/chassi_mk1\";\n\tpublic static String LOGISTICSPIPE_CHASSI2_TEXTURE_FILE = \"pipes/chassi/chassi_mk2\";\n\tpublic static String LOGISTICSPIPE_CHASSI3_TEXTURE_FILE = \"pipes/chassi/chassi_mk3\";\n\tpublic static String LOGISTICSPIPE_CHASSI4_TEXTURE_FILE = \"pipes/chassi/chassi_mk4\";\n\tpublic static String LOGISTICSPIPE_CHASSI5_TEXTURE_FILE = \"pipes/chassi/chassi_mk5\";\n\t// Chassi status overlay\n\tpublic static String LOGISTICSPIPE_CHASSI_ROUTED_TEXTURE_FILE = \"pipes/chassi/status_overlay/routed\";\n\tpublic static String LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE_FILE = \"pipes/chassi/status_overlay/not_routed\";\n\tpublic static String LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE_FILE = \"pipes/chassi/status_overlay/direction\";\n\t// Pipe Power Overlays\n\tpublic static String LOGISTICSPIPE_OVERLAY_POWERED_TEXTURE_FILE = \"pipes/status_overlay/powered-pipe\";\n\tpublic static String LOGISTICSPIPE_OVERLAY_UNPOWERED_TEXTURE_FILE = \"pipes/status_overlay/un-powered-pipe\";\n\tpublic static String LOGISTICSPIPE_UN_OVERLAY_TEXTURE_FILE = \"pipes/status_overlay/un-overlayed\";\n\tpublic static String LOGISTICSPIPE_BASIC_TRANSPORT_TEXTURE_FILE = \"pipes/transport/basic\";\n\tpublic static String LOGISTICS_SOLID_BLOCK = Textures.LOGISTICSPIPE_TEXTURE_FILE;\n\tpublic static IIconProvider LPactionIconProvider;\n\tpublic static LPPipeIconProvider LPpipeIconProvider;\n\tpublic static LPPipeIconTransformerProvider LPnewPipeIconProvider;\n\n\tstatic {\n\t\tTextures.empty.normal = 0;\n\t\tTextures.empty.powered = 0;\n\t\tTextures.empty.unpowered = 0;\n\t}\n\n\tstatic {\n\t\tTextures.empty_1.normal = 1;\n\t\tTextures.empty_1.powered = 1;\n\t\tTextures.empty_1.unpowered = 1;\n\t}\n\n\tstatic {\n\t\tTextures.empty_2.normal = 2;\n\t\tTextures.empty_2.powered = 2;\n\t\tTextures.empty_2.unpowered = 2;\n\t}\n\n\tstatic {\n\t\tTextures.smallEmpty.normal = 0;\n\t\tTextures.smallEmpty.newTexture = 0;\n\t}\n\n\tprivate int index = 0;\n\tprivate int newTextureIndex = 0;\n\n\tpublic Textures() {\n\t\tTextures.LPactionIconProvider = new LPActionTriggerIconProvider();\n\t\tTextures.LPpipeIconProvider = new LPPipeIconProvider();\n\t\tTextures.LPnewPipeIconProvider = new LPPipeIconTransformerProvider();\n\t}\n\n\t//this gets called with null par1IIconRegister from preinit, and later with non-null from textureprestitch\n\tpublic void registerBlockIcons(Object par1IIconRegister) {\n\t\t//Register Empty Texture for slot 0\n\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, 0, \"empty\", \"\", true);\n\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, 1, \"empty\", \"\", true);\n\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, 2, \"empty\", \"\", true);\n\n\t\tindex = 3;\n\t\tnewTextureIndex = 0;\n\n\t\t// Standalone pipes\n\t\tTextures.LOGISTICSPIPE_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_PROVIDER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_PROVIDER_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_POWERED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_POWERED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_POWERED_POWERED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_POWERED_POWERED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_DIRECTION_POWERED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_DIRECTION_POWERED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_SECURITY_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_SECURITY_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_ROUTED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_ROUTED_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_NOTROUTED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_NOTROUTED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_ROUTED_POWERED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_ROUTED_POWERED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_SUBPOWER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_SUBPOWER_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_OPAQUE_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_OPAQUE_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_REQUESTER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_REQUESTER_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CRAFTER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CRAFTER_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_SATELLITE_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_SATELLITE_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_SUPPLIER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_SUPPLIER_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUIDSUPPLIER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUIDSUPPLIER_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUIDSUPPLIER_MK2_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUIDSUPPLIER_MK2_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CRAFTERMK2_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CRAFTERMK2_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_REQUESTERMK2_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_REQUESTERMK2_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_PROVIDERMK2_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_PROVIDERMK2_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_REMOTE_ORDERER_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_REMOTE_ORDERER_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_INVSYSCON_CON_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_INVSYSCON_CON_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_INVSYSCON_DIS_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_INVSYSCON_DIS_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_INVSYSCON_MIS_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_INVSYSCON_MIS_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_ENTRANCE_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_ENTRANCE_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_DESTINATION_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_DESTINATION_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CRAFTERMK3_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CRAFTERMK3_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_FIREWALL_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_FIREWALL_TEXTURE_FILE);\n\t\t//Fluid\n\t\tTextures.LOGISTICSPIPE_LIQUID_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_LIQUID_POWERED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_POWERED_TEXTURE_FILE, 2);\n\t\tTextures.LOGISTICSPIPE_LIQUID_CONNECTOR = registerSingleTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_CONNECTOR_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_BASIC = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_BASIC_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_INSERTION = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_INSERTION_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_PROVIDER = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_PROVIDER_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_REQUEST = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_REQUEST_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_EXTRACTOR = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_EXTRACTOR_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_SATELLITE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_SATELLITE_FILE);\n\t\tTextures.LOGISTICSPIPE_LIQUID_TERMINUS = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_LIQUID_TERMINUS_FILE);\n\n\t\t//Chassi\n\t\tTextures.LOGISTICSPIPE_CHASSI_ROUTED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI_ROUTED_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI1_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI1_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI2_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI2_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI3_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI3_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI4_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI4_TEXTURE_FILE);\n\t\tTextures.LOGISTICSPIPE_CHASSI5_TEXTURE = registerTexture(par1IIconRegister, Textures.LOGISTICSPIPE_CHASSI5_TEXTURE_FILE);\n\n\t\t//Transport\n\t\tTextures.LOGISTICSPIPE_BASIC_TRANSPORT_TEXTURE = registerSmallTexture(par1IIconRegister, Textures.LOGISTICSPIPE_BASIC_TRANSPORT_TEXTURE_FILE);\n\n\t\tif (MainProxy.isClient() && par1IIconRegister != null) {\n\t\t\tTextures.LOGISTICS_REQUEST_TABLE = new Object[5];\n\t\t\tfor (int i = 0; i < 5; i++) {\n\t\t\t\tTextures.LOGISTICS_REQUEST_TABLE[i] = ((TextureMap) par1IIconRegister).registerSprite(new ResourceLocation(\"logisticspipes:blocks/requesttable/\" + i));\n\t\t\t}\n\t\t\tTextures.LOGISTICS_REQUEST_TABLE_NEW = ((TextureMap) par1IIconRegister).registerSprite(new ResourceLocation(\"logisticspipes:blocks/requesttable/requesttexture\"));\n\t\t\tTextures.LOGISTICS_REQUEST_TABLE_NEW_ROUTED = ((TextureMap) par1IIconRegister).registerSprite(new ResourceLocation(\"logisticspipes:blocks/requesttable/routed\"));\n\t\t\tTextures.LOGISTICS_REQUEST_TABLE_NEW_UNROUTED = ((TextureMap) par1IIconRegister).registerSprite(new ResourceLocation(\"logisticspipes:blocks/requesttable/unrouted\"));\n\t\t\tTextures.LOGISTICS_REQUEST_TABLE_NEW_EMPTY = ((TextureMap) par1IIconRegister).registerSprite(new ResourceLocation(\"logisticspipes:blocks/empty\"));\n\t\t\tTextures.LOGISTICS_SIDE_SELECTION = ((TextureMap) par1IIconRegister).registerSprite(new ResourceLocation(\"logisticspipes:blocks/sideSelection\"));\n\t\t}\n\n\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\tSystem.out.println(\"LP: pipetextures \" + index);\n\t\t}\n\t}\n\n\tpublic void registerItemIcons(Object textureMap) {\n\t\tTextures.LPactionIconProvider.registerIcons(textureMap);\n\t}\n\n\tprivate TextureType registerTexture(Object par1IIconRegister, String fileName) {\n\t\treturn registerTexture(par1IIconRegister, fileName, 1);\n\t}\n\n\t/**\n\t * @param par1IIconRegister - IconRegister\n\t * @param fileName          - name of texture\n\t * @param flag              - 2 - register single texture without overlay, 1/0 register\n\t *                          with overlay\n\t */\n\n\tprivate TextureType registerTexture(Object par1IIconRegister, String fileName, int flag) {\n\t\tTextureType texture = new TextureType();\n\t\ttexture.normal = index++;\n\t\ttexture.powered = texture.normal;\n\t\ttexture.unpowered = texture.normal;\n\t\ttexture.fileName = fileName;\n\t\tboolean isClient = MainProxy.isClient();\n\t\tif (isClient) {\n\t\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture.normal, fileName, Textures.LOGISTICSPIPE_UN_OVERLAY_TEXTURE_FILE, (flag == 2));\n\t\t}\n\t\tif (flag == 1) {\n\t\t\ttexture.powered = index++;\n\t\t\ttexture.unpowered = index++;\n\t\t\tif (isClient) {\n\t\t\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture.powered, fileName, Textures.LOGISTICSPIPE_OVERLAY_POWERED_TEXTURE_FILE, false);\n\t\t\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture.unpowered, fileName, Textures.LOGISTICSPIPE_OVERLAY_UNPOWERED_TEXTURE_FILE, false);\n\t\t\t}\n\t\t\tif (!fileName.contains(\"status_overlay\")) {\n\t\t\t\ttexture.newTexture = newTextureIndex++;\n\t\t\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture.newTexture, fileName, \"NewPipeTexture\", true);\n\t\t\t}\n\t\t}\n\t\treturn texture;\n\t}\n\n\tprivate SmallTextureType registerSmallTexture(Object par1IIconRegister, String fileName) {\n\t\tSmallTextureType texture = new SmallTextureType();\n\t\ttexture.normal = index++;\n\t\ttexture.fileName = fileName;\n\t\tboolean isClient = MainProxy.isClient();\n\t\tif (isClient) {\n\t\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture.normal, fileName, \"\", true);\n\t\t}\n\t\ttexture.newTexture = newTextureIndex++;\n\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture.newTexture, fileName, \"NewPipeTexture\", true);\n\t\treturn texture;\n\t}\n\n\tprivate int registerSingleTexture(Object par1IIconRegister, String fileName) {\n\t\tint texture = index++;\n\t\tif (FMLCommonHandler.instance().getEffectiveSide().isClient()) {\n\t\t\tMainProxy.proxy.addLogisticsPipesOverride(par1IIconRegister, texture, fileName, Textures.LOGISTICSPIPE_UN_OVERLAY_TEXTURE_FILE, true);\n\t\t}\n\t\treturn texture;\n\t}\n\n\tpublic static class TextureType {\n\n\t\tpublic int normal;\n\t\tpublic int powered;\n\t\tpublic int unpowered;\n\t\tpublic int newTexture;\n\t\tpublic String fileName = \"\";\n\t}\n\n\tpublic static class SmallTextureType {\n\n\t\tpublic int normal;\n\t\tpublic int newTexture;\n\t\tpublic String fileName = \"\";\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/textures/provider/LPActionTriggerIconProvider.java",
    "content": "package logisticspipes.textures.provider;\r\n\r\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\r\nimport net.minecraft.client.renderer.texture.TextureMap;\r\nimport net.minecraft.util.ResourceLocation;\r\n\r\nimport net.minecraftforge.fml.common.FMLCommonHandler;\r\nimport net.minecraftforge.fml.relauncher.Side;\r\nimport net.minecraftforge.fml.relauncher.SideOnly;\r\n\r\nimport logisticspipes.renderer.IIconProvider;\r\n\r\npublic class LPActionTriggerIconProvider implements IIconProvider {\r\n\r\n\tpublic static int actionDisablePipeIconIndex = 0;\r\n\tpublic static int triggerCraftingIconIndex = 1;\r\n\tpublic static int triggerPowerDischargingIconIndex = 2;\r\n\tpublic static int triggerPowerNeededIconIndex = 3;\r\n\tpublic static int triggerSupplierFailedIconIndex = 4;\r\n\tpublic static int triggerHasDestinationIconIndex = 5;\r\n\tpublic static int actionRobotRoutingIconIndex = 6;\r\n\r\n\t@SideOnly(Side.CLIENT)\r\n\tprivate TextureAtlasSprite[] icons;\r\n\r\n\tpublic LPActionTriggerIconProvider() {\r\n\t\tif (FMLCommonHandler.instance().getSide() == Side.CLIENT) {\r\n\t\t\ticons = new TextureAtlasSprite[7];\r\n\t\t}\r\n\t}\r\n\r\n\t@Override\r\n\t@SideOnly(Side.CLIENT)\r\n\tpublic TextureAtlasSprite getIcon(int iconIndex) {\r\n\t\tif (iconIndex > 6) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn icons[iconIndex];\r\n\t}\r\n\r\n\t@Override\r\n\t@SideOnly(Side.CLIENT)\r\n\tpublic void registerIcons(Object icon) {\r\n\t\tTextureMap iconRegister = (TextureMap) icon;\r\n\t\ticons[LPActionTriggerIconProvider.actionDisablePipeIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/DisablePipe\"));\r\n\t\ticons[LPActionTriggerIconProvider.triggerCraftingIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/CraftingWaiting\"));\r\n\t\ticons[LPActionTriggerIconProvider.triggerPowerDischargingIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/PowerDischarging\"));\r\n\t\ticons[LPActionTriggerIconProvider.triggerPowerNeededIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/PowerNeeded\"));\r\n\t\ticons[LPActionTriggerIconProvider.triggerSupplierFailedIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/ActionTrigger1\"));\r\n\t\ticons[LPActionTriggerIconProvider.triggerHasDestinationIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/ActionTrigger17\"));\r\n\t\ticons[LPActionTriggerIconProvider.actionRobotRoutingIconIndex] = iconRegister.registerSprite(new ResourceLocation(\"logisticspipes:actionTriggers/RobotRouting\"));\r\n\t}\r\n}\r\n"
  },
  {
    "path": "common/logisticspipes/textures/provider/LPPipeIconProvider.java",
    "content": "package logisticspipes.textures.provider;\r\n\r\nimport java.util.ArrayList;\r\n\r\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\r\n\r\nimport net.minecraftforge.fml.common.FMLCommonHandler;\r\nimport net.minecraftforge.fml.relauncher.Side;\r\nimport net.minecraftforge.fml.relauncher.SideOnly;\r\n\r\nimport logisticspipes.renderer.IIconProvider;\r\n\r\npublic class LPPipeIconProvider implements IIconProvider {\r\n\r\n\t@SideOnly(Side.CLIENT)\r\n\tprivate ArrayList<TextureAtlasSprite> icons;\r\n\r\n\tpublic LPPipeIconProvider() {\r\n\t\tif (FMLCommonHandler.instance().getSide() == Side.CLIENT) {\r\n\t\t\ticons = new ArrayList<>();\r\n\t\t}\r\n\t}\r\n\r\n\t@Override\r\n\t@SideOnly(Side.CLIENT)\r\n\tpublic TextureAtlasSprite getIcon(int iconIndex) {\r\n\t\treturn icons.get(iconIndex);\r\n\t}\r\n\r\n\t@SideOnly(Side.CLIENT)\r\n\tpublic void setIcon(int index, TextureAtlasSprite icon) {\r\n\t\twhile (icons.size() < index + 1) {\r\n\t\t\ticons.add(null);\r\n\t\t}\r\n\t\ticons.set(index, icon);\r\n\t}\r\n\r\n\t@Override\r\n\t@SideOnly(Side.CLIENT)\r\n\tpublic void registerIcons(Object iconRegister) {}\r\n}\r\n"
  },
  {
    "path": "common/logisticspipes/textures/provider/LPPipeIconTransformerProvider.java",
    "content": "package logisticspipes.textures.provider;\n\nimport java.util.ArrayList;\n\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.object3d.interfaces.TextureTransformation;\n\npublic class LPPipeIconTransformerProvider {\n\n\t@SideOnly(Side.CLIENT)\n\tprivate ArrayList<TextureTransformation> icons;\n\n\tpublic LPPipeIconTransformerProvider() {\n\t\tif (FMLCommonHandler.instance().getSide() == Side.CLIENT) {\n\t\t\ticons = new ArrayList<>();\n\t\t}\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic TextureTransformation getIcon(int iconIndex) {\n\t\treturn icons.get(iconIndex);\n\t}\n\n\t@SideOnly(Side.CLIENT)\n\tpublic void setIcon(int index, TextureAtlasSprite icon) {\n\t\twhile (icons.size() < index + 1) {\n\t\t\ticons.add(null);\n\t\t}\n\t\tif (icons.get(index) != null) {\n\t\t\ticons.get(index).update(icon);\n\t\t} else {\n\t\t\ticons.set(index, SimpleServiceLocator.cclProxy.createIconTransformer(icon));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/ClientPacketBufferHandlerThread.java",
    "content": "package logisticspipes.ticks;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.LinkedList;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.zip.GZIPInputStream;\nimport java.util.zip.GZIPOutputStream;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport net.minecraftforge.fml.common.gameevent.TickEvent;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.BufferTransfer;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.LPDataIOWrapper;\n\npublic class ClientPacketBufferHandlerThread {\n\n\tprivate final ClientCompressorThread clientCompressorThread = new ClientCompressorThread();\n\tprivate final ClientDecompressorThread clientDecompressorThread = new ClientDecompressorThread();\n\n\tpublic ClientPacketBufferHandlerThread() {}\n\n\tprivate static byte[] compress(byte[] content) {\n\t\tByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();\n\t\ttry {\n\t\t\tGZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);\n\t\t\tgzipOutputStream.write(content);\n\t\t\tgzipOutputStream.close();\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\treturn byteArrayOutputStream.toByteArray();\n\t}\n\n\tprivate static byte[] decompress(byte[] contentBytes) {\n\t\tByteArrayOutputStream out = new ByteArrayOutputStream();\n\t\ttry {\n\t\t\tGZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(contentBytes));\n\t\t\tint buffer;\n\t\t\twhile ((buffer = gzip.read()) != -1) {\n\t\t\t\tout.write(buffer);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\treturn out.toByteArray();\n\t}\n\n\tpublic void clientTick() {\n\t\tclientDecompressorThread.clientTickEnd();\n\t}\n\n\tpublic void setPause(boolean flag) {\n\t\tclientCompressorThread.setPause(flag);\n\t}\n\n\tpublic void addPacketToCompressor(ModernPacket packet) {\n\t\tclientCompressorThread.addPacketToCompressor(packet);\n\t}\n\n\tpublic void handlePacket(byte[] content) {\n\t\tclientDecompressorThread.handlePacket(content);\n\t}\n\n\tpublic void clear() {\n\t\tclientCompressorThread.clear();\n\t\tclientDecompressorThread.clear();\n\t}\n\n\tpublic void queuePacket(ModernPacket packet, EntityPlayer player) {\n\t\tclientDecompressorThread.queuePacket(packet, player);\n\t}\n\n\tprivate static class ClientCompressorThread extends Thread {\n\n\t\t//list of C->S packets to be serialized and compressed\n\t\tprivate final LinkedList<ModernPacket> clientList = new LinkedList<>();\n\t\t//serialized but still uncompressed C->S data\n\t\tprivate byte[] clientBuffer = new byte[] {};\n\t\t//used to cork the compressor so we can queue up a whole bunch of packets at once\n\t\tprivate boolean pause = false;\n\t\t//Clear content on next tick\n\t\tprivate boolean clear = false;\n\n\t\tprivate Lock clearLock = new ReentrantLock();\n\n\t\tpublic ClientCompressorThread() {\n\t\t\tsuper(\"LogisticsPipes Packet Compressor Client\");\n\t\t\tsetDaemon(true);\n\t\t\tstart();\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (true) {\n\t\t\t\tsynchronized (clientList) {\n\t\t\t\t\tif (!pause && clientList.size() > 0) {\n\t\t\t\t\t\tclientBuffer = LPDataIOWrapper.collectData(output -> {\n\t\t\t\t\t\t\toutput.writeBytes(clientBuffer);\n\t\t\t\t\t\t\tclearLock.lock();\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tfor (ModernPacket packet : clientList) {\n\t\t\t\t\t\t\t\t\toutput.writeByteArray(LPDataIOWrapper.collectData(dataOutput -> {\n\t\t\t\t\t\t\t\t\t\tdataOutput.writeShort(packet.getId());\n\t\t\t\t\t\t\t\t\t\tdataOutput.writeInt(packet.getDebugId());\n\t\t\t\t\t\t\t\t\t\tpacket.writeData(dataOutput);\n\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tclientList.clear();\n\t\t\t\t\t\t\t\tclearLock.unlock();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//Send Content\n\t\t\t\tif (clientBuffer.length > 0) {\n\t\t\t\t\twhile (clientBuffer.length > 1024 * 32) {\n\t\t\t\t\t\tbyte[] sendbuffer = Arrays.copyOf(clientBuffer, 1024 * 32);\n\t\t\t\t\t\tclientBuffer = Arrays.copyOfRange(clientBuffer, 1024 * 32, clientBuffer.length);\n\t\t\t\t\t\tbyte[] compressed = ClientPacketBufferHandlerThread.compress(sendbuffer);\n\t\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(BufferTransfer.class).setContent(compressed));\n\t\t\t\t\t}\n\t\t\t\t\tbyte[] sendbuffer = clientBuffer;\n\t\t\t\t\tclientBuffer = new byte[] {};\n\t\t\t\t\tbyte[] compressed = ClientPacketBufferHandlerThread.compress(sendbuffer);\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(BufferTransfer.class).setContent(compressed));\n\t\t\t\t}\n\t\t\t\tsynchronized (clientList) {\n\t\t\t\t\twhile (pause || clientList.size() == 0) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tclientList.wait();\n\t\t\t\t\t\t} catch (InterruptedException ignored) { }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (clear) {\n\t\t\t\t\tclear = false;\n\t\t\t\t\tclientBuffer = new byte[] {};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void addPacketToCompressor(ModernPacket packet) {\n\t\t\tsynchronized (clientList) {\n\t\t\t\tclientList.add(packet);\n\t\t\t\tif (!pause) {\n\t\t\t\t\tclientList.notify();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void setPause(boolean flag) {\n\t\t\tsynchronized (clientList) {\n\t\t\t\tpause = flag;\n\t\t\t\tif (!pause) {\n\t\t\t\t\tclientList.notify();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void clear() {\n\t\t\tclear = true;\n\t\t\tnew Thread() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tclearLock.lock();\n\t\t\t\t\tclientList.clear();\n\t\t\t\t\tclearLock.unlock();\n\t\t\t\t}\n\t\t\t}.start();\n\t\t}\n\t}\n\n\tprivate static class ClientDecompressorThread extends Thread {\n\n\t\t//Received compressed S->C data\n\t\tprivate final LinkedList<byte[]> queue = new LinkedList<>();\n\t\t//FIFO for deserialized S->C packets, decompressor adds, tickEnd removes\n\t\tprivate final LinkedList<Pair<EntityPlayer, byte[]>> PacketBuffer = new LinkedList<>();\n\t\tprivate final ReentrantLock packetBufferLock = new ReentrantLock();\n\t\t//List of packets that that should be reattempted to apply in the next tick\n\t\tprivate final LinkedList<Pair<EntityPlayer, ModernPacket>> retryPackets = new LinkedList<>();\n\t\tprivate final ReentrantLock retryPacketsLock = new ReentrantLock();\n\t\t//decompressed serialized S->C data\n\t\tprivate byte[] ByteBuffer = new byte[] {};\n\t\t//Clear content on next tick\n\t\tprivate boolean clear = false;\n\n\t\tpublic ClientDecompressorThread() {\n\t\t\tsuper(\"LogisticsPipes Packet Decompressor Client\");\n\t\t\tsetDaemon(true);\n\t\t\tstart();\n\t\t}\n\n\t\tprivate void handlePacketData(final Pair<EntityPlayer, byte[]> playerDataPair) {\n\t\t\tLPDataIOWrapper.provideData(playerDataPair.getValue2(), input -> PacketHandler.onPacketData(input, playerDataPair.getValue1()));\n\t\t}\n\n\t\tpublic void clientTickEnd() {\n\t\t\tPair<EntityPlayer, byte[]> part;\n\t\t\twhile (true) {\n\t\t\t\tpart = null;\n\t\t\t\tpacketBufferLock.lock();\n\t\t\t\ttry {\n\t\t\t\t\tif (PacketBuffer.size() > 0) {\n\t\t\t\t\t\tpart = PacketBuffer.pop();\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tpacketBufferLock.unlock();\n\t\t\t\t}\n\n\t\t\t\tif (part == null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\thandlePacketData(part);\n\t\t\t}\n\t\t\tPair<EntityPlayer, ModernPacket> partB;\n\t\t\twhile (true) {\n\t\t\t\tpartB = null;\n\t\t\t\tretryPacketsLock.lock();\n\t\t\t\ttry {\n\t\t\t\t\tif (retryPackets.size() > 0) {\n\t\t\t\t\t\tpartB = retryPackets.pop();\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tretryPacketsLock.unlock();\n\t\t\t\t}\n\n\t\t\t\tif (partB == null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tPacketHandler.onPacketData(partB.getValue2(), partB.getValue1());\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (true) {\n\t\t\t\tboolean flag;\n\t\t\t\tdo {\n\t\t\t\t\tflag = false;\n\t\t\t\t\tbyte[] buffer = null;\n\t\t\t\t\tsynchronized (queue) {\n\t\t\t\t\t\tif (queue.size() > 0) {\n\t\t\t\t\t\t\tflag = true;\n\t\t\t\t\t\t\tbuffer = queue.getFirst();\n\t\t\t\t\t\t\tqueue.removeFirst();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (flag && buffer != null) {\n\t\t\t\t\t\tbyte[] packetbytes = ClientPacketBufferHandlerThread.decompress(buffer);\n\t\t\t\t\t\tbyte[] newBuffer = new byte[packetbytes.length + ByteBuffer.length];\n\t\t\t\t\t\tSystem.arraycopy(ByteBuffer, 0, newBuffer, 0, ByteBuffer.length);\n\t\t\t\t\t\tSystem.arraycopy(packetbytes, 0, newBuffer, ByteBuffer.length, packetbytes.length);\n\t\t\t\t\t\tByteBuffer = newBuffer;\n\t\t\t\t\t}\n\t\t\t\t} while (flag);\n\n\t\t\t\twhile (ByteBuffer.length >= 4) {\n\t\t\t\t\tint size = ((ByteBuffer[0] & 255) << 24) + ((ByteBuffer[1] & 255) << 16) + ((ByteBuffer[2] & 255) << 8) + ((ByteBuffer[3] & 255) << 0);\n\t\t\t\t\tif (size + 4 > ByteBuffer.length) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbyte[] packet = Arrays.copyOfRange(ByteBuffer, 4, size + 4);\n\t\t\t\t\tByteBuffer = Arrays.copyOfRange(ByteBuffer, size + 4, ByteBuffer.length);\n\t\t\t\t\tpacketBufferLock.lock();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tPacketBuffer.add(new Pair<>(MainProxy.proxy.getClientPlayer(), packet));\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tpacketBufferLock.unlock();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsynchronized (queue) {\n\t\t\t\t\twhile (queue.size() == 0) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tqueue.wait();\n\t\t\t\t\t\t} catch (InterruptedException ignored) { }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (clear) {\n\t\t\t\t\tclear = false;\n\t\t\t\t\tByteBuffer = new byte[] {};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void handlePacket(byte[] content) {\n\t\t\tsynchronized (queue) {\n\t\t\t\tqueue.addLast(content);\n\t\t\t\tqueue.notify();\n\t\t\t}\n\t\t}\n\n\t\tpublic void clear() {\n\t\t\tclear = true;\n\t\t\tqueue.clear();\n\t\t\tretryPackets.clear();\n\t\t}\n\n\t\tpublic void queuePacket(ModernPacket packet, EntityPlayer player) {\n\t\t\tretryPackets.add(new Pair<>(player, packet));\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/HudUpdateTick.java",
    "content": "package logisticspipes.ticks;\n\nimport java.util.BitSet;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.IRouter;\n\npublic class HudUpdateTick {\n\n\tprivate static BitSet routersNeedingUpdate = new BitSet(4096);\n\tprivate static int firstRouter = -1;\n\tprivate static int inventorySlotsToUpdatePerTick = 90;\n\n\tpublic HudUpdateTick() {}\n\n\tpublic static void clearUpdateFlags() {\n\t\tHudUpdateTick.routersNeedingUpdate.clear();\n\t}\n\n\tpublic static void add(IRouter run) {\n\t\tint index = run.getSimpleID();\n\t\tif (index < 0) {\n\t\t\treturn;\n\t\t}\n\t\tHudUpdateTick.routersNeedingUpdate.set(index); //expands the bit-set when out of bounds.\n\t\tif (HudUpdateTick.firstRouter == -1) {\n\t\t\tHudUpdateTick.firstRouter = index;\n\t\t}\n\t}\n\n\tpublic static void tick() {\n\t\tif (HudUpdateTick.firstRouter == -1) {\n\t\t\treturn;\n\t\t}\n\t\tint slotSentCount = 0;\n\t\t//cork the compressor\n\t\tSimpleServiceLocator.serverBufferHandler.setPause(true);\n\t\twhile (HudUpdateTick.firstRouter != -1 && slotSentCount < HudUpdateTick.inventorySlotsToUpdatePerTick) {\n\t\t\tHudUpdateTick.routersNeedingUpdate.clear(HudUpdateTick.firstRouter);\n\t\t\tIRouter currentRouter = SimpleServiceLocator.routerManager.getServerRouter(HudUpdateTick.firstRouter);\n\t\t\tif (currentRouter != null) {\n\t\t\t\tCoreRoutedPipe pipe = currentRouter.getCachedPipe();\n\t\t\t\tif (pipe != null) {\n\t\t\t\t\tslotSentCount += pipe.sendQueueChanged(true);\n\t\t\t\t}\n\t\t\t}\n\t\t\tHudUpdateTick.firstRouter = HudUpdateTick.routersNeedingUpdate.nextSetBit(HudUpdateTick.firstRouter);\n\t\t}\n\t\t//and let it compress and send\n\t\tSimpleServiceLocator.serverBufferHandler.setPause(false);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/LPTickHandler.java",
    "content": "package logisticspipes.ticks;\n\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.Phase;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.WorldTickEvent;\nimport net.minecraftforge.fml.relauncher.Side;\n\nimport com.google.common.collect.MapMaker;\nimport lombok.AccessLevel;\nimport lombok.Data;\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.commands.commands.debug.DebugGuiController;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.FluidIdentifier;\nimport network.rs485.grow.ServerTickDispatcher;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LPTickHandler {\n\n\tpublic static int adjChecksDone = 0;\n\n\t@SubscribeEvent\n\tpublic void clientTick(ClientTickEvent event) {\n\t\tif (event.phase == Phase.END) {\n\t\t\tFluidIdentifier.initFromForge(true);\n\t\t\tSimpleServiceLocator.clientBufferHandler.clientTick();\n\t\t\tMainProxy.proxy.tickClient();\n\t\t\tDebugGuiController.instance().execClient();\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void serverTick(ServerTickEvent event) {\n\t\tif (event.phase == Phase.END) {\n\t\t\tHudUpdateTick.tick();\n\t\t\tSimpleServiceLocator.serverBufferHandler.serverTick();\n\t\t\tMainProxy.proxy.tickServer();\n\t\t\tLPTickHandler.adjChecksDone = 0;\n\t\t\tDebugGuiController.instance().execServer();\n\t\t\tServerTickDispatcher.INSTANCE.tick();\n\t\t}\n\t}\n\n\tprivate static Map<World, LPWorldInfo> worldInfo = new MapMaker().weakKeys().makeMap();\n\n\t@SubscribeEvent\n\tpublic void worldTick(WorldTickEvent event) {\n\t\tif (event.phase != Phase.END) {\n\t\t\treturn;\n\t\t}\n\t\tif (event.side != Side.SERVER) {\n\t\t\treturn;\n\t\t}\n\t\tLPWorldInfo info = LPTickHandler.getWorldInfo(event.world);\n\t\tinfo.worldTick++;\n\t}\n\n\tpublic static LPWorldInfo getWorldInfo(World world) {\n\t\tLPWorldInfo info = LPTickHandler.worldInfo.get(world);\n\t\tif (info == null) {\n\t\t\tinfo = new LPWorldInfo();\n\t\t\tLPTickHandler.worldInfo.put(world, info);\n\t\t}\n\t\treturn info;\n\t}\n\n\t@Data\n\tpublic static class LPWorldInfo {\n\n\t\t@Getter\n\t\t@Setter(value = AccessLevel.PRIVATE)\n\t\tprivate long worldTick = 0;\n\t\t@Getter\n\t\tprivate Set<DoubleCoordinates> updateQueued = new HashSet<>();\n\n\t\t@Getter\n\t\t@Setter\n\t\tprivate boolean skipBlockUpdateForWorld = false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/QueuedTasks.java",
    "content": "package logisticspipes.ticks;\n\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.concurrent.Callable;\n\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.Phase;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent;\n\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.transport.LPTravelingItem;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class QueuedTasks {\n\n\t@SuppressWarnings(\"rawtypes\")\n\tprivate static LinkedList<Callable> queue = new LinkedList<>();\n\n\t// called on server shutdown only.\n\tpublic static void clearAllTasks() {\n\t\tQueuedTasks.queue.clear();\n\t}\n\n\t@SuppressWarnings(\"rawtypes\")\n\tpublic static void queueTask(Callable task) {\n\t\tsynchronized (QueuedTasks.queue) {\n\t\t\tQueuedTasks.queue.add(task);\n\t\t}\n\t}\n\n\t@SuppressWarnings({ \"rawtypes\" })\n\t@SubscribeEvent\n\tpublic void tickEnd(ServerTickEvent event) {\n\t\tif (event.phase != Phase.END) {\n\t\t\treturn;\n\t\t}\n\t\tCallable call;\n\t\twhile (!QueuedTasks.queue.isEmpty()) {\n\t\t\tsynchronized (QueuedTasks.queue) {\n\t\t\t\tcall = QueuedTasks.queue.removeFirst();\n\t\t\t}\n\t\t\tif (call != null) {\n\t\t\t\ttry {\n\t\t\t\t\tcall.call();\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tMainProxy.proxy.tick();\n\t\tsynchronized (LPTravelingItem.forceKeep) {\n\t\t\tIterator<Pair<Integer, Object>> iter = LPTravelingItem.forceKeep.iterator();\n\t\t\twhile (iter.hasNext()) {\n\t\t\t\tPair<Integer, Object> pair = iter.next();\n\t\t\t\tpair.setValue1(pair.getValue1() - 1);\n\t\t\t\tif (pair.getValue1() < 0) {\n\t\t\t\t\titer.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/RenderTickHandler.java",
    "content": "package logisticspipes.ticks;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.ActiveRenderInfo;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.InventoryPlayer;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.event.RenderWorldLastEvent;\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.common.eventhandler.EventPriority;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.Phase;\nimport net.minecraftforge.fml.common.gameevent.TickEvent.RenderTickEvent;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.interfaces.ITubeOrientation;\nimport logisticspipes.items.ItemLogisticsPipe;\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.renderer.GuiOverlay;\nimport logisticspipes.renderer.LogisticsHUDRenderer;\nimport logisticspipes.routing.debug.ClientViewController;\nimport logisticspipes.utils.LPPositionSet;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\nimport network.rs485.logisticspipes.world.DoubleCoordinatesType;\n\npublic class RenderTickHandler {\n\n\tprivate long renderTicks = 0;\n\n\t@SubscribeEvent(priority = EventPriority.HIGHEST)\n\tpublic void renderTick(RenderTickEvent event) {\n\t\tif (event.phase == Phase.START) {\n\t\t\tif (GuiOverlay.getInstance().isCompatibleGui()) {\n\t\t\t\tGuiOverlay.getInstance().preRender();\n\t\t\t}\n\t\t\tClientViewController.instance().tick();\n\t\t} else {\n\t\t\trenderTicks++;\n\t\t\tif (LogisticsHUDRenderer.instance().displayRenderer()) {\n\t\t\t\tGL11.glPushMatrix();\n\t\t\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\t\t\tmc.entityRenderer.setupCameraTransform(event.renderTickTime, 1);\n\t\t\t\tActiveRenderInfo.updateRenderInfo(mc.player, mc.gameSettings.thirdPersonView == 2);\n\t\t\t\tLogisticsHUDRenderer.instance().renderWorldRelative(renderTicks, event.renderTickTime);\n\t\t\t\tmc.entityRenderer.setupOverlayRendering();\n\t\t\t\tGL11.glPopMatrix();\n\n\t\t\t\tGL11.glPushMatrix();\n\t\t\t\tLogisticsHUDRenderer.instance().renderPlayerDisplay(renderTicks);\n\t\t\t\tGL11.glPopMatrix();\n\t\t\t} else if (GuiOverlay.getInstance().isCompatibleGui()) {\n\t\t\t\tGuiOverlay.getInstance().renderOverGui();\n\t\t\t}\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\t@SideOnly(Side.CLIENT)\n\tpublic void renderWorldLast(RenderWorldLastEvent worldEvent) {\n\t\t// We are not holding an Item that needs to render a ghost pipe!\n\t\tif (!displayPipeGhost()) return;\n\n\t\tMinecraft mc = Minecraft.getMinecraft();\n\t\tEntityPlayer player = mc.player;\n\t\tRayTraceResult box = mc.objectMouseOver;\n\n\t\t// The box is null or we are targeting something else than a block!\n\t\tif (box == null || box.typeOfHit != RayTraceResult.Type.BLOCK) return;\n\n\t\tInventoryPlayer inventory = FMLClientHandler.instance().getClient().player.inventory;\n\t\tItemStack stack = inventory.mainInventory.get(inventory.currentItem);\n\t\tCoreUnroutedPipe pipe = ((ItemLogisticsPipe) stack.getItem()).getDummyPipe();\n\t\tWorld world = player.getEntityWorld();\n\t\tEnumFacing side = box.sideHit;\n\t\tBlockPos pos = box.getBlockPos();\n\t\tBlock block = world.getBlockState(pos).getBlock();\n\n\t\tif (block == Blocks.SNOW_LAYER && block.isReplaceable(world, pos)) {\n\t\t\tside = EnumFacing.UP;\n\t\t} else if (!block.isReplaceable(world, pos)) {\n\t\t\tpos = pos.offset(side);\n\t\t}\n\n\t\tboolean isFreeSpace = true;\n\t\tITubeOrientation orientation = null;\n\n\t\tif (pipe instanceof CoreMultiBlockPipe) {\n\t\t\tCoreMultiBlockPipe multiPipe = (CoreMultiBlockPipe) pipe;\n\t\t\tDoubleCoordinates placeAt = new DoubleCoordinates(pos);\n\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> globalPos = new LPPositionSet<>(DoubleCoordinatesType.class);\n\t\t\tglobalPos.add(new DoubleCoordinatesType<>(placeAt, CoreMultiBlockPipe.SubBlockTypeForShare.NON_SHARE));\n\t\t\tLPPositionSet<DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare>> positions = multiPipe.getSubBlocks();\n\t\t\torientation = multiPipe.getTubeOrientation(player, pos.getX(), pos.getZ());\n\n\t\t\tif (orientation == null) return;\n\n\t\t\torientation.rotatePositions(positions);\n\t\t\tpositions.stream().map(p -> p.add(placeAt)).forEach(globalPos::add);\n\t\t\tglobalPos.addToAll(orientation.getOffset());\n\n\t\t\tfor (DoubleCoordinatesType<CoreMultiBlockPipe.SubBlockTypeForShare> posType : globalPos) {\n\t\t\t\tif (!world.mayPlace(LPBlocks.pipe, posType.getBlockPos(), false, side, player)) {\n\t\t\t\t\tTileEntity tile = world.getTileEntity(posType.getBlockPos());\n\t\t\t\t\tboolean canPlace = false;\n\t\t\t\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\t\t\t\tif (CoreMultiBlockPipe.canShare(((LogisticsTileGenericSubMultiBlock) tile).getSubTypes(), posType.getType())) {\n\t\t\t\t\t\t\tcanPlace = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!canPlace) {\n\t\t\t\t\t\tisFreeSpace = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (!world.mayPlace(LPBlocks.pipe, pos, false, side, player)) {\n\t\t\t\tisFreeSpace = false;\n\t\t\t}\n\t\t}\n\n\t\t// No free space to render anything!\n\t\tif (!isFreeSpace) return;\n\n\t\tGlStateManager.pushMatrix();\n\t\tdouble x;\n\t\tdouble y;\n\t\tdouble z;\n\t\tif (orientation != null) {\n\t\t\tx = pos.getX() + orientation.getOffset().getXInt() - player.prevPosX - ((player.posX - player.prevPosX) * worldEvent.getPartialTicks());\n\t\t\ty = pos.getY() + orientation.getOffset().getYInt() - player.prevPosY - ((player.posY - player.prevPosY) * worldEvent.getPartialTicks());\n\t\t\tz = pos.getZ() + orientation.getOffset().getZInt() - player.prevPosZ - ((player.posZ - player.prevPosZ) * worldEvent.getPartialTicks());\n\t\t} else {\n\t\t\tx = pos.getX() - player.prevPosX - ((player.posX - player.prevPosX) * worldEvent.getPartialTicks());\n\t\t\ty = pos.getY() - player.prevPosY - ((player.posY - player.prevPosY) * worldEvent.getPartialTicks());\n\t\t\tz = pos.getZ() - player.prevPosZ - ((player.posZ - player.prevPosZ) * worldEvent.getPartialTicks());\n\t\t}\n\t\tGL11.glTranslated(x + 0.001, y + 0.001, z + 0.001);\n\n\t\tGlStateManager.enableBlend();\n\t\tGlStateManager.disableTexture2D();\n\t\tGL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\n\t\tmc.renderEngine.bindTexture(new ResourceLocation(\"logisticspipes\", \"textures/blocks/pipes/white.png\"));\n\n\t\tSimpleServiceLocator.cclProxy.getRenderState().reset();\n\t\tSimpleServiceLocator.cclProxy.getRenderState().setAlphaOverride(0xff);\n\n\t\tGlStateManager.enableTexture2D();\n\n\t\tSimpleServiceLocator.cclProxy.getRenderState().setAlphaOverride(0x50);\n\t\tSimpleServiceLocator.cclProxy.getRenderState().startDrawing(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);\n\n\t\tpipe.getHighlightRenderer().renderHighlight(orientation);\n\n\t\tSimpleServiceLocator.cclProxy.getRenderState().draw();\n\n\t\tSimpleServiceLocator.cclProxy.getRenderState().setAlphaOverride(0xff);\n\t\tGlStateManager.disableBlend();\n\t\tGlStateManager.depthMask(true);\n\t\tGlStateManager.popMatrix();\n\t}\n\n\tprivate boolean displayPipeGhost() {\n\t\tEntityPlayer player = FMLClientHandler.instance().getClient().player;\n\t\tif (player == null) return false;\n\n\t\tInventoryPlayer pInventory = player.inventory;\n\t\tif (pInventory == null) return false;\n\n\t\tNonNullList<ItemStack> inv = pInventory.mainInventory;\n\t\tif (inv == null) return false;\n\n\t\treturn inv.size() > pInventory.currentItem\n\t\t\t\t&& inv.get(pInventory.currentItem).getItem() instanceof ItemLogisticsPipe;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/RoutingTableUpdateThread.java",
    "content": "package logisticspipes.ticks;\n\nimport java.util.concurrent.PriorityBlockingQueue;\n\nimport logisticspipes.config.Configs;\n\npublic class RoutingTableUpdateThread extends Thread {\n\n\tprivate static PriorityBlockingQueue<Runnable> updateCalls = new PriorityBlockingQueue<>();\n\n\tprivate static Long average = 0L;\n\n\tpublic RoutingTableUpdateThread(int i) {\n\t\tsuper(\"LogisticsPipes RoutingTableUpdateThread #\" + i);\n\t\tsetDaemon(true);\n\t\tsetPriority(Configs.MULTI_THREAD_PRIORITY);\n\t\tstart();\n\t}\n\n\tpublic static void add(Runnable run) {\n\t\tRoutingTableUpdateThread.updateCalls.add(run);\n\t}\n\n\tpublic static boolean remove(Runnable run) {\n\t\treturn RoutingTableUpdateThread.updateCalls.remove(run);\n\t}\n\n\tpublic static int size() {\n\t\treturn RoutingTableUpdateThread.updateCalls.size();\n\t}\n\n\tpublic static long getAverage() {\n\t\tsynchronized (RoutingTableUpdateThread.average) {\n\t\t\treturn RoutingTableUpdateThread.average;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void run() {\n\t\tRunnable item;\n\t\t// take blocks until things are available, no need to check\n\t\ttry {\n\t\t\twhile ((item = RoutingTableUpdateThread.updateCalls.take()) != null) {\n\t\t\t\tlong starttime = System.nanoTime();\n\t\t\t\titem.run();\n\t\t\t\tlong took = System.nanoTime() - starttime;\n\t\t\t\tsynchronized (RoutingTableUpdateThread.average) {\n\t\t\t\t\tif (RoutingTableUpdateThread.average == 0) {\n\t\t\t\t\t\tRoutingTableUpdateThread.average = took;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRoutingTableUpdateThread.average = ((RoutingTableUpdateThread.average * 999L) + took) / 1000L;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (InterruptedException ignored) {\n\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/ServerPacketBufferHandlerThread.java",
    "content": "package logisticspipes.ticks;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.lang.ref.WeakReference;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.Map.Entry;\nimport java.util.Queue;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.zip.GZIPInputStream;\nimport java.util.zip.GZIPOutputStream;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.BufferTransfer;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.util.LPDataIOWrapper;\n\npublic class ServerPacketBufferHandlerThread {\n\n\tprivate final ServerCompressorThread serverCompressorThread = new ServerCompressorThread();\n\tprivate final ServerDecompressorThread serverDecompressorThread = new ServerDecompressorThread();\n\n\tpublic ServerPacketBufferHandlerThread() {}\n\n\tprivate static byte[] compress(byte[] content) {\n\t\tByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();\n\t\ttry {\n\t\t\tGZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);\n\t\t\tgzipOutputStream.write(content);\n\t\t\tgzipOutputStream.close();\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\treturn byteArrayOutputStream.toByteArray();\n\t}\n\n\tprivate static byte[] decompress(byte[] contentBytes) {\n\t\tByteArrayOutputStream out = new ByteArrayOutputStream();\n\t\ttry {\n\t\t\tGZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(contentBytes));\n\t\t\tint buffer;\n\t\t\twhile ((buffer = gzip.read()) != -1) {\n\t\t\t\tout.write(buffer);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\treturn out.toByteArray();\n\t}\n\n\tpublic void serverTick() {\n\t\tserverDecompressorThread.serverTickEnd();\n\t}\n\n\tpublic void setPause(boolean flag) {\n\t\tserverCompressorThread.setPause(flag);\n\t}\n\n\tpublic void addPacketToCompressor(ModernPacket packet, EntityPlayer player) {\n\t\tserverCompressorThread.addPacketToCompressor(packet, player);\n\t}\n\n\tpublic void handlePacket(byte[] content, EntityPlayer player) {\n\t\tserverDecompressorThread.handlePacket(content, player);\n\t}\n\n\tpublic void clear(final EntityPlayer player) {\n\t\tnew Thread(() -> {\n\t\t\tserverCompressorThread.clear(player);\n\t\t\tserverDecompressorThread.clear(player);\n\t\t}).start();\n\t}\n\n\tprivate static class ServerCompressorThread extends Thread {\n\n\t\t//Map of Players to lists of S->C packets to be serialized and compressed\n\t\tprivate final HashMap<EntityPlayer, LinkedList<ModernPacket>> serverList = new HashMap<>();\n\t\t//Map of Players to serialized but still uncompressed S->C data\n\t\tprivate final HashMap<EntityPlayer, byte[]> serverBuffer = new HashMap<>();\n\t\t//used to cork the compressor so we can queue up a whole bunch of packets at once\n\t\tprivate boolean pause = false;\n\t\t//Clear content on next tick (wrapped in weak ref to prevent leakage, only important if the maps hold a ref)\n\t\tprivate final Queue<WeakReference<EntityPlayer>> playersToClear = new LinkedList<>();\n\n\t\tpublic ServerCompressorThread() {\n\t\t\tsuper(\"LogisticsPipes Packet Compressor Server\");\n\t\t\tsetDaemon(true);\n\t\t\tstart();\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (true) {\n\t\t\t\tsynchronized (serverList) {\n\t\t\t\t\tif (!pause) {\n\t\t\t\t\t\tfor (Entry<EntityPlayer, LinkedList<ModernPacket>> playerPacketEntry : serverList.entrySet()) {\n\t\t\t\t\t\t\tEntityPlayer player = playerPacketEntry.getKey();\n\t\t\t\t\t\t\tserverBuffer.put(player, LPDataIOWrapper.collectData(output -> {\n\t\t\t\t\t\t\t\tif (serverBuffer.containsKey(player)) {\n\t\t\t\t\t\t\t\t\toutput.writeBytes(serverBuffer.get(player));\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tLinkedList<ModernPacket> packets = playerPacketEntry.getValue();\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tfor (ModernPacket packet : packets) {\n\t\t\t\t\t\t\t\t\t\toutput.writeByteArray(LPDataIOWrapper.collectData(dataOutput -> {\n\t\t\t\t\t\t\t\t\t\t\tdataOutput.writeShort(packet.getId());\n\t\t\t\t\t\t\t\t\t\t\tdataOutput.writeInt(packet.getDebugId());\n\t\t\t\t\t\t\t\t\t\t\tpacket.writeData(dataOutput);\n\t\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\t\tpackets.clear();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tserverList.clear();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t//Send Content\n\t\t\t\tfor (Entry<EntityPlayer, byte[]> player : serverBuffer.entrySet()) {\n\t\t\t\t\twhile (player.getValue().length > 32 * 1024) {\n\t\t\t\t\t\tbyte[] sendbuffer = Arrays.copyOf(player.getValue(), 1024 * 32);\n\t\t\t\t\t\tbyte[] newbuffer = Arrays.copyOfRange(player.getValue(), 1024 * 32, player.getValue().length);\n\t\t\t\t\t\tplayer.setValue(newbuffer);\n\t\t\t\t\t\tbyte[] compressed = ServerPacketBufferHandlerThread.compress(sendbuffer);\n\t\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(BufferTransfer.class).setContent(compressed), player.getKey());\n\t\t\t\t\t}\n\t\t\t\t\tbyte[] sendbuffer = player.getValue();\n\t\t\t\t\tbyte[] compressed = ServerPacketBufferHandlerThread.compress(sendbuffer);\n\t\t\t\t\tMainProxy.sendPacketToPlayer(PacketHandler.getPacket(BufferTransfer.class).setContent(compressed), player.getKey());\n\t\t\t\t}\n\t\t\t\tserverBuffer.clear();\n\t\t\t\tsynchronized (serverList) {\n\t\t\t\t\twhile (pause || serverList.size() == 0) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tserverList.wait();\n\t\t\t\t\t\t} catch (InterruptedException ignored) { }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsynchronized (playersToClear) {\n\t\t\t\t\tWeakReference<EntityPlayer> playerRef;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tplayerRef = playersToClear.poll();\n\t\t\t\t\t\tif (playerRef != null) {\n\t\t\t\t\t\t\tfinal EntityPlayer player = playerRef.get();\n\t\t\t\t\t\t\tif (player != null) {\n\t\t\t\t\t\t\t\tserverBuffer.remove(player);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} while (playerRef != null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void addPacketToCompressor(ModernPacket packet, EntityPlayer player) {\n\t\t\tsynchronized (serverList) {\n\t\t\t\tLinkedList<ModernPacket> packetList = serverList.computeIfAbsent(player, k -> new LinkedList<>());\n\t\t\t\tpacketList.add(packet);\n\t\t\t\tif (!pause) {\n\t\t\t\t\tserverList.notify();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void setPause(boolean flag) {\n\t\t\tsynchronized (serverList) {\n\t\t\t\tpause = flag;\n\t\t\t\tif (!pause) {\n\t\t\t\t\tserverList.notify();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void clear(EntityPlayer player) {\n\t\t\tsynchronized (serverList) {\n\t\t\t\tserverList.remove(player);\n\t\t\t}\n\t\t\tsynchronized (playersToClear) {\n\t\t\t\tplayersToClear.add(new WeakReference<>(player));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static class ServerDecompressorThread extends Thread {\n\n\t\t//Map of Player to received compressed C->S data\n\t\tprivate final HashMap<EntityPlayer, LinkedList<byte[]>> queue = new HashMap<>();\n\t\t//Map of Player to decompressed serialized C->S data\n\t\tprivate final HashMap<EntityPlayer, byte[]> ByteBuffer = new HashMap<>();\n\t\t//FIFO for deserialized C->S packets, decompressor adds, tickEnd removes\n\t\tprivate final LinkedList<Pair<EntityPlayer, byte[]>> PacketBuffer = new LinkedList<>();\n\t\tprivate final ReentrantLock packetBufferLock = new ReentrantLock();\n\t\t//Clear content on next tick (wrapped in weak ref to prevent leakage, only important if the maps hold a ref)\n\t\tprivate final Queue<WeakReference<EntityPlayer>> playersToClear = new LinkedList<>();\n\n\t\tpublic ServerDecompressorThread() {\n\t\t\tsuper(\"LogisticsPipes Packet Decompressor Server\");\n\t\t\tsetDaemon(true);\n\t\t\tstart();\n\t\t}\n\n\t\tprivate void handlePacketData(final Pair<EntityPlayer, byte[]> playerDataPair) {\n\t\t\tLPDataIOWrapper.provideData(playerDataPair.getValue2(), input -> {\n\t\t\t\tPacketHandler.onPacketData(input, playerDataPair.getValue1());\n\t\t\t});\n\t\t}\n\n\t\tpublic void serverTickEnd() {\n\t\t\tPair<EntityPlayer, byte[]> part;\n\t\t\twhile (true) {\n\t\t\t\tpart = null;\n\t\t\t\tpacketBufferLock.lock();\n\t\t\t\ttry {\n\t\t\t\t\tif (PacketBuffer.size() > 0) {\n\t\t\t\t\t\tpart = PacketBuffer.pop();\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tpacketBufferLock.unlock();\n\t\t\t\t}\n\n\t\t\t\tif (part == null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\thandlePacketData(part);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (true) {\n\t\t\t\tboolean flag;\n\t\t\t\tdo {\n\t\t\t\t\tflag = false;\n\t\t\t\t\tbyte[] buffer = null;\n\t\t\t\t\tEntityPlayer player = null;\n\t\t\t\t\tsynchronized (queue) {\n\t\t\t\t\t\tif (queue.size() > 0) {\n\t\t\t\t\t\t\tfor (Iterator<Entry<EntityPlayer, LinkedList<byte[]>>> it = queue.entrySet().iterator(); it.hasNext(); ) {\n\t\t\t\t\t\t\t\tEntry<EntityPlayer, LinkedList<byte[]>> lPlayer = it.next();\n\t\t\t\t\t\t\t\tif (lPlayer.getValue().size() > 0) {\n\t\t\t\t\t\t\t\t\tflag = true;\n\t\t\t\t\t\t\t\t\tbuffer = lPlayer.getValue().getFirst();\n\t\t\t\t\t\t\t\t\tplayer = lPlayer.getKey();\n\t\t\t\t\t\t\t\t\tif (lPlayer.getValue().size() > 1) {\n\t\t\t\t\t\t\t\t\t\tlPlayer.getValue().removeFirst();\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tit.remove();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tit.remove();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (flag && buffer != null && player != null) {\n\t\t\t\t\t\tbyte[] ByteBufferForPlayer = ByteBuffer.computeIfAbsent(player, k -> new byte[] {});\n\t\t\t\t\t\tbyte[] packetbytes = ServerPacketBufferHandlerThread.decompress(buffer);\n\t\t\t\t\t\tbyte[] newBuffer = new byte[packetbytes.length + ByteBufferForPlayer.length];\n\t\t\t\t\t\tSystem.arraycopy(ByteBufferForPlayer, 0, newBuffer, 0, ByteBufferForPlayer.length);\n\t\t\t\t\t\tSystem.arraycopy(packetbytes, 0, newBuffer, ByteBufferForPlayer.length, packetbytes.length);\n\t\t\t\t\t\tByteBuffer.put(player, newBuffer);\n\t\t\t\t\t}\n\t\t\t\t} while (flag);\n\n\t\t\t\tfor (Entry<EntityPlayer, byte[]> player : ByteBuffer.entrySet()) {\n\t\t\t\t\twhile (player.getValue().length >= 4) {\n\t\t\t\t\t\tbyte[] ByteBufferForPlayer = player.getValue();\n\t\t\t\t\t\tint size = ((ByteBufferForPlayer[0] & 255) << 24) + ((ByteBufferForPlayer[1] & 255) << 16) + ((ByteBufferForPlayer[2] & 255) << 8) + ((ByteBufferForPlayer[3] & 255) << 0);\n\t\t\t\t\t\tif (size + 4 > ByteBufferForPlayer.length) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbyte[] packet = Arrays.copyOfRange(ByteBufferForPlayer, 4, size + 4);\n\t\t\t\t\t\tByteBufferForPlayer = Arrays.copyOfRange(ByteBufferForPlayer, size + 4, ByteBufferForPlayer.length);\n\t\t\t\t\t\tplayer.setValue(ByteBufferForPlayer);\n\t\t\t\t\t\tpacketBufferLock.lock();\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tPacketBuffer.add(new Pair<>(player.getKey(), packet));\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tpacketBufferLock.unlock();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tByteBuffer.values().removeIf(ByteBufferForPlayer -> ByteBufferForPlayer.length == 0);\n\n\t\t\t\tsynchronized (queue) {\n\t\t\t\t\twhile (queue.size() == 0) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tqueue.wait();\n\t\t\t\t\t\t} catch (InterruptedException ignored) { }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsynchronized (playersToClear) {\n\t\t\t\t\tWeakReference<EntityPlayer> playerRef;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tplayerRef = playersToClear.poll();\n\t\t\t\t\t\tif (playerRef != null) {\n\t\t\t\t\t\t\tfinal EntityPlayer player = playerRef.get();\n\t\t\t\t\t\t\tif (player != null) {\n\t\t\t\t\t\t\t\tByteBuffer.remove(player);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} while (playerRef != null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpublic void handlePacket(byte[] content, EntityPlayer player) {\n\t\t\tsynchronized (queue) {\n\t\t\t\tLinkedList<byte[]> list = queue.computeIfAbsent(player, k -> new LinkedList<>());\n\t\t\t\tlist.addLast(content);\n\t\t\t\tqueue.notify();\n\t\t\t}\n\t\t}\n\n\t\tpublic void clear(EntityPlayer player) {\n\t\t\tsynchronized (queue) {\n\t\t\t\tqueue.remove(player);\n\t\t\t}\n\t\t\tsynchronized (playersToClear) {\n\t\t\t\tplayersToClear.add(new WeakReference<>(player));\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/ticks/VersionChecker.java",
    "content": "package logisticspipes.ticks;\n\nimport java.io.InputStream;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Scanner;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\n\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport net.minecraftforge.fml.common.Loader;\nimport net.minecraftforge.fml.common.event.FMLInterModComms;\n\nimport com.google.gson.Gson;\nimport com.google.gson.internal.LinkedTreeMap;\nimport lombok.Data;\n\nimport logisticspipes.LogisticsPipes;\n\npublic final class VersionChecker implements Callable<VersionChecker.VersionInfo> {\n\n\tpublic static final int COMMIT_MAX_LINE_LENGTH = 60;\n\n\tprivate static Future<VersionInfo> versionCheckFuture;\n\tprivate String statusString;\n\tprivate VersionInfo versionInfo = null;\n\n\tprivate VersionChecker() {\n\t}\n\n\tpublic static VersionChecker runVersionCheck() {\n\t\tVersionChecker obj = new VersionChecker();\n\t\tversionCheckFuture = LogisticsPipes.singleThreadExecutor.submit(obj);\n\t\treturn obj;\n\t}\n\n\tpublic String getVersionCheckerStatus() {\n\t\tif (versionCheckFuture != null) {\n\t\t\tif (versionCheckFuture.isDone()) {\n\t\t\t\t// has to be done, before getting final string and setting to null\n\t\t\t\tstatusString = internalGetVersionCheckerStatus();\n\t\t\t\tversionCheckFuture = null;\n\t\t\t} else {\n\t\t\t\tstatusString = internalGetVersionCheckerStatus();\n\t\t\t}\n\t\t}\n\t\treturn statusString;\n\t}\n\n\tpublic boolean isVersionCheckDone() {\n\t\treturn versionInfo != null;\n\t}\n\n\tpublic VersionInfo getVersionInfo() {\n\t\treturn versionInfo;\n\t}\n\n\tprivate String internalGetVersionCheckerStatus() {\n\t\tif (versionCheckFuture.isDone()) {\n\t\t\ttry {\n\t\t\t\tversionInfo = versionCheckFuture.get();\n\t\t\t\tif (versionInfo == null) {\n\t\t\t\t\tif (LogisticsPipes.isDevelopmentEnvironment()) {\n\t\t\t\t\t\treturn \"You are running Logistics Pipes from a development environment.\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn \"It seems you are missing the current version information on Logistics Pipes. There is no version checking available.\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (versionInfo.isNewVersionAvailable()) {\n\t\t\t\t\t\treturn \"New Logistics Pipes build found: #\" + versionInfo.getNewestBuild();\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn \"You have the newest Logistics Pipes build :)\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\treturn \"The version check task was interrupted and there is no version information available.\";\n\t\t\t} catch (ExecutionException e) {\n\t\t\t\tLogisticsPipes.log.warn(\"The version check task had an exception while getting the newest version information\", e);\n\t\t\t\treturn \"The version check task had an exception. See the log file for more information.\";\n\t\t\t}\n\t\t} else {\n\t\t\treturn \"The version check is not yet ready, sorry.\";\n\t\t}\n\t}\n\n\t@Override\n\tpublic VersionInfo call() throws Exception {\n\t\tif (LogisticsPipes.UNKNOWN.equals(LogisticsPipes.getVERSION())) {\n\t\t\treturn null;\n\t\t}\n\n\t\tVersionInfo versionInfo = new VersionInfo();\n\t\tURL url = new URL(String.format(\"http://rs485.network/version?VERSION=%s:%b\", LogisticsPipes.getVERSION(), LogisticsPipes.isDEBUG()));\n\t\tHttpURLConnection conn = (HttpURLConnection) url.openConnection();\n\t\tInputStream inputStream = (InputStream) conn.getContent();\n\t\tString jsonString;\n\t\ttry (Scanner sc = new Scanner(inputStream)) {\n\t\t\tsc.useDelimiter(\"\\\\A\");\n\t\t\tjsonString = sc.next();\n\t\t}\n\n\t\tGson gson = new Gson();\n\t\tLinkedTreeMap part = gson.fromJson(jsonString, LinkedTreeMap.class);\n\n\t\tBoolean hasNew = (Boolean) part.get(\"new\");\n\t\tversionInfo.setNewVersionAvailable(hasNew);\n\t\tif (hasNew) {\n\t\t\tversionInfo.setNewestBuild(String.valueOf(part.get(\"build\")));\n\t\t\tLogisticsPipes.log.info(\"New Logistics Pipes build found: #\" + versionInfo.getNewestBuild());\n\n\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\tLinkedTreeMap<String, List<String>> changelog = (LinkedTreeMap<String, List<String>>) part.get(\"changelog\");\n\n\t\t\tList<String> changeLogList = new ArrayList<>();\n\t\t\tif (changelog != null) {\n\t\t\t\tfor (String build : changelog.keySet()) {\n\t\t\t\t\tchangeLogList.add(build + \": \");\n\t\t\t\t\tfor (String commit : changelog.get(build)) {\n\t\t\t\t\t\tif (commit.length() > COMMIT_MAX_LINE_LENGTH) {\n\t\t\t\t\t\t\tString prefix = \"    \";\n\t\t\t\t\t\t\tboolean first = true;\n\t\t\t\t\t\t\twhile (!commit.isEmpty()) {\n\t\t\t\t\t\t\t\tint maxLength;\n\t\t\t\t\t\t\t\tif (first) {\n\t\t\t\t\t\t\t\t\tmaxLength = COMMIT_MAX_LINE_LENGTH;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tmaxLength = COMMIT_MAX_LINE_LENGTH - prefix.length();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tint splitAt = commit.substring(0, Math.min(maxLength, commit.length())).lastIndexOf(' ');\n\t\t\t\t\t\t\t\tif (commit.length() < COMMIT_MAX_LINE_LENGTH) {\n\t\t\t\t\t\t\t\t\tsplitAt = commit.length();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (splitAt <= 0) {\n\t\t\t\t\t\t\t\t\tsplitAt = Math.min(maxLength, commit.length());\n\t\t\t\t\t\t\t\t} else if (commit.length() > COMMIT_MAX_LINE_LENGTH && splitAt < COMMIT_MAX_LINE_LENGTH - 20) {\n\t\t\t\t\t\t\t\t\tsplitAt = Math.min(maxLength, commit.length());\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tchangeLogList.add((first ? \"\" : prefix) + commit.substring(0, splitAt));\n\t\t\t\t\t\t\t\tcommit = commit.substring(splitAt);\n\t\t\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tchangeLogList.add(commit);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tversionInfo.setChangelog(changeLogList);\n\t\t\tsendIMCOutdatedMessage(versionInfo);\n\t\t}\n\t\treturn versionInfo;\n\t}\n\n\t/**\n\t * Integration with Version Checker\n\t * (http://www.minecraftforum.net/topic/2721902-/)\n\t */\n\tprivate void sendIMCOutdatedMessage(VersionInfo versionInfo) {\n\t\tif (Loader.isModLoaded(\"VersionChecker\")) {\n\t\t\tNBTTagCompound tag = new NBTTagCompound();\n\t\t\ttag.setString(\"oldVersion\", LogisticsPipes.getVERSION());\n\t\t\ttag.setString(\"newVersion\", versionInfo.getNewestBuild());\n\t\t\ttag.setString(\"updateUrl\", \"http://ci.rs485.network/view/Logistics%20Pipes/\");\n\t\t\ttag.setBoolean(\"isDirectLink\", false);\n\n\t\t\tStringBuilder stringBuilder = new StringBuilder();\n\t\t\tfor (String changeLogLine : versionInfo.getChangelog()) {\n\t\t\t\tstringBuilder.append(changeLogLine).append(\"\\n\");\n\t\t\t}\n\t\t\ttag.setString(\"changeLog\", stringBuilder.toString());\n\t\t\tFMLInterModComms.sendRuntimeMessage(\"LogisticsPipes\", \"VersionChecker\", \"addUpdate\", tag);\n\t\t\tversionInfo.setImcMessageSent(true);\n\t\t}\n\t}\n\n\t@Data\n\tpublic static class VersionInfo {\n\n\t\tprivate boolean newVersionAvailable;\n\t\tprivate boolean imcMessageSent;\n\t\tprivate String newestBuild;\n\t\tprivate List<String> changelog;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/EntrencsTransport.java",
    "content": "package logisticspipes.transport;\n\nimport logisticspipes.pipes.PipeItemsSystemDestinationLogistics;\nimport logisticspipes.pipes.PipeItemsSystemEntranceLogistics;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.routing.ExitRoute;\nimport logisticspipes.routing.PipeRoutingConnectionType;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\n\npublic class EntrencsTransport extends PipeTransportLogistics {\n\n\tpublic EntrencsTransport() {\n\t\tsuper(true);\n\t}\n\n\tpublic PipeItemsSystemEntranceLogistics pipe;\n\n\t@Override\n\tpublic RoutingResult resolveDestination(LPTravelingItemServer data) {\n\t\tif (data.getDestination() < 0 || data.getArrived()) {\n\t\t\tif (pipe.getLocalFreqUUID() != null) {\n\t\t\t\tif (pipe.useEnergy(5)) {\n\t\t\t\t\tfor (ExitRoute router : pipe.getRouter().getIRoutersByCost()) {\n\t\t\t\t\t\tif (!router.containsFlag(PipeRoutingConnectionType.canRouteTo)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tCoreRoutedPipe lPipe = router.destination.getPipe();\n\t\t\t\t\t\tif (lPipe instanceof PipeItemsSystemDestinationLogistics) {\n\t\t\t\t\t\t\tPipeItemsSystemDestinationLogistics dPipe = (PipeItemsSystemDestinationLogistics) lPipe;\n\t\t\t\t\t\t\tif (dPipe.getTargetUUID() != null) {\n\t\t\t\t\t\t\t\tif (dPipe.getTargetUUID().equals(pipe.getLocalFreqUUID())) {\n\t\t\t\t\t\t\t\t\tdata.setDestination(dPipe.getRouter().getSimpleID());\n\t\t\t\t\t\t\t\t\tdata.setArrived(false);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn super.resolveDestination(data);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/LPItemList.java",
    "content": "package logisticspipes.transport;\n\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Set;\nimport javax.annotation.Nonnull;\n\nimport com.google.common.collect.BiMap;\nimport com.google.common.collect.HashBiMap;\n\npublic class LPItemList implements Iterable<LPTravelingItem> {\n\n\tprivate final BiMap<Integer, LPTravelingItem> items = HashBiMap.create();\n\tprivate final Set<LPTravelingItem> toLoad = new HashSet<>();\n\tprivate final Set<LPTravelingItem> toAdd = new HashSet<>();\n\tprivate final Set<LPTravelingItem> toRemove = new HashSet<>();\n\tprivate int delay = 0;\n\tprivate final PipeTransportLogistics pipe;\n\tprivate boolean iterating = false;\n\n\tpublic LPItemList(PipeTransportLogistics pipe) {\n\t\tthis.pipe = pipe;\n\t}\n\n\tpublic void add(LPTravelingItem item) {\n\t\tif (iterating) {\n\t\t\ttoAdd.add(item);\n\t\t\treturn;\n\t\t}\n\t\tif (items.containsValue(item)) {\n\t\t\treturn;\n\t\t}\n\t\titem.setContainer(pipe.container);\n\t\titems.put(item.getId(), item);\n\t}\n\n\tprivate void addAll(Collection<? extends LPTravelingItem> collection) {\n\t\tcollection.forEach(this::add);\n\t}\n\n\tpublic LPTravelingItem get(int id) {\n\t\treturn items.get(id);\n\t}\n\n\tvoid scheduleLoad(LPTravelingItem item) {\n\t\tdelay = 10;\n\t\ttoLoad.add(item);\n\t}\n\n\tprivate void loadScheduledItems() {\n\t\tif (delay > 0) {\n\t\t\tdelay--;\n\t\t\treturn;\n\t\t}\n\t\taddAll(toLoad);\n\t\ttoLoad.clear();\n\t}\n\n\tpublic void scheduleAdd() {\n\t\titerating = true;\n\n\t}\n\n\tpublic void addScheduledItems() {\n\t\titerating = false;\n\t\taddAll(toAdd);\n\t\ttoAdd.clear();\n\t}\n\n\tpublic boolean scheduleRemoval(LPTravelingItem item) {\n\t\treturn toRemove.add(item);\n\t}\n\n\tpublic boolean unscheduleRemoval(LPTravelingItem item) {\n\t\treturn toRemove.remove(item);\n\t}\n\n\tvoid removeScheduledItems() {\n\t\titems.values().removeAll(toRemove);\n\t\ttoRemove.clear();\n\t}\n\n\tvoid purgeBadItems() {\n\t\tIterator<LPTravelingItem> it = items.values().iterator();\n\t\twhile (it.hasNext()) {\n\t\t\tLPTravelingItem item = it.next();\n\t\t\tif (item.isCorrupted()) {\n\t\t\t\tit.remove();\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (item.getContainer() != pipe.container) {\n\t\t\t\tit.remove();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void flush() {\n\t\tloadScheduledItems();\n\t\tremoveScheduledItems();\n\t\tpurgeBadItems();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterator<LPTravelingItem> iterator() {\n\t\treturn items.values().iterator();\n\t}\n\n\tvoid clear() {\n\t\titems.clear();\n\t}\n\n\tpublic boolean isEmpty() {\n\t\treturn items.isEmpty();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/LPTravelingItem.java",
    "content": "package logisticspipes.transport;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\nimport logisticspipes.interfaces.routing.IRequireReliableFluidTransport;\nimport logisticspipes.interfaces.routing.IRequireReliableTransport;\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.IRouter;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.order.IDistanceTracker;\nimport logisticspipes.utils.EnumFacingUtil;\nimport logisticspipes.utils.FluidIdentifierStack;\nimport logisticspipes.utils.SlidingWindowBitSet;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic abstract class LPTravelingItem {\n\n\tpublic static final Map<Integer, WeakReference<LPTravelingItemServer>> serverList = new HashMap<>();\n\tpublic static final Map<Integer, WeakReference<LPTravelingItemClient>> clientList = new HashMap<>();\n\tpublic static final List<Pair<Integer, Object>> forceKeep = new ArrayList<>();\n\tpublic static final SlidingWindowBitSet clientSideKnownIDs = new SlidingWindowBitSet(20); // 20\n\n\tprivate static int nextFreeId = 0;\n\tprotected int id;\n\tprotected float speed = 0.01F;\n\n\tpublic int lastTicked = 0;\n\n\tprotected TileEntity container;\n\tprotected float position = 0;\n\tprotected float yaw = 0;\n\tpublic EnumFacing input = null;\n\tpublic EnumFacing output = null;\n\tpublic final EnumSet<EnumFacing> blacklist = EnumSet.noneOf(EnumFacing.class);\n\n\tpublic LPTravelingItem() {\n\t\tid = getNextId();\n\t}\n\n\tpublic LPTravelingItem(int id, float position, EnumFacing input, EnumFacing output, float yaw) {\n\t\tthis.id = id;\n\t\tthis.position = position;\n\t\tthis.input = input;\n\t\tthis.output = output;\n\t\tthis.yaw = yaw;\n\t}\n\n\tpublic LPTravelingItem(int id) {\n\t\tthis.id = id;\n\t}\n\n\tprotected int getNextId() {\n\t\treturn ++LPTravelingItem.nextFreeId;\n\t}\n\n\tpublic void setPosition(float position) {\n\t\tthis.position = position;\n\t}\n\n\tpublic void setYaw(float yaw) {\n\t\tthis.yaw = yaw % 360;\n\t}\n\n\tpublic float getPosition() {\n\t\treturn position;\n\t}\n\n\tpublic float getYaw() {\n\t\treturn yaw;\n\t}\n\n\tpublic float getSpeed() {\n\t\treturn speed;\n\t}\n\n\tpublic void setSpeed(float speed) {\n\t\tthis.speed = speed;\n\t}\n\n\tpublic void setContainer(TileEntity container) {\n\t\tthis.container = container;\n\t}\n\n\tpublic TileEntity getContainer() {\n\t\treturn container;\n\t}\n\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\n\tpublic abstract ItemIdentifierStack getItemIdentifierStack();\n\n\tpublic boolean isCorrupted() {\n\t\treturn getItemIdentifierStack() == null || getItemIdentifierStack().getStackSize() <= 0;\n\t}\n\n\tpublic int getAge() {\n\t\treturn 0;\n\t}\n\n\tpublic void addAge() {}\n\n\tpublic float getHoverStart() {\n\t\treturn 0;\n\t}\n\n\tpublic abstract LPTravelingItem renderCopy();\n\n\tpublic static final class LPTravelingItemClient extends LPTravelingItem {\n\n\t\t@Setter\n\t\tprivate ItemIdentifierStack item;\n\t\tprivate int age;\n\t\tprivate float hoverStart = (float) (Math.random() * Math.PI * 2.0D);\n\n\t\tpublic LPTravelingItemClient(int id, float position, EnumFacing input, EnumFacing output, float yaw) {\n\t\t\tsuper(id, position, input, output, yaw);\n\t\t}\n\n\t\tpublic LPTravelingItemClient(int id, ItemIdentifierStack stack) {\n\t\t\tsuper(id);\n\t\t\titem = stack;\n\t\t}\n\n\t\t@Override\n\t\tpublic ItemIdentifierStack getItemIdentifierStack() {\n\t\t\treturn item;\n\t\t}\n\n\t\tpublic void updateInformation(EnumFacing input, EnumFacing output, float speed, float position, float yaw) {\n\t\t\tthis.input = input;\n\t\t\tthis.output = output;\n\t\t\tthis.speed = speed;\n\t\t\tthis.position = position;\n\t\t\tthis.yaw = yaw;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getAge() {\n\t\t\treturn 0;//age;\n\t\t}\n\n\t\t@Override\n\t\tpublic void addAge() {\n\t\t\tage++;\n\t\t}\n\n\t\t@Override\n\t\tpublic float getHoverStart() {\n\t\t\treturn 0;//hoverStart;\n\t\t}\n\n\t\t@Override\n\t\tpublic LPTravelingItem renderCopy() {\n\t\t\tLPTravelingItemClient copy = new LPTravelingItemClient(id, position, input, output, yaw);\n\t\t\tcopy.speed = speed;\n\t\t\tcopy.hoverStart = hoverStart;\n\t\t\tcopy.item = new ItemIdentifierStack(item);\n\t\t\tcopy.age = age;\n\t\t\tcopy.container = container;\n\t\t\treturn copy;\n\t\t}\n\t}\n\n\tpublic static final class LPTravelingItemServer extends LPTravelingItem implements IRoutedItem {\n\n\t\t@Getter\n\t\tprivate ItemRoutingInformation info;\n\n\t\tpublic LPTravelingItemServer(ItemIdentifierStack stack) {\n\t\t\tsuper();\n\t\t\tinfo = new ItemRoutingInformation();\n\t\t\tinfo.setItem(stack);\n\t\t}\n\n\t\tpublic LPTravelingItemServer(ItemRoutingInformation info) {\n\t\t\tsuper();\n\t\t\tthis.info = info;\n\t\t}\n\n\t\tpublic LPTravelingItemServer(NBTTagCompound data) {\n\t\t\tsuper();\n\t\t\tinfo = new ItemRoutingInformation();\n\t\t\treadFromNBT(data);\n\t\t}\n\n\t\t@Override\n\t\tpublic ItemIdentifierStack getItemIdentifierStack() {\n\t\t\treturn info.getItem();\n\t\t}\n\n\t\tpublic void setInformation(ItemRoutingInformation info) {\n\t\t\tthis.info = info;\n\t\t}\n\n\t\t@Override\n\t\tpublic void readFromNBT(NBTTagCompound data) {\n\t\t\tsetPosition(data.getFloat(\"position\"));\n\t\t\tsetSpeed(data.getFloat(\"speed\"));\n\t\t\tif (data.hasKey(\"input\")) {\n\t\t\t\tinput = EnumFacingUtil.getOrientation(data.getInteger(\"input\"));\n\t\t\t} else {\n\t\t\t\tinput = null;\n\t\t\t}\n\t\t\tif (data.hasKey(\"output\")) {\n\t\t\t\toutput = EnumFacingUtil.getOrientation(data.getInteger(\"output\"));\n\t\t\t} else {\n\t\t\t\toutput = null;\n\t\t\t}\n\t\t\tinfo.readFromNBT(data);\n\t\t}\n\n\t\t@Override\n\t\tpublic void writeToNBT(NBTTagCompound data) {\n\t\t\tdata.setFloat(\"position\", getPosition());\n\t\t\tdata.setFloat(\"speed\", getSpeed());\n\t\t\tif (input != null) {\n\t\t\t\tdata.setInteger(\"input\", input.ordinal());\n\t\t\t}\n\t\t\tif (output != null) {\n\t\t\t\tdata.setInteger(\"output\", output.ordinal());\n\t\t\t}\n\t\t\tinfo.writeToNBT(data);\n\t\t}\n\n\t\tpublic EntityItem toEntityItem() {\n\t\t\tWorld world = container.getWorld();\n\t\t\tif (MainProxy.isServer(world)) {\n\t\t\t\tif (getItemIdentifierStack().getStackSize() <= 0) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tif (getItemIdentifierStack().makeNormalStack().getItem() instanceof LogisticsFluidContainer) {\n\t\t\t\t\titemWasLost();\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tEnumFacing exitdirection = output;\n\t\t\t\tif (exitdirection == null) {\n\t\t\t\t\texitdirection = input;\n\t\t\t\t}\n\n\t\t\t\tDoubleCoordinates position = new DoubleCoordinates(container).add(new DoubleCoordinates(0.5, 0.375, 0.5));\n\n\t\t\t\tswitch (exitdirection) {\n\t\t\t\t\tcase DOWN:\n\t\t\t\t\t\tCoordinateUtils.add(position, exitdirection, 0.5);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase UP:\n\t\t\t\t\t\tCoordinateUtils.add(position, exitdirection, 0.75);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase NORTH:\n\t\t\t\t\tcase SOUTH:\n\t\t\t\t\tcase WEST:\n\t\t\t\t\tcase EAST:\n\t\t\t\t\t\tCoordinateUtils.add(position, exitdirection, 0.625);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tDoubleCoordinates motion = new DoubleCoordinates(0, 0, 0);\n\t\t\t\tCoordinateUtils.add(motion, exitdirection, getSpeed() * 2.0);\n\n\t\t\t\tEntityItem entityitem = getItemIdentifierStack().makeEntityItem(world, position.getXCoord(), position.getYCoord(), position.getZCoord());\n\n\t\t\t\t//entityitem.lifespan = 1200;\n\t\t\t\t//entityitem.delayBeforeCanPickup = 10;\n\n\t\t\t\t//uniformly distributed in -0.005 .. 0.01 to increase bias toward smaller values\n\t\t\t\tfloat f3 = world.rand.nextFloat() * 0.015F - 0.005F;\n\t\t\t\tentityitem.motionX = (float) world.rand.nextGaussian() * f3 + motion.getXCoord();\n\t\t\t\tentityitem.motionY = (float) world.rand.nextGaussian() * f3 + motion.getYCoord();\n\t\t\t\tentityitem.motionZ = (float) world.rand.nextGaussian() * f3 + motion.getZCoord();\n\t\t\t\titemWasLost();\n\n\t\t\t\treturn entityitem;\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void clearDestination() {\n\t\t\tif (info.destinationint >= 0) {\n\t\t\t\titemWasLost();\n\t\t\t\tinfo.jamlist.add(info.destinationint);\n\t\t\t}\n\t\t\t//keep buffercounter and jamlist\n\t\t\tinfo.destinationint = -1;\n\t\t\tinfo.destinationUUID = null;\n\t\t\tinfo._doNotBuffer = false;\n\t\t\tinfo.arrived = false;\n\t\t\tinfo._transportMode = TransportMode.Unknown;\n\t\t\tinfo.targetInfo = null;\n\t\t}\n\n\t\tpublic void itemWasLost() {\n\t\t\tif (container != null) {\n\t\t\t\tif (MainProxy.isClient(container.getWorld())) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tIRouter destinationRouter = SimpleServiceLocator.routerManager.getRouter(info.destinationint);\n\t\t\tif (destinationRouter != null) {\n\t\t\t\tif (destinationRouter.getPipe() != null) {\n\t\t\t\t\tdestinationRouter.getPipe().notifyOfReroute(info);\n\t\t\t\t\tif (destinationRouter.getPipe() instanceof IRequireReliableTransport) {\n\t\t\t\t\t\t((IRequireReliableTransport) destinationRouter.getPipe()).itemLost(\n\t\t\t\t\t\t\t\tnew ItemIdentifierStack(info.getItem()), info.targetInfo);\n\t\t\t\t\t}\n\t\t\t\t\tif (destinationRouter.getPipe() instanceof IRequireReliableFluidTransport) {\n\t\t\t\t\t\tif (info.getItem().getItem().isFluidContainer()) {\n\t\t\t\t\t\t\tFluidIdentifierStack liquid = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(info.getItem());\n\t\t\t\t\t\t\t((IRequireReliableFluidTransport) destinationRouter.getPipe()).liquidLost(liquid.getFluid(), liquid.getAmount());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic int getDestination() {\n\t\t\treturn info.destinationint;\n\t\t}\n\n\t\t@Override\n\t\tpublic void setDestination(int destination) {\n\t\t\tinfo.destinationint = destination;\n\t\t\tfinal @Nullable World world = container != null ? container.getWorld() : null;\n\t\t\tif (MainProxy.isServer(world)) {\n\t\t\t\tIRouter router = SimpleServiceLocator.routerManager.getServerRouter(destination);\n\t\t\t\tif (router != null) {\n\t\t\t\t\tinfo.destinationUUID = router.getId();\n\t\t\t\t} else {\n\t\t\t\t\tinfo.destinationUUID = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tinfo.destinationUUID = null;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void setDoNotBuffer(boolean isBuffered) {\n\t\t\tinfo._doNotBuffer = isBuffered;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean getDoNotBuffer() {\n\t\t\treturn info._doNotBuffer;\n\t\t}\n\n\t\t@Override\n\t\tpublic void setArrived(boolean flag) {\n\t\t\tinfo.arrived = flag;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean getArrived() {\n\t\t\treturn info.arrived;\n\t\t}\n\n\t\t@Override\n\t\tpublic void split(int itemsToTake, EnumFacing orientation) {\n\t\t\tif (getItemIdentifierStack().getItem().isFluidContainer()) {\n\t\t\t\tthrow new UnsupportedOperationException(\"Can't split up a FluidContainer\");\n\t\t\t}\n\t\t\tItemIdentifierStack stackToKeep = getItemIdentifierStack();\n\t\t\tItemIdentifierStack stackToSend = new ItemIdentifierStack(stackToKeep);\n\t\t\tstackToKeep.setStackSize(itemsToTake);\n\t\t\tstackToSend.setStackSize(stackToSend.getStackSize() - itemsToTake);\n\n\t\t\tnewId();\n\n\t\t\tLPTravelingItemServer newItem = new LPTravelingItemServer(stackToSend);\n\t\t\tnewItem.setSpeed(getSpeed());\n\t\t\tnewItem.setTransportMode(getTransportMode());\n\n\t\t\tnewItem.setDestination(getDestination());\n\t\t\tnewItem.clearDestination();\n\n\t\t\tif (container instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) container).pipe.transport instanceof PipeTransportLogistics) {\n\t\t\t\t((LogisticsTileGenericPipe) container).pipe.transport.injectItem((LPTravelingItem) newItem, orientation);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void setTransportMode(TransportMode transportMode) {\n\t\t\tinfo._transportMode = transportMode;\n\t\t}\n\n\t\t@Override\n\t\tpublic TransportMode getTransportMode() {\n\t\t\treturn info._transportMode;\n\t\t}\n\n\t\t@Override\n\t\tpublic void addToJamList(IRouter router) {\n\t\t\tinfo.jamlist.add(router.getSimpleID());\n\t\t}\n\n\t\t@Override\n\t\tpublic List<Integer> getJamList() {\n\t\t\treturn info.jamlist;\n\t\t}\n\n\t\t@Override\n\t\tpublic int getBufferCounter() {\n\t\t\treturn info.bufferCounter;\n\t\t}\n\n\t\t@Override\n\t\tpublic void setBufferCounter(int counter) {\n\t\t\tinfo.bufferCounter = counter;\n\t\t}\n\n\t\t@Override\n\t\tpublic UUID getDestinationUUID() {\n\t\t\treturn info.destinationUUID;\n\t\t}\n\n\t\t@Override\n\t\tpublic void checkIDFromUUID() {\n\t\t\tIRouter router = SimpleServiceLocator.routerManager.getRouter(info.destinationint);\n\t\t\tif (router == null || info.destinationUUID != router.getId()) {\n\t\t\t\tinfo.destinationint = SimpleServiceLocator.routerManager.getIDforUUID(info.destinationUUID);\n\t\t\t}\n\t\t}\n\n\t\tpublic void refreshDestinationInformation() {\n\t\t\tIRouter destinationRouter = SimpleServiceLocator.routerManager.getRouter(info.destinationint);\n\t\t\tif (destinationRouter != null && destinationRouter.getPipe() instanceof CoreRoutedPipe) {\n\t\t\t\tdestinationRouter.getPipe().refreshItem(getInfo());\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void setDistanceTracker(IDistanceTracker tracker) {\n\t\t\tinfo.tracker = tracker;\n\t\t}\n\n\t\t@Override\n\t\tpublic IDistanceTracker getDistanceTracker() {\n\t\t\treturn info.tracker;\n\t\t}\n\n\t\tpublic void resetDelay() {\n\t\t\tinfo.resetDelay();\n\t\t}\n\n\t\t@Override\n\t\tpublic void setAdditionalTargetInformation(IAdditionalTargetInformation targetInfo) {\n\t\t\tinfo.targetInfo = targetInfo;\n\t\t}\n\n\t\t@Override\n\t\tpublic IAdditionalTargetInformation getAdditionalTargetInformation() {\n\t\t\treturn info.targetInfo;\n\t\t}\n\n\t\tpublic void newId() {\n\t\t\tid = getNextId();\n\t\t}\n\n\t\t@Override\n\t\tpublic LPTravelingItem renderCopy() {\n\t\t\tthrow new UnsupportedOperationException();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/PipeFluidTransportLogistics.java",
    "content": "package logisticspipes.transport;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.fluids.FluidStack;\nimport net.minecraftforge.fluids.FluidTank;\nimport net.minecraftforge.fluids.capability.IFluidHandler;\nimport net.minecraftforge.fluids.capability.IFluidTankProperties;\n\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.network.packets.pipe.PipeFluidUpdate;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.SafeTimeTracker;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class PipeFluidTransportLogistics extends PipeTransportLogistics {\n\n\tpublic FluidTank[] sideTanks = new FluidTank[EnumFacing.VALUES.length];\n\tpublic FluidTank internalTank = new FluidTank(getInnerCapacity());\n\n\tpublic FluidStack[] renderCache = new FluidStack[7];\n\n\tpublic PipeFluidTransportLogistics() {\n\t\tsuper(true);\n\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\tsideTanks[dir.ordinal()] = new FluidTank(getSideCapacity());\n\t\t}\n\t}\n\n\tpublic IFluidHandler getIFluidHandler(EnumFacing face) {\n\t\treturn new FluidHandler(face);\n\t}\n\n\tprivate FluidRoutedPipe getFluidPipe() {\n\t\treturn (FluidRoutedPipe) getPipe();\n\t}\n\n\t/**\n\t * For internal use only\n\t */\n\tpublic IFluidTankProperties[] getTankProperties(EnumFacing from) {\n\t\tif (from == null) return internalTank.getTankProperties();\n\t\treturn sideTanks[from.ordinal()].getTankProperties();\n\t}\n\n\tpublic int fill(EnumFacing from, FluidStack resource, boolean doFill) {\n\t\tif (from.ordinal() < EnumFacing.VALUES.length && getFluidPipe().canReceiveFluid()) {\n\t\t\treturn sideTanks[from.ordinal()].fill(resource, doFill);\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tpublic FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain) {\n\t\tif (from.ordinal() < EnumFacing.VALUES.length) {\n\t\t\treturn sideTanks[from.ordinal()].drain(maxDrain, doDrain);\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain) {\n\t\tif (sideTanks[from.ordinal()].getFluid() == null || !(sideTanks[from.ordinal()].getFluid().isFluidEqual(resource))) {\n\t\t\treturn new FluidStack(resource.getFluid(), 0);\n\t\t}\n\t\treturn drain(from, resource.amount, doDrain);\n\t}\n\n\tpublic class FluidHandler implements IFluidHandler {\n\n\t\tprivate EnumFacing from;\n\n\t\tFluidHandler(EnumFacing from) {\n\t\t\tthis.from = from;\n\t\t}\n\n\t\t@Override\n\t\tpublic int fill(FluidStack resource, boolean doFill) {\n\t\t\tif (from.ordinal() < EnumFacing.VALUES.length && getFluidPipe().canReceiveFluid()) {\n\t\t\t\treturn sideTanks[from.ordinal()].fill(resource, doFill);\n\t\t\t} else {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic FluidStack drain(int maxDrain, boolean doDrain) {\n\t\t\tif (from.ordinal() < EnumFacing.VALUES.length) {\n\t\t\t\treturn sideTanks[from.ordinal()].drain(maxDrain, doDrain);\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic FluidStack drain(FluidStack resource, boolean doDrain) {\n\t\t\tif (sideTanks[from.ordinal()].getFluid() == null || !(sideTanks[from.ordinal()].getFluid().isFluidEqual(resource))) {\n\t\t\t\treturn new FluidStack(resource.getFluid(), 0);\n\t\t\t}\n\t\t\treturn drain(resource.amount, doDrain);\n\t\t}\n\n\t\t@Override\n\t\tpublic IFluidTankProperties[] getTankProperties() {\n\t\t\tif (from.ordinal() < EnumFacing.VALUES.length) {\n\t\t\t\treturn sideTanks[from.ordinal()].getTankProperties();\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.readFromNBT(nbttagcompound);\n\n\t\tfor (EnumFacing direction : EnumFacing.VALUES) {\n\t\t\tif (nbttagcompound.hasKey(\"tank[\" + direction.ordinal() + \"]\")) {\n\t\t\t\tsideTanks[direction.ordinal()].readFromNBT(nbttagcompound.getCompoundTag(\"tank[\" + direction.ordinal() + \"]\"));\n\t\t\t}\n\t\t}\n\t\tif (nbttagcompound.hasKey(\"tank[middle]\")) {\n\t\t\tinternalTank.readFromNBT(nbttagcompound.getCompoundTag(\"tank[middle]\"));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound) {\n\t\tsuper.writeToNBT(nbttagcompound);\n\n\t\tfor (EnumFacing direction : EnumFacing.VALUES) {\n\t\t\tNBTTagCompound subTag = new NBTTagCompound();\n\t\t\tsideTanks[direction.ordinal()].writeToNBT(subTag);\n\t\t\tnbttagcompound.setTag(\"tank[\" + direction.ordinal() + \"]\", subTag);\n\t\t}\n\t\tNBTTagCompound subTag = new NBTTagCompound();\n\t\tinternalTank.writeToNBT(subTag);\n\t\tnbttagcompound.setTag(\"tank[middle]\", subTag);\n\t}\n\n\tpublic int getInnerCapacity() {\n\t\treturn 10000;\n\t}\n\n\tpublic int getSideCapacity() {\n\t\treturn 5000;\n\t}\n\n\t@Override\n\tpublic void onNeighborBlockChange() {\n\t\tsuper.onNeighborBlockChange();\n\n\t\tfor (EnumFacing direction : EnumFacing.VALUES) {\n\t\t\tif (!MainProxy.checkPipesConnections(container, container.getTile(PipeFluidTransportLogistics.orientations[direction.ordinal()]), PipeFluidTransportLogistics.orientations[direction.ordinal()])) {\n\t\t\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\t\t\tFluidStack stack = sideTanks[direction.ordinal()].getFluid();\n\t\t\t\t\tif (stack != null) {\n\t\t\t\t\t\tsideTanks[direction.ordinal()].setFluid(null);\n\t\t\t\t\t\tinternalTank.fill(stack, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (renderCache[direction.ordinal()] != null) {\n\t\t\t\t\trenderCache[direction.ordinal()].amount = 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void updateEntity() {\n\t\tsuper.updateEntity();\n\t\tupdateFluid();\n\t}\n\n\t/*\n\t * BuildCraft Fluid Sync Code\n\t */\n\tprivate final SafeTimeTracker tracker = new SafeTimeTracker(10);\n\tprivate long clientSyncCounter = 30;\n\tpublic byte initClient = 0;\n\n\tprivate static final EnumFacing[] orientations = EnumFacing.values();\n\n\tprivate void updateFluid() {\n\t\tif (MainProxy.isClient(getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\tif (tracker.markTimeIfDelay(getWorld())) {\n\n\t\t\tboolean init = false;\n\t\t\tif (++clientSyncCounter > 40) {\n\t\t\t\tclientSyncCounter = 0;\n\t\t\t\tinit = true;\n\t\t\t}\n\t\t\tif (clientSyncCounter < 0) {\n\t\t\t\tclientSyncCounter = 0;\n\t\t\t}\n\t\t\tModernPacket packet = computeFluidUpdate(init, true);\n\t\t\tif (packet != null) {\n\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(container, packet);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Computes the PacketFluidUpdate packet for transmission to a client\n\t *\n\t * @param initPacket    everything is sent, no delta stuff ( first packet )\n\t * @param persistChange The render cache change is persisted\n\t * @return PacketFluidUpdate liquid update packet\n\t */\n\tprivate ModernPacket computeFluidUpdate(boolean initPacket, boolean persistChange) {\n\n\t\tboolean changed = false;\n\n\t\tif (initClient > 0) {\n\t\t\tinitClient--;\n\t\t\tif (initClient == 1) {\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t}\n\n\t\tFluidStack[] renderCache = this.renderCache.clone();\n\n\t\tfor (EnumFacing dir : PipeFluidTransportLogistics.orientations) {\n\t\t\tFluidStack current;\n\t\t\tif (dir != null) {\n\t\t\t\tcurrent = sideTanks[dir.ordinal()].getFluid();\n\t\t\t} else {\n\t\t\t\tcurrent = internalTank.getFluid();\n\t\t\t}\n\t\t\tFluidStack prev = renderCache[dir.ordinal()];\n\n\t\t\tif (prev == null && current == null) {\n\t\t\t\tcontinue;\n\t\t\t} else if (prev == null) {\n\t\t\t\tchanged = true;\n\t\t\t\trenderCache[dir.ordinal()] = current.copy();\n\t\t\t\tcontinue;\n\t\t\t} else if (current == null) {\n\t\t\t\tchanged = true;\n\t\t\t\trenderCache[dir.ordinal()] = null;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (prev.getFluid() != current.getFluid() || initPacket) {\n\t\t\t\tchanged = true;\n\t\t\t\trenderCache[dir.ordinal()] = new FluidStack(current.getFluid(), renderCache[dir.ordinal()].amount);\n\t\t\t}\n\n\t\t\tif (prev.amount != current.amount || initPacket) {\n\t\t\t\tchanged = true;\n\t\t\t\trenderCache[dir.ordinal()].amount = current.amount;\n\t\t\t}\n\t\t}\n\n\t\tif (persistChange) {\n\t\t\tthis.renderCache = renderCache;\n\t\t}\n\n\t\tif (changed || initPacket) {\n\t\t\treturn PacketHandler.getPacket(PipeFluidUpdate.class).setRenderCache(renderCache).setTilePos(container).setChunkDataPacket(initPacket);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t@Override\n\tprotected boolean isItemUnwanted(ItemIdentifierStack stack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tprotected boolean isPipeCheck(TileEntity tile) {\n\t\treturn SimpleServiceLocator.pipeInformationManager.isPipe(tile);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/PipeMultiBlockTransportLogistics.java",
    "content": "package logisticspipes.transport;\n\nimport java.util.List;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.Explosion;\n\nimport logisticspipes.pipes.basic.CoreMultiBlockPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericSubMultiBlock;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemClient;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\n\npublic class PipeMultiBlockTransportLogistics extends PipeTransportLogistics {\n\n\tprivate CoreMultiBlockPipe multiPipe;\n\n\tpublic PipeMultiBlockTransportLogistics() {\n\t\tsuper(false);\n\t}\n\n\t@Override\n\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing side) {\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe != null && ((LogisticsTileGenericPipe) tile).pipe.isHSTube()) {\n\t\t\treturn true;\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock && ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe() != null && !((LogisticsTileGenericSubMultiBlock) tile).getMainPipe().isEmpty()) {\n\t\t\tfor (LogisticsTileGenericPipe pipe : ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe()) {\n\t\t\t\tif (pipe.pipe == null || !pipe.pipe.isHSTube()) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic CoreMultiBlockPipe getMultiPipe() {\n\t\tif (multiPipe == null) {\n\t\t\tCoreUnroutedPipe uPipe = getPipe();\n\t\t\tif (uPipe instanceof CoreMultiBlockPipe) {\n\t\t\t\tmultiPipe = (CoreMultiBlockPipe) uPipe;\n\t\t\t}\n\t\t}\n\t\treturn multiPipe;\n\t}\n\n\t@Override\n\tpublic float getPipeLength() {\n\t\tif (getMultiPipe() != null) {\n\t\t\treturn getMultiPipe().getPipeLength();\n\t\t}\n\t\treturn super.getPipeLength();\n\t}\n\n\tpublic double getDistanceWeight() {\n\t\tif (getMultiPipe() != null) {\n\t\t\treturn getMultiPipe().getDistanceWeight();\n\t\t}\n\t\treturn super.getDistanceWeight();\n\t}\n\n\t@Override\n\tpublic float getYawDiff(LPTravelingItem item) {\n\t\tif (getMultiPipe() != null) {\n\t\t\treturn getMultiPipe().getYawDiff(item);\n\t\t}\n\t\treturn super.getYawDiff(item);\n\t}\n\n\t@Override\n\tpublic RoutingResult resolveDestination(LPTravelingItemServer data) {\n\t\tif (getMultiPipe() == null) {\n\t\t\treturn new RoutingResult(null, false);\n\t\t}\n\t\treturn new RoutingResult(getMultiPipe().getExitForInput(data.input.getOpposite()), true);\n\t}\n\n\t@Override\n\tprotected void reachedEnd(LPTravelingItem item) {\n\t\tTileEntity tile = null;\n\t\tif (getMultiPipe() != null) {\n\t\t\ttile = getMultiPipe().getConnectedEndTile(item.output);\n\t\t}\n\t\tif (items.scheduleRemoval(item)) {\n\t\t\tif (MainProxy.isServer(container.getWorld())) {\n\t\t\t\thandleTileReachedServer((LPTravelingItemServer) item, tile, item.output);\n\t\t\t} else {\n\t\t\t\thandleTileReachedClient((LPTravelingItemClient) item, tile, item.output);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void handleTileReachedServer(LPTravelingItemServer arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\tmarkChunkModified(tile);\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe instanceof CoreMultiBlockPipe) {\n\t\t\tpassToNextPipe(arrivingItem, tile);\n\t\t\treturn;\n\t\t} else if (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> masterTile = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tif (!masterTile.isEmpty()) {\n\t\t\t\tif (masterTile.size() > 1) {\n\t\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t\t}\n\t\t\t\tpassToNextPipe(arrivingItem, masterTile.get(0));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tExplosion explosion = new Explosion(this.getWorld(), null, this.getPipe().getX(), this.getPipe().getY(), this.getPipe().getZ(), 4.0F, false, true);\n\t\texplosion.doExplosionB(true);\n\t}\n\n\t@Override\n\tprotected void handleTileReachedClient(LPTravelingItemClient arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe instanceof CoreMultiBlockPipe) {\n\t\t\tpassToNextPipe(arrivingItem, tile);\n\t\t\treturn;\n\t\t} else if (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> masterTile = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tif (!masterTile.isEmpty()) {\n\t\t\t\tif (masterTile.size() > 1) {\n\t\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t\t}\n\t\t\t\tpassToNextPipe(arrivingItem, masterTile.get(0));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tExplosion explosion = new Explosion(this.getWorld(), null, this.getPipe().getX(), this.getPipe().getY(), this.getPipe().getZ(), 4.0F, false, true);\n\t\texplosion.doExplosionB(true);\n\t}\n\n\t@Override\n\tpublic void readjustSpeed(LPTravelingItemServer item) {\n\t\titem.setSpeed(0.8F);\n\t}\n\n\t@Override\n\tpublic CoreUnroutedPipe getNextPipe(EnumFacing output) {\n\t\tTileEntity tile = null;\n\t\tif (getMultiPipe() != null) {\n\t\t\ttile = getMultiPipe().getConnectedEndTile(output);\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericSubMultiBlock) {\n\t\t\tList<LogisticsTileGenericPipe> list = ((LogisticsTileGenericSubMultiBlock) tile).getMainPipe();\n\t\t\tif (!list.isEmpty()) {\n\t\t\t\tif (list.size() > 1) {\n\t\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t\t}\n\t\t\t\ttile = list.get(0);\n\t\t\t}\n\t\t}\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\treturn ((LogisticsTileGenericPipe) tile).pipe;\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/PipeTransportLogistics.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.transport;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Random;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.world.World;\nimport net.minecraft.world.chunk.Chunk;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Data;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.api.ILogisticsPowerProvider;\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity;\nimport logisticspipes.interfaces.IBufferItems;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.IItemAdvancedExistance;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.interfaces.ISpecialInsertion;\nimport logisticspipes.interfaces.ISubSystemPowerProvider;\nimport logisticspipes.interfaces.routing.ITargetSlotInformation;\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.logisticspipes.IRoutedItem.TransportMode;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.pipe.ItemBufferSyncPacket;\nimport logisticspipes.network.packets.pipe.PipeContentPacket;\nimport logisticspipes.network.packets.pipe.PipeContentRequest;\nimport logisticspipes.network.packets.pipe.PipePositionPacket;\nimport logisticspipes.pipes.PipeItemsFluidSupplier;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.PipeLogisticsChassis.ChassiTargetInformation;\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemClient;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.utils.CacheHolder.CacheTypes;\nimport logisticspipes.utils.InventoryHelper;\nimport logisticspipes.utils.OrientationsUtil;\nimport logisticspipes.utils.SyncList;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class PipeTransportLogistics {\n\n\t@Data\n\t@AllArgsConstructor\n\tstatic class RoutingResult {\n\n\t\tprivate EnumFacing face;\n\t\tprivate boolean hasRoute;\n\t}\n\n\tprivate final int _bufferTimeOut = 20 * 2; // 2 Seconds\n\tpublic final SyncList<Triplet<ItemIdentifierStack, Pair<Integer /* Time */, Integer /* BufferCounter */>, LPTravelingItemServer>> _itemBuffer = new SyncList<>();\n\tprivate Chunk chunk;\n\tpublic LPItemList items = new LPItemList(this);\n\tpublic LogisticsTileGenericPipe container;\n\tpublic final boolean isRouted;\n\tpublic final int MAX_DESTINATION_UNREACHABLE_BUFFER = 30;\n\n\tpublic PipeTransportLogistics(boolean isRouted) {\n\t\tthis.isRouted = isRouted;\n\t}\n\n\tpublic void initialize() {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\t// cache chunk for marking dirty\n\t\t\tchunk = getWorld().getChunk(container.getPos());\n\t\t\tItemBufferSyncPacket packet = PacketHandler.getPacket(ItemBufferSyncPacket.class);\n\t\t\tpacket.setTilePos(container);\n\t\t\t_itemBuffer.setPacketType(packet, getWorld().provider.getDimension(), container.getX(), container.getZ());\n\t\t}\n\t}\n\n\tpublic void markChunkModified(TileEntity tile) {\n\t\tif (tile != null && chunk != null) {\n\t\t\t// items are crossing a chunk boundary, mark both chunks modified\n\t\t\tif (container.getPos().getX() >> 4 != tile.getPos().getX() >> 4 || container.getPos().getZ() >> 4 != tile.getPos().getZ() >> 4) {\n\t\t\t\tchunk.markDirty();\n\t\t\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe != null && ((LogisticsTileGenericPipe) tile).pipe.transport != null && ((LogisticsTileGenericPipe) tile).pipe.transport.chunk != null) {\n\t\t\t\t\t((LogisticsTileGenericPipe) tile).pipe.transport.chunk.markDirty();\n\t\t\t\t} else {\n\t\t\t\t\tgetWorld().getChunk(tile.getPos()).markDirty();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected CoreUnroutedPipe getPipe() {\n\t\treturn container.pipe;\n\t}\n\n\tprotected CoreRoutedPipe getRoutedPipe() {\n\t\tif (!isRouted) {\n\t\t\tthrow new UnsupportedOperationException(\"Can't use a Transport pipe as a routing pipe\");\n\t\t}\n\t\treturn (CoreRoutedPipe) container.pipe;\n\t}\n\n\tpublic void updateEntity() {\n\t\tmoveSolids();\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (!_itemBuffer.isEmpty()) {\n\t\t\t\tList<LPTravelingItem> toAdd = new LinkedList<>();\n\t\t\t\tIterator<Triplet<ItemIdentifierStack, Pair<Integer, Integer>, LPTravelingItemServer>> iterator = _itemBuffer.iterator();\n\t\t\t\twhile (iterator.hasNext()) {\n\t\t\t\t\tTriplet<ItemIdentifierStack, Pair<Integer, Integer>, LPTravelingItemServer> next = iterator.next();\n\t\t\t\t\tint currentTimeOut = next.getValue2().getValue1();\n\t\t\t\t\tif (currentTimeOut > 0) {\n\t\t\t\t\t\tnext.getValue2().setValue1(currentTimeOut - 1);\n\t\t\t\t\t} else if (next.getValue3() != null) {\n\t\t\t\t\t\tif (getRoutedPipe().getRouter().hasRoute(next.getValue3().getDestination(), next.getValue3().getTransportMode() == TransportMode.Active, next.getValue3().getItemIdentifierStack().getItem()) || next.getValue2().getValue2() > MAX_DESTINATION_UNREACHABLE_BUFFER) {\n\t\t\t\t\t\t\tnext.getValue3().setBufferCounter(next.getValue2().getValue2() + 1);\n\t\t\t\t\t\t\ttoAdd.add(next.getValue3());\n\t\t\t\t\t\t\titerator.remove();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnext.getValue2().setValue2(next.getValue2().getValue2() + 1);\n\t\t\t\t\t\t\tnext.getValue2().setValue1(_bufferTimeOut);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tLPTravelingItemServer item = SimpleServiceLocator.routedItemHelper.createNewTravelItem(next.getValue1());\n\t\t\t\t\t\titem.setDoNotBuffer(true);\n\t\t\t\t\t\titem.setBufferCounter(next.getValue2().getValue2() + 1);\n\t\t\t\t\t\ttoAdd.add(item);\n\t\t\t\t\t\titerator.remove();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (LPTravelingItem item : toAdd) {\n\t\t\t\t\tthis.injectItem(item, EnumFacing.UP);\n\t\t\t\t}\n\t\t\t}\n\t\t\t_itemBuffer.sendUpdateToWaters();\n\t\t}\n\t}\n\n\tpublic void dropBuffer() {\n\t\tIterator<Triplet<ItemIdentifierStack, Pair<Integer, Integer>, LPTravelingItemServer>> iterator = _itemBuffer.iterator();\n\t\twhile (iterator.hasNext()) {\n\t\t\tItemIdentifierStack next = iterator.next().getValue1();\n\t\t\tMainProxy.dropItems(getWorld(), next.makeNormalStack(), getPipe().getX(), getPipe().getY(), getPipe().getZ());\n\t\t\titerator.remove();\n\t\t}\n\t}\n\n\tpublic int injectItem(LPTravelingItemServer item, EnumFacing inputOrientation) {\n\t\treturn injectItem((LPTravelingItem) item, inputOrientation);\n\t}\n\n\tpublic float getPipeLength() {\n\t\treturn 1.0F;\n\t}\n\n\tpublic double getDistanceWeight() {\n\t\treturn 1.0D;\n\t}\n\n\tpublic float getYawDiff(LPTravelingItem item) {\n\t\treturn 0.0F;\n\t}\n\n\tpublic int injectItem(LPTravelingItem item, EnumFacing inputOrientation) {\n\t\tif (item.isCorrupted()) {\n\t\t\t// Safe guard - if for any reason the item is corrupted at this\n\t\t\t// stage, avoid adding it to the pipe to avoid further exceptions.\n\t\t\treturn 0;\n\t\t}\n\t\tgetPipe().triggerDebug();\n\n\t\tint originalCount = item.getItemIdentifierStack().getStackSize();\n\n\t\titem.input = inputOrientation;\n\n\t\tif (MainProxy.isServer(container.getWorld())) {\n\t\t\treadjustSpeed((LPTravelingItemServer) item);\n\t\t\tItemRoutingInformation info1 = ((LPTravelingItemServer) item).getInfo().clone();\n\t\t\tRoutingResult result = resolveDestination((LPTravelingItemServer) item);\n\t\t\titem.output = result.getFace();\n\t\t\tif (!result.hasRoute) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tgetPipe().debug.log(\"Injected Item: [\" + item.input + \", \" + item.output + \"] (\" + info1);\n\t\t} else {\n\t\t\titem.output = null;\n\t\t}\n\n\t\tif (item.getPosition() >= getPipeLength()) {\n\t\t\treachedEnd(item);\n\t\t} else {\n\t\t\titems.add(item);\n\n\t\t\tif (MainProxy.isServer(container.getWorld()) && !getPipe().isOpaque() && item.getItemIdentifierStack().getStackSize() > 0) {\n\t\t\t\tsendItemPacket((LPTravelingItemServer) item);\n\t\t\t}\n\t\t}\n\t\treturn originalCount - item.getItemIdentifierStack().getStackSize();\n\t}\n\n\tpublic int injectItem(IRoutedItem item, EnumFacing inputOrientation) {\n\t\treturn injectItem((LPTravelingItem) SimpleServiceLocator.routedItemHelper.getServerTravelingItem(item), inputOrientation);\n\t}\n\n\t/**\n\t * emit the supplied item. This function assumes ownershop of the item, and\n\t * you may assume that it is now either buffered by the pipe or moving\n\t * through the pipe.\n\t *\n\t * @param item\n\t *            the item that just bounced off an inventory. In the case of a\n\t *            pipe with a buffer, this function will alter item.\n\t */\n\tprotected void reverseItem(LPTravelingItemServer item) {\n\t\tif (item.isCorrupted()) {\n\t\t\t// Safe guard - if for any reason the item is corrupted at this\n\t\t\t// stage, avoid adding it to the pipe to avoid further exceptions.\n\t\t\treturn;\n\t\t}\n\n\t\tif (getPipe() instanceof IBufferItems) {\n\t\t\titem.getItemIdentifierStack().setStackSize(((IBufferItems) getPipe()).addToBuffer(item.getItemIdentifierStack(), item.getAdditionalTargetInformation()));\n\t\t\tif (item.getItemIdentifierStack().getStackSize() <= 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Assign new ID to update ItemStack content\n\t\titem.id = item.getNextId();\n\n\t\tif (item.getPosition() >= getPipeLength()) {\n\t\t\titem.setPosition(item.getPosition() - getPipeLength());\n\t\t}\n\n\t\titem.input = item.output.getOpposite();\n\n\t\treadjustSpeed(item);\n\t\tRoutingResult result = resolveDestination(item);\n\t\titem.output = result.getFace();\n\t\tif (!result.hasRoute) {\n\t\t\treturn;\n\t\t} else if (item.output == null) {\n\t\t\tdropItem(item);\n\t\t\treturn;\n\t\t}\n\n\t\titems.unscheduleRemoval(item);\n\t\tif (!getPipe().isOpaque()) {\n\t\t\tsendItemPacket(item);\n\t\t}\n\t}\n\n\tpublic RoutingResult resolveDestination(LPTravelingItemServer data) {\n\t\tif (isRouted) {\n\t\t\treturn resolveRoutedDestination(data);\n\t\t} else {\n\t\t\treturn resolveUnroutedDestination(data);\n\t\t}\n\t}\n\n\tpublic RoutingResult resolveUnroutedDestination(LPTravelingItemServer data) {\n\t\tList<EnumFacing> dirs = new ArrayList<>(Arrays.asList(EnumFacing.VALUES));\n\t\tdirs.remove(data.input.getOpposite());\n\t\tIterator<EnumFacing> iter = dirs.iterator();\n\t\twhile (iter.hasNext()) {\n\t\t\tEnumFacing dir = iter.next();\n\t\t\tDoubleCoordinates pos = CoordinateUtils.add(getPipe().getLPPosition(), dir);\n\t\t\tTileEntity tile = pos.getTileEntity(getWorld());\n\t\t\tif (!SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\t\titer.remove();\n\t\t\t} else if (!canPipeConnect(tile, dir)) {\n\t\t\t\titer.remove();\n\t\t\t} else if (tile instanceof LogisticsTileGenericPipe && !((LogisticsTileGenericPipe) tile).canConnect(container, dir.getOpposite(), false)) {\n\t\t\t\titer.remove();\n\t\t\t}\n\t\t}\n\t\tif (dirs.isEmpty()) {\n\t\t\treturn new RoutingResult(null, false);\n\t\t}\n\t\tint num = new Random().nextInt(dirs.size());\n\t\treturn new RoutingResult(dirs.get(num), true);\n\t}\n\n\tpublic RoutingResult resolveRoutedDestination(LPTravelingItemServer data) {\n\n\t\tEnumFacing blocked = null;\n\n\t\tif (data.getDestinationUUID() == null) {\n\t\t\tItemIdentifierStack stack = data.getItemIdentifierStack();\n\t\t\tItemRoutingInformation result = getRoutedPipe().getQueuedForItemStack(stack);\n\t\t\tif (result != null) {\n\t\t\t\tdata.setInformation(result);\n\t\t\t\tdata.getInfo().setItem(stack);\n\t\t\t\tblocked = data.input.getOpposite();\n\t\t\t}\n\t\t}\n\n\t\tif (data.getItemIdentifierStack() != null) {\n\t\t\tgetRoutedPipe().relayedItem(data.getItemIdentifierStack().getStackSize());\n\t\t}\n\n\t\tif (data.getDestination() >= 0 && !getRoutedPipe().getRouter().hasRoute(data.getDestination(), data.getTransportMode() == TransportMode.Active, data.getItemIdentifierStack().getItem()) && data.getBufferCounter() < MAX_DESTINATION_UNREACHABLE_BUFFER) {\n\t\t\t_itemBuffer.add(new Triplet<>(data.getItemIdentifierStack(), new Pair<>(_bufferTimeOut, data.getBufferCounter()), data));\n\t\t\treturn new RoutingResult(null, false);\n\t\t}\n\n\t\tEnumFacing value;\n\t\tif (getRoutedPipe().stillNeedReplace() || getRoutedPipe().initialInit()) {\n\t\t\tdata.setDoNotBuffer(false);\n\t\t\tvalue = null;\n\t\t} else {\n\t\t\tvalue = getRoutedPipe().getRouteLayer().getOrientationForItem(data, blocked);\n\t\t}\n\t\tif (value == null && MainProxy.isClient(getWorld())) {\n\t\t\treturn new RoutingResult(null, true);\n\t\t}\n\n\t\tif (value == null && !data.getDoNotBuffer() && data.getBufferCounter() < 5) {\n\t\t\t_itemBuffer.add(new Triplet<>(data.getItemIdentifierStack(), new Pair<>(_bufferTimeOut, data.getBufferCounter()), null));\n\t\t\treturn new RoutingResult(null, false);\n\t\t}\n\n\t\tif (value != null && !getRoutedPipe().getRouter().isRoutedExit(value)) {\n\t\t\tif (isItemUnwanted(data.getItemIdentifierStack())) {\n\t\t\t\treturn new RoutingResult(null, false);\n\t\t\t}\n\t\t}\n\n\t\tdata.resetDelay();\n\n\t\treturn new RoutingResult(value, true);\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbt) {\n\n\t\tNBTTagList nbttaglist = nbt.getTagList(\"travelingEntities\", 10);\n\n\t\tfor (int j = 0; j < nbttaglist.tagCount(); ++j) {\n\t\t\ttry {\n\t\t\t\tNBTTagCompound dataTag = nbttaglist.getCompoundTagAt(j);\n\n\t\t\t\tLPTravelingItem item = new LPTravelingItemServer(dataTag);\n\n\t\t\t\tif (item.isCorrupted()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\titems.scheduleLoad(item);\n\t\t\t} catch (Throwable t) {\n\t\t\t\t// It may be the case that entities cannot be reloaded between\n\t\t\t\t// two versions - ignore these errors.\n\t\t\t}\n\t\t}\n\n\t\t_itemBuffer.clear();\n\n\t\tNBTTagList nbttaglist2 = nbt.getTagList(\"buffercontents\", 10);\n\t\tfor (int i = 0; i < nbttaglist2.tagCount(); i++) {\n\t\t\tNBTTagCompound nbttagcompound1 = nbttaglist2.getCompoundTagAt(i);\n\t\t\t_itemBuffer.add(new Triplet<>(ItemIdentifierStack.getFromStack(ItemStackLoader.loadAndFixItemStackFromNBT(nbttagcompound1)), new Pair<>(_bufferTimeOut, 0), null));\n\t\t}\n\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbt) {\n\n\t\t{\n\t\t\tNBTTagList nbttaglist = new NBTTagList();\n\n\t\t\tfor (LPTravelingItem item : items) {\n\t\t\t\tif (item instanceof LPTravelingItemServer) {\n\t\t\t\t\tNBTTagCompound dataTag = new NBTTagCompound();\n\t\t\t\t\tnbttaglist.appendTag(dataTag);\n\t\t\t\t\t((LPTravelingItemServer) item).writeToNBT(dataTag);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnbt.setTag(\"travelingEntities\", nbttaglist);\n\t\t}\n\n\t\tNBTTagList nbttaglist2 = new NBTTagList();\n\n\t\tfor (Pair<ItemIdentifierStack, Pair<Integer, Integer>> stack : _itemBuffer) {\n\t\t\tNBTTagCompound nbttagcompound1 = new NBTTagCompound();\n\t\t\tstack.getValue1().makeNormalStack().writeToNBT(nbttagcompound1);\n\t\t\tnbttaglist2.appendTag(nbttagcompound1);\n\t\t}\n\t\tnbt.setTag(\"buffercontents\", nbttaglist2);\n\n\t}\n\n\tpublic void readjustSpeed(LPTravelingItemServer item) {\n\t\tfloat defaultBoost;\n\n\t\tswitch (item.getTransportMode()) {\n\t\t\tcase Default:\n\t\t\t\tdefaultBoost = 20F;\n\t\t\t\tbreak;\n\t\t\tcase Passive:\n\t\t\t\tdefaultBoost = 25F;\n\t\t\t\tbreak;\n\t\t\tcase Active:\n\t\t\t\tdefaultBoost = 30F;\n\t\t\t\tbreak;\n\t\t\tcase Unknown:\n\t\t\t\tdefaultBoost = 20F;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdefaultBoost = 20F;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif (isRouted) {\n\t\t\tfloat multiplyerSpeed = 1.0F + (0.02F * getRoutedPipe().getUpgradeManager().getSpeedUpgradeCount());\n\t\t\tfloat multiplyerPower = 1.0F + (0.03F * getRoutedPipe().getUpgradeManager().getSpeedUpgradeCount());\n\n\t\t\tfloat add = Math.max(item.getSpeed(), LPConstants.PIPE_NORMAL_SPEED * defaultBoost * multiplyerPower) - item.getSpeed();\n\t\t\tif (getRoutedPipe().useEnergy((int) (add * 50 + 0.5))) {\n\t\t\t\titem.setSpeed(Math.min(Math.max(item.getSpeed(), LPConstants.PIPE_NORMAL_SPEED * defaultBoost * multiplyerSpeed), 1.0F));\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void handleTileReachedServer(LPTravelingItemServer arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\thandleTileReachedServer_internal(arrivingItem, tile, dir);\n\t}\n\n\tprotected final void handleTileReachedServer_internal(LPTravelingItemServer arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\tif (getPipe() instanceof PipeItemsFluidSupplier) {\n\t\t\t((PipeItemsFluidSupplier) getPipe()).endReached(arrivingItem, tile);\n\t\t\tif (arrivingItem.getItemIdentifierStack().getStackSize() <= 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tmarkChunkModified(tile);\n\t\tif (arrivingItem.getInfo() != null && arrivingItem.getArrived() && isRouted) {\n\t\t\tgetRoutedPipe().notifyOfItemArival(arrivingItem.getInfo());\n\t\t}\n\t\tif (getPipe() instanceof FluidRoutedPipe) {\n\t\t\tif (((FluidRoutedPipe) getPipe()).endReached(arrivingItem, tile)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tboolean isSpecialConnectionInformationTransition = false;\n\t\tif (SimpleServiceLocator.specialtileconnection.needsInformationTransition(tile)) {\n\t\t\tisSpecialConnectionInformationTransition = true;\n\t\t\tSimpleServiceLocator.specialtileconnection.transmit(tile, arrivingItem);\n\t\t}\n\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\tif (passToNextPipe(arrivingItem, tile)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\tIInventoryUtil util = SimpleServiceLocator.inventoryUtilFactory.getInventoryUtil(tile, dir.getOpposite());\n\t\t\tif (util != null && isRouted) {\n\t\t\t\tgetRoutedPipe().getCacheHolder().trigger(CacheTypes.Inventory);\n\n\t\t\t\t// items.scheduleRemoval(arrivingItem);\n\t\t\t\t// destroy the item on exit if it isn't exitable\n\t\t\t\tif (!isSpecialConnectionInformationTransition && isItemUnwanted(arrivingItem.getItemIdentifierStack())) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// last chance for chassi to back out\n\t\t\t\tif (arrivingItem.getTransportMode() != TransportMode.Active && !getRoutedPipe().getTransportLayer().stillWantItem(arrivingItem)) {\n\t\t\t\t\treverseItem(arrivingItem);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfinal ISlotUpgradeManager slotManager;\n\t\t\t\t{\n\t\t\t\t\tModulePositionType slot = null;\n\t\t\t\t\tint positionInt = -1;\n\t\t\t\t\tif (arrivingItem.getInfo().targetInfo instanceof ChassiTargetInformation) {\n\t\t\t\t\t\tpositionInt = ((ChassiTargetInformation) arrivingItem.getInfo().targetInfo).getModuleSlot();\n\t\t\t\t\t\tslot = ModulePositionType.SLOT;\n\t\t\t\t\t} else if (LogisticsPipes.isDEBUG() && container.pipe instanceof PipeLogisticsChassis) {\n\t\t\t\t\t\tSystem.out.println(arrivingItem);\n\t\t\t\t\t\tnew RuntimeException(\"[ItemInsertion] Information weren't ment for a chassi pipe\").printStackTrace();\n\t\t\t\t\t}\n\t\t\t\t\tslotManager = getRoutedPipe().getUpgradeManager(slot, positionInt);\n\t\t\t\t}\n\t\t\t\tif (arrivingItem.getAdditionalTargetInformation() instanceof ITargetSlotInformation) {\n\n\t\t\t\t\tITargetSlotInformation information = (ITargetSlotInformation) arrivingItem.getAdditionalTargetInformation();\n\t\t\t\t\tif (util instanceof ISpecialInsertion) {\n\t\t\t\t\t\tint slot = information.getTargetSlot();\n\t\t\t\t\t\tint amount = information.getAmount();\n\t\t\t\t\t\tif (util.getSizeInventory() > slot) {\n\t\t\t\t\t\t\tItemStack content = util.getStackInSlot(slot);\n\t\t\t\t\t\t\tItemStack toAdd = arrivingItem.getItemIdentifierStack().makeNormalStack();\n\t\t\t\t\t\t\tfinal int amountLeft = Math.max(0, amount - content.getCount());\n\t\t\t\t\t\t\ttoAdd.setCount(Math.min(toAdd.getCount(), amountLeft));\n\t\t\t\t\t\t\tif (toAdd.getCount() > 0) {\n\t\t\t\t\t\t\t\tif (util.getSizeInventory() > slot) {\n\t\t\t\t\t\t\t\t\tint added = ((ISpecialInsertion) util).addToSlot(toAdd, slot);\n\t\t\t\t\t\t\t\t\tarrivingItem.getItemIdentifierStack().lowerStackSize(added);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (information.isLimited()) {\n\t\t\t\t\t\t\tif (arrivingItem.getItemIdentifierStack().getStackSize() > 0) {\n\t\t\t\t\t\t\t\treverseItem(arrivingItem);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// sneaky insertion\n\t\t\t\tif (!getRoutedPipe().getUpgradeManager().hasCombinedSneakyUpgrade() || slotManager.hasOwnSneakyUpgrade()) {\n\t\t\t\t\tEnumFacing insertion = arrivingItem.output.getOpposite();\n\t\t\t\t\tif (slotManager.hasSneakyUpgrade()) {\n\t\t\t\t\t\tinsertion = slotManager.getSneakyOrientation();\n\t\t\t\t\t}\n\t\t\t\t\tif (insertArrivingItem(arrivingItem, tile, insertion)) return;\n\t\t\t\t} else {\n\t\t\t\t\tEnumFacing[] dirs = getRoutedPipe().getUpgradeManager().getCombinedSneakyOrientation();\n\t\t\t\t\tfor (EnumFacing insertion : dirs) {\n\t\t\t\t\t\tif (insertion == null) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (insertArrivingItem(arrivingItem, tile, insertion)) return;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (arrivingItem.getItemIdentifierStack().getStackSize() > 0) {\n\t\t\t\t\treverseItem(arrivingItem);\n\t\t\t\t}\n\t\t\t\treturn;// the item is handled\n\t\t\t}// end of insert into IInventory\n\t\t}\n\t\tdropItem(arrivingItem);\n\t}\n\n\t/**\n\t * @return true, if every item has been inserted and otherwise false.\n\t */\n\tprivate boolean insertArrivingItem(LPTravelingItemServer arrivingItem, TileEntity tile, EnumFacing insertion) {\n\t\tItemStack added = InventoryHelper.getTransactorFor(tile, insertion).add(arrivingItem.getItemIdentifierStack().makeNormalStack(), insertion, true);\n\n\t\tif (!added.isEmpty()) {\n\t\t\tarrivingItem.getItemIdentifierStack().lowerStackSize(added.getCount());\n\t\t\tarrivingItem.setBufferCounter(0);\n\t\t}\n\n\t\tItemRoutingInformation info = arrivingItem.getInfo();\n\t\tfinal boolean isSplitStack = arrivingItem.getItemIdentifierStack().getStackSize() > 0;\n\t\tif (isSplitStack) {\n\t\t\t// we have some leftovers, we are splitting the stack, we need to clone the info\n\t\t\tinfo = info.clone();\n\t\t}\n\t\tif(added.isEmpty()){\n\t\t\tinfo.getItem().setStackSize(0);\n\t\t} else {\n\t\t\tinfo.getItem().setStackSize(added.getCount());\n\t\t}\n\n\t\tinventorySystemConnectorHook(info, tile);\n\n\t\t// back to normal code, break if we've inserted everything, all items disposed of.\n\t\treturn !isSplitStack;\n\t}\n\n\tprotected void handleTileReachedClient(LPTravelingItemClient arrivingItem, TileEntity tile, EnumFacing dir) {\n\t\tif (SimpleServiceLocator.pipeInformationManager.isItemPipe(tile)) {\n\t\t\tpassToNextPipe(arrivingItem, tile);\n\t\t}\n\t\t// Just ignore any other case\n\t}\n\n\tprotected boolean isItemUnwanted(ItemIdentifierStack itemIdentifierStack) {\n\t\tif (itemIdentifierStack != null && itemIdentifierStack.makeNormalStack().getItem() instanceof IItemAdvancedExistance) {\n\t\t\treturn !((IItemAdvancedExistance) itemIdentifierStack.makeNormalStack().getItem()).canExistInNormalInventory(itemIdentifierStack.makeNormalStack());\n\t\t}\n\t\treturn false;\n\t}\n\n\tprotected void inventorySystemConnectorHook(ItemRoutingInformation info, TileEntity tile) {}\n\n\tpublic boolean canPipeConnect(TileEntity tile, EnumFacing side) {\n\t\treturn canPipeConnect_internal(tile, side);\n\t}\n\n\tpublic final boolean canPipeConnect_internal(TileEntity tile, EnumFacing side) {\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\tif (((LogisticsTileGenericPipe) tile).pipe != null && ((LogisticsTileGenericPipe) tile).pipe.isHSTube() && !((LogisticsTileGenericPipe) tile).pipe.actAsNormalPipe()) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\tif (isRouted) {\n\t\t\tif (tile instanceof ILogisticsPowerProvider || tile instanceof ISubSystemPowerProvider) {\n\t\t\t\tEnumFacing ori = OrientationsUtil.getOrientationOfTilewithTile(container, tile);\n\t\t\t\tif (ori != null) {\n\t\t\t\t\treturn !((tile instanceof LogisticsPowerJunctionTileEntity || tile instanceof ISubSystemPowerProvider) && ori.getAxis() == EnumFacing.Axis.Y);\n\t\t\t\t}\n\t\t\t}\n\t\t\tIInventoryUtil util = SimpleServiceLocator.inventoryUtilFactory.getInventoryUtil(tile, side.getOpposite());\n\t\t\tif (util != null) {\n\t\t\t\treturn util.getSizeInventory() > 0;\n\t\t\t}\n\t\t\treturn isPipeCheck(tile);\n\t\t} else {\n\t\t\treturn isPipeCheck(tile);\n\t\t}\n\t}\n\n\tprotected boolean isPipeCheck(TileEntity tile) {\n\t\treturn SimpleServiceLocator.pipeInformationManager.isItemPipe(tile);\n\t}\n\n\tprotected void reachedEnd(LPTravelingItem item) {\n\t\tTileEntity tile = container.getTile(item.output);\n\t\tif (items.scheduleRemoval(item)) {\n\t\t\tif (MainProxy.isServer(container.getWorld())) {\n\t\t\t\thandleTileReachedServer((LPTravelingItemServer) item, tile, item.output);\n\t\t\t} else {\n\t\t\t\thandleTileReachedClient((LPTravelingItemClient) item, tile, item.output);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void moveSolids() {\n\t\titems.flush();\n\t\titems.scheduleAdd();\n\t\tfor (LPTravelingItem item : items) {\n\t\t\tif (item.lastTicked >= MainProxy.getGlobalTick()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\titem.lastTicked = MainProxy.getGlobalTick();\n\t\t\titem.addAge();\n\t\t\titem.setPosition(item.getPosition() + item.getSpeed());\n\t\t\tif (hasReachedEnd(item)) {\n\t\t\t\tif (item.output == null) {\n\t\t\t\t\tif (MainProxy.isServer(container.getWorld())) {\n\t\t\t\t\t\tdropItem((LPTravelingItemServer) item);\n\t\t\t\t\t}\n\t\t\t\t\titems.scheduleRemoval(item);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\treachedEnd(item);\n\t\t\t}\n\t\t}\n\t\titems.removeScheduledItems();\n\t\titems.addScheduledItems();\n\t}\n\n\tprotected boolean passToNextPipe(LPTravelingItem item, TileEntity tile) {\n\t\tIPipeInformationProvider information = SimpleServiceLocator.pipeInformationManager.getInformationProviderFor(tile);\n\t\tif (information != null) {\n\t\t\titem.setPosition(item.getPosition() - getPipeLength());\n\t\t\titem.setYaw(item.getYaw() + (getYawDiff(item)));\n\t\t\treturn information.acceptItem(item, container);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Accept items from BC\n\t */ /*\n\t@ModDependentMethod(modId = \"BuildCraft|Transport\")\n\tpublic void injectItem(TravelingItem item, EnumFacing inputOrientation) {\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tif (item instanceof LPRoutedBCTravelingItem) {\n\t\t\t\tItemRoutingInformation info = ((LPRoutedBCTravelingItem) item).getRoutingInformation();\n\t\t\t\tinfo.setItem(ItemIdentifierStack.getFromStack(item.getItemStack()));\n\t\t\t\tLPTravelingItemServer lpItem = new LPTravelingItemServer(info);\n\t\t\t\tlpItem.setSpeed(item.getSpeed());\n\t\t\t\tthis.injectItem(lpItem, inputOrientation);\n\t\t\t} else {\n\t\t\t\tItemRoutingInformation info = LPRoutedBCTravelingItem.restoreFromExtraNBTData(item);\n\t\t\t\tif (info != null) {\n\t\t\t\t\tinfo.setItem(ItemIdentifierStack.getFromStack(item.getItemStack()));\n\t\t\t\t\tLPTravelingItemServer lpItem = new LPTravelingItemServer(info);\n\t\t\t\t\tlpItem.setSpeed(item.getSpeed());\n\t\t\t\t\tthis.injectItem(lpItem, inputOrientation);\n\t\t\t\t} else {\n\t\t\t\t\tLPTravelingItemServer lpItem = SimpleServiceLocator.routedItemHelper.createNewTravelItem(item.getItemStack());\n\t\t\t\t\tlpItem.setSpeed(item.getSpeed());\n\t\t\t\t\tthis.injectItem(lpItem, inputOrientation);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t*/\n\tprivate void dropItem(LPTravelingItemServer item) {\n\t\tif (MainProxy.isClient(container.getWorld())) {\n\t\t\treturn;\n\t\t}\n\t\titem.setSpeed(0.05F);\n\t\titem.setContainer(container);\n\t\tEntityItem entity = item.toEntityItem();\n\t\tif (entity != null) {\n\t\t\tcontainer.getWorld().spawnEntity(entity);\n\t\t}\n\t}\n\n\tprotected boolean hasReachedEnd(LPTravelingItem item) {\n\t\treturn item.getPosition() >= ((item.output == null) ? 0.75F : getPipeLength());\n\t}\n\n\tprotected void neighborChange() {}\n\n\tpublic NonNullList<ItemStack> dropContents() {\n\t\tNonNullList<ItemStack> list = NonNullList.create();\n\t\tif (MainProxy.isServer(getWorld())) {\n\t\t\tfor (LPTravelingItem item : items) {\n\t\t\t\tlist.add(item.getItemIdentifierStack().makeNormalStack());\n\t\t\t}\n\t\t}\n\t\treturn list;\n\t}\n\n\tpublic boolean delveIntoUnloadedChunks() {\n\t\treturn true;\n\t}\n\n\tprivate void sendItemPacket(LPTravelingItemServer item) {\n\t\tif (MainProxy.isAnyoneWatching(container.getPos(), getWorld().provider.getDimension())) {\n\t\t\tif (!LPTravelingItem.clientSideKnownIDs.get(item.getId())) {\n\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(container, (PacketHandler.getPacket(PipeContentPacket.class).setItem(item.getItemIdentifierStack()).setTravelId(item.getId())));\n\t\t\t\tLPTravelingItem.clientSideKnownIDs.set(item.getId());\n\t\t\t}\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(container, (PacketHandler.getPacket(PipePositionPacket.class).setSpeed(item.getSpeed()).setPosition(item.getPosition()).setInput(item.input).setOutput(item.output).setTravelId(item.getId()).setYaw(item.getYaw()).setTilePos(container)));\n\t\t}\n\t}\n\n\tpublic void handleItemPositionPacket(int travelId, EnumFacing input, EnumFacing output, float speed, float position, float yaw) {\n\t\tWeakReference<LPTravelingItemClient> ref = LPTravelingItem.clientList.get(travelId);\n\t\tLPTravelingItemClient item = null;\n\t\tif (ref != null) {\n\t\t\titem = ref.get();\n\t\t}\n\t\tif (item == null) {\n\t\t\tsendItemContentRequest(travelId);\n\t\t\titem = new LPTravelingItemClient(travelId, position, input, output, yaw);\n\t\t\titem.setSpeed(speed);\n\t\t\tLPTravelingItem.clientList.put(travelId, new WeakReference<>(item));\n\t\t} else {\n\t\t\tif (item.getContainer() instanceof LogisticsTileGenericPipe) {\n\t\t\t\t((LogisticsTileGenericPipe) item.getContainer()).pipe.transport.items.scheduleRemoval(item);\n\t\t\t\t((LogisticsTileGenericPipe) item.getContainer()).pipe.transport.items.removeScheduledItems();\n\t\t\t}\n\t\t\titem.updateInformation(input, output, speed, position, yaw);\n\t\t}\n\t\t//update lastTicked so we don't double-move items\n\t\titem.lastTicked = MainProxy.getGlobalTick();\n\t\tif (items.get(travelId) == null) {\n\t\t\titems.add(item);\n\t\t}\n\t\t//getPipe().spawnParticle(Particles.OrangeParticle, 1);\n\t}\n\n\tprivate void sendItemContentRequest(int travelId) {\n\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(PipeContentRequest.class).setInteger(travelId));\n\t}\n\n\tpublic void sendItem(@Nonnull ItemStack stackToSend) {\n\t\tthis.injectItem((LPTravelingItem) SimpleServiceLocator.routedItemHelper.createNewTravelItem(stackToSend), EnumFacing.UP);\n\t}\n\n\tpublic World getWorld() {\n\t\treturn container.getWorld();\n\t}\n\n\tpublic void onNeighborBlockChange() {}\n\n\tpublic void onBlockPlaced() {}\n\n\tpublic void setTile(LogisticsTileGenericPipe tile) {\n\t\tcontainer = tile;\n\t}\n\n\tpublic CoreUnroutedPipe getNextPipe(EnumFacing output) {\n\t\tTileEntity tile = container.getTile(output);\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\treturn ((LogisticsTileGenericPipe) tile).pipe;\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/transport/TransportInvConnection.java",
    "content": "package logisticspipes.transport;\n\nimport java.util.Objects;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.pipes.PipeItemsInvSysConnector;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.utils.OrientationsUtil;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class TransportInvConnection extends PipeTransportLogistics {\n\n\tpublic TransportInvConnection() {\n\t\tsuper(true);\n\t}\n\n\t@Override\n\tprotected boolean isItemUnwanted(ItemIdentifierStack stack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tprotected void inventorySystemConnectorHook(ItemRoutingInformation info, TileEntity tile) {\n\t\tif (tile == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tfinal EnumFacing orientationOfTilewithTile = OrientationsUtil.getOrientationOfTilewithTile(getPipe().container, tile);\n\t\tObjects.requireNonNull(orientationOfTilewithTile, \"Could not get direction from pipe and tile entity\");\n\n\t\tif (tile.hasCapability(LogisticsPipes.ITEM_HANDLER_CAPABILITY, orientationOfTilewithTile.getOpposite())) {\n\t\t\t((PipeItemsInvSysConnector) container.pipe).handleItemEnterInv(info, tile);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/CacheHolder.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Set;\n\nimport com.google.common.collect.HashBasedTable;\nimport com.google.common.collect.Table;\n\nimport logisticspipes.asm.te.LPTileEntityObject;\n\n/**\n * Cache is cleared every 200 ticks when used on Routed Pipes.\n */\npublic class CacheHolder {\n\n\tpublic enum CacheTypes {\n\t\t/**\n\t\t * <p>\n\t\t * Cleared when pipes [every supported type] are added to the network.\n\t\t * </p>\n\t\t */\n\t\tRouting,\n\t\t/**\n\t\t * <p>\n\t\t * Cleared when an item is inserted or extracted from an adjacent\n\t\t * inventory<br>\n\t\t * The Extraction trigger needs to be implemented separately for every\n\t\t * use case.\n\t\t * </p>\n\t\t */\n\t\tInventory\n\t}\n\n\tprivate final Table<CacheTypes, Object, Object> cache = HashBasedTable.create();\n\n\tpublic Object getCacheFor(CacheTypes type, Object key) {\n\t\treturn cache.get(type, key);\n\t}\n\n\tpublic void setCache(CacheTypes type, Object key, Object value) {\n\t\tcache.put(type, key, value);\n\t}\n\n\tpublic void trigger(CacheTypes type) {\n\t\tif (type != null) {\n\t\t\tcache.row(type).clear();\n\t\t} else {\n\t\t\tcache.clear();\n\t\t}\n\t}\n\n\tpublic static void clearCache(Set<LPTileEntityObject> toClear) {\n\t\tfor (LPTileEntityObject obj : toClear) {\n\t\t\tobj.trigger(CacheTypes.Routing);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/CardManagementInventory.java",
    "content": "package logisticspipes.utils;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.text.ITextComponent;\nimport net.minecraft.util.text.TextComponentString;\n\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.items.LogisticsItemCard;\nimport logisticspipes.utils.item.ItemIdentifierInventory;\n\npublic class CardManagementInventory implements IInventory {\n\n\tItemIdentifierInventory inv = new ItemIdentifierInventory(4, \"\", 1);\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn 10;\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn inv.isEmpty();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack getStackInSlot(int i) {\n\t\tif (i > -1 && i < 4) {\n\t\t\treturn inv.getStackInSlot(i);\n\t\t}\n\t\tItemStack card = inv.getStackInSlot(3);\n\t\tif (!card.isEmpty()) {\n\t\t\tNBTTagCompound nbt = card.getTagCompound();\n\t\t\tif (nbt == null) {\n\t\t\t\tnbt = new NBTTagCompound();\n\t\t\t}\n\t\t\tNBTTagCompound colors = nbt.getCompoundTag(\"colors\");\n\t\t\tint slot = i - 4;\n\n\t\t\tint colorCode;\n\t\t\tif (colors.hasKey(\"color:\" + slot)) {\n\t\t\t\tcolorCode = colors.getInteger(\"color:\" + slot);\n\t\t\t} else {\n\t\t\t\tcolors.setInteger(\"color:\" + slot, 16);\n\t\t\t\tcolorCode = 16;\n\t\t\t}\n\n\t\t\tMinecraftColor color = MinecraftColor.values()[colorCode];\n\n\t\t\tnbt.setTag(\"colors\", colors);\n\t\t\tcard.setTagCompound(nbt);\n\t\t\tinv.setInventorySlotContents(3, card);\n\n\t\t\treturn color.getItemStack();\n\t\t}\n\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack decrStackSize(int i, int j) {\n\t\tif (i > -1 && i < 4) {\n\t\t\treturn inv.decrStackSize(i, j);\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack removeStackFromSlot(int i) {\n\t\tif (i > -1 && i < 4) {\n\t\t\treturn inv.removeStackFromSlot(i);\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\tpublic void setInventorySlotContents(int i, @Nonnull ItemStack itemstack) {\n\t\tif (i > -1 && i < 4) {\n\t\t\tif (i == 0 && !itemstack.isEmpty() && !inv.getStackInSlot(1).isEmpty() && inv.getStackInSlot(2).isEmpty() && inv.getStackInSlot(1).getItemDamage() == itemstack.getItemDamage()) {\n\t\t\t\titemstack.setTagCompound(inv.getStackInSlot(1).getTagCompound());\n\t\t\t\tinv.setInventorySlotContents(2, itemstack);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (i == 1 && !itemstack.isEmpty() && !inv.getStackInSlot(0).isEmpty() && inv.getStackInSlot(2).isEmpty() && inv.getStackInSlot(0).getItemDamage() == itemstack.getItemDamage()) {\n\t\t\t\titemstack.setTagCompound(inv.getStackInSlot(0).getTagCompound());\n\t\t\t\tinv.setInventorySlotContents(2, itemstack);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tinv.setInventorySlotContents(i, itemstack);\n\t\t\treturn;\n\t\t}\n\t\tItemStack card = inv.getStackInSlot(3);\n\t\tif (!card.isEmpty()) {\n\t\t\tNBTTagCompound nbt = card.getTagCompound();\n\t\t\tif (nbt == null) {\n\t\t\t\tnbt = new NBTTagCompound();\n\t\t\t}\n\t\t\tNBTTagCompound colors = nbt.getCompoundTag(\"colors\");\n\t\t\tint slot = i - 4;\n\t\t\tcolors.setInteger(\"color:\" + slot, MinecraftColor.getColor(itemstack).ordinal());\n\t\t\tnbt.setTag(\"colors\", colors);\n\t\t\tcard.setTagCompound(nbt);\n\t\t\tinv.setInventorySlotContents(3, card);\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getName() {\n\t\treturn \"Card Managment Inventory\";\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ITextComponent getDisplayName() {\n\t\treturn new TextComponentString(\"\");\n\t}\n\n\t@Override\n\tpublic boolean hasCustomName() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int getInventoryStackLimit() {\n\t\treturn 64;\n\t}\n\n\t@Override\n\tpublic boolean isUsableByPlayer(@Nonnull EntityPlayer entityplayer) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void markDirty() {}\n\n\t@Override\n\tpublic void openInventory(@Nonnull EntityPlayer player) {}\n\n\t@Override\n\tpublic void closeInventory(@Nonnull EntityPlayer player) {}\n\n\t@Override\n\tpublic boolean isItemValidForSlot(int i, @Nonnull ItemStack itemstack) {\n\t\tif (itemstack.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\t\tif (i == 0 || i == 1) {\n\t\t\treturn itemstack.getItem() instanceof ItemModule;\n\t\t} else if (i == 3) {\n\t\t\treturn itemstack.getItem() instanceof LogisticsItemCard;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void close(EntityPlayer player, int x, int y, int z) {\n\t\tinv.dropContents(player.world, x, y, z);\n\t}\n\n\t@Override\n\tpublic int getField(int id) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void setField(int id, int value) {\n\n\t}\n\n\t@Override\n\tpublic int getFieldCount() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void clear() {\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/ChainAddArrayList.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.ArrayList;\n\nimport logisticspipes.interfaces.IChainAddList;\n\npublic class ChainAddArrayList<T> extends ArrayList<T> implements IChainAddList<T> {\n\n\t@Override\n\tpublic T addChain(T add) {\n\t\tthis.add(add);\n\t\treturn add;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/Color.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/mc16/LICENSE.md\n */\n\npackage logisticspipes.utils;\n\n/**\n * Enumeration for colors and their int values. Also contains some static\n * functions.\n */\npublic enum Color {\n\tBLANK(0x00000000),\n\tWHITE(0xFFFFFFFF),\n\tWHITE_50(0x80FFFFFF),\n\tBLACK(0xFF000000),\n\tLIGHTER_GREY(0xFFE0E0E0),\n\tLIGHT_GREY(0xFFC0C0C0),\n\tGREY(0xFFA0A0A0),\n\tDARK_GREY(0xFF808080),\n\tDARKER_GREY(0xFF555555),\n\tRED(0xFFFF0000),\n\tGREEN(0xFF00FF00),\n\tBLUE(0xFF0000FF),\n\tLIGHT_YELLOW(0xFFFFFFA0),\n\tTEXT_DARK(0xff404040),\n\tTEXT_WHITE(0xffffffff),\n\tTEXT_HOVERED(0xffffffa0),\n\tTEXT_DISABLED(0xffA0A0A0),\n\tBACKGROUND_LIGHT(0xffc6c6c6),\n\tBACKGROUND_DARK(0xff8b8b8b),\n\t/** Light red */\n\tFUZZY_ORE_DICT_COLOR(0xFFFF4040),\n\t/** Light green */\n\tFUZZY_IGNORE_DAMAGE_COLOR(0xFF40FF40),\n\t/** Bright blue */\n\tFUZZY_IGNORE_NBT_COLOR(0xFF4040FF),\n\t/** Muddy Green */\n\tFUZZY_ORE_CATEGORY_COLOR(0xFF7F7F40),\n\t;\n\n\tprivate final int colorValue;\n\n\tColor(int value) {\n\t\tcolorValue = value;\n\t}\n\n\tpublic int getValue() {\n\t\treturn colorValue;\n\t}\n\n\tpublic static int getValue(Color color) {\n\t\treturn color.colorValue;\n\t}\n\n\tpublic static float getAlpha(int colorValue) {\n\t\treturn (colorValue >> 24 & 255) / 255.0F;\n\t}\n\n\tpublic static float getRed(int colorValue) {\n\t\treturn (colorValue >> 16 & 255) / 255.0F;\n\t}\n\n\tpublic static float getGreen(int colorValue) {\n\t\treturn (colorValue >> 8 & 255) / 255.0F;\n\t}\n\n\tpublic static float getBlue(int colorValue) {\n\t\treturn (colorValue & 255) / 255.0F;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/CraftingUtil.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.item.crafting.CraftingManager;\nimport net.minecraft.item.crafting.IRecipe;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.registry.RegistryNamespaced;\n\npublic class CraftingUtil {\n\n\t// Suppressed because getRecipeList shouldn't ever return something that\n\t// isn't a recipe.\n\tpublic static RegistryNamespaced<ResourceLocation, IRecipe> getRecipeList() {\n\t\treturn CraftingManager.REGISTRY;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/DelayedGeneric.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.concurrent.Delayed;\nimport java.util.concurrent.TimeUnit;\nimport javax.annotation.Nonnull;\n\npublic class DelayedGeneric<T> implements Delayed {\n\n\tprivate final long origin;\n\tprivate final long delay;\n\tprivate final T workItem;\n\n\tpublic DelayedGeneric(final T workItem, final long delay) {\n\t\tthis.origin = System.nanoTime();\n\t\tthis.workItem = workItem;\n\t\tthis.delay = delay * 1000;\n\t}\n\n\tpublic T get() {\n\t\treturn workItem;\n\t}\n\n\t@Override\n\tpublic long getDelay(TimeUnit unit) {\n\t\treturn unit.convert(delay - (System.nanoTime() - origin), TimeUnit.NANOSECONDS);\n\t}\n\n\t@Override\n\tpublic int compareTo(@Nonnull Delayed delayed) {\n\t\tif (delayed == this) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tif (delayed instanceof DelayedGeneric) {\n\t\t\tlong diff = (delay + origin) - (((DelayedGeneric<?>) delayed).delay + ((DelayedGeneric<?>) delayed).origin);\n\t\t\treturn ((diff == 0) ? 0 : ((diff < 0) ? -1 : 1));\n\t\t}\n\n\t\tlong d = (getDelay(TimeUnit.NANOSECONDS) - delayed.getDelay(TimeUnit.NANOSECONDS));\n\t\treturn ((d == 0) ? 0 : ((d < 0) ? -1 : 1));\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"DelayedGeneric[\" + workItem.toString() + \", (\" + delay + \", \" + getDelay(TimeUnit.MILLISECONDS) + \")]\";\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/DummyWorldProvider.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.world.World;\n\nimport logisticspipes.interfaces.IWorldProvider;\n\npublic class DummyWorldProvider implements IWorldProvider {\n\n\tprivate final World world;\n\n\tpublic DummyWorldProvider(World world) {\n\t\tthis.world = world;\n\t}\n\n\t@Override\n\tpublic World getWorld() {\n\t\treturn world;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/EnumFacingUtil.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.util.EnumFacing;\n\npublic class EnumFacingUtil {\n\n\tpublic static EnumFacing getOrientation(int input) {\n\t\tif (input < 0 || EnumFacing.VALUES.length <= input) {\n\t\t\treturn null;\n\t\t}\n\t\treturn EnumFacing.VALUES[input];\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/EqualWeakReference.java",
    "content": "package logisticspipes.utils;\n\nimport java.lang.ref.WeakReference;\n\npublic class EqualWeakReference<T> extends WeakReference<T> {\n\n\tpublic EqualWeakReference(T referent) {\n\t\tsuper(referent);\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (obj instanceof EqualWeakReference) {\n\t\t\tObject o = ((EqualWeakReference<?>) obj).get();\n\t\t\tif (o == null) {\n\t\t\t\treturn get() == null;\n\t\t\t} else {\n\t\t\t\treturn o.equals(get());\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/FinalNBTTagCompound.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Collections;\nimport java.util.Set;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.nbt.NBTBase;\nimport net.minecraft.nbt.NBTTagCompound;\n\npublic class FinalNBTTagCompound extends NBTTagCompound {\n\n\tprivate boolean constructing;\n\n\tpublic FinalNBTTagCompound(NBTTagCompound base) {\n\t\tsuper();\n\t\tconstructing = true;\n\t\tsuper.merge(base);\n\t\tconstructing = false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Set<String> getKeySet() {\n\t\treturn Collections.unmodifiableSet(super.getKeySet());\n\t}\n\n\t@Override\n\tpublic void setBoolean(@Nonnull String key, boolean value) {\n\t\tif (constructing) super.setBoolean(key, value);\n\t}\n\n\t@Override\n\tpublic void setByte(@Nonnull String key, byte value) {\n\t\tif (constructing) super.setByte(key, value);\n\t}\n\n\t@Override\n\tpublic void setByteArray(@Nonnull String key, @Nonnull byte[] value) {\n\t\tif (constructing) super.setByteArray(key, value);\n\t}\n\n\t@Override\n\tpublic void setDouble(@Nonnull String key, double value) {\n\t\tif (constructing) super.setDouble(key, value);\n\t}\n\n\t@Override\n\tpublic void setFloat(@Nonnull String key, float value) {\n\t\tif (constructing) super.setFloat(key, value);\n\t}\n\n\t@Override\n\tpublic void setIntArray(@Nonnull String key, @Nonnull int[] value) {\n\t\tif (constructing) super.setIntArray(key, value);\n\t}\n\n\t@Override\n\tpublic void setInteger(@Nonnull String key, int value) {\n\t\tif (constructing) super.setInteger(key, value);\n\t}\n\n\t@Override\n\tpublic void setLong(@Nonnull String key, long value) {\n\t\tif (constructing) super.setLong(key, value);\n\t}\n\n\t@Override\n\tpublic void setShort(@Nonnull String key, short value) {\n\t\tif (constructing) super.setShort(key, value);\n\t}\n\n\t@Override\n\tpublic void setString(@Nonnull String key, String value) {\n\t\tif (constructing) super.setString(key, value);\n\t}\n\n\t@Override\n\tpublic void setTag(@Nonnull String key, @Nonnull NBTBase value) {\n\t\tif (constructing) super.setTag(key, value);\n\t}\n\n\t@Override\n\tpublic void setUniqueId(String key, UUID value) {\n\t\tif (constructing) super.setUniqueId(key, value);\n\t}\n\n\t@Override\n\tpublic void merge(NBTTagCompound other) {\n\t\tif (constructing) super.merge(other);\n\t}\n\n\t@Override\n\tpublic void removeTag(@Nonnull String key) {\n\t\tif (constructing) super.removeTag(key);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/FinalPair.java",
    "content": "package logisticspipes.utils;\n\n/**\n * A final pair that caches hashcode and implements equals, mainly for use as\n * hashmap key\n */\npublic class FinalPair<T1, T2> {\n\n\tprivate final T1 _value1;\n\tprivate final T2 _value2;\n\tprivate final int _hashcode;\n\n\tpublic FinalPair(T1 value1, T2 value2) {\n\t\t_value1 = value1;\n\t\t_value2 = value2;\n\t\t_hashcode = _value1.hashCode() ^ _value2.hashCode();\n\t}\n\n\tpublic T1 getValue1() {\n\t\treturn _value1;\n\t}\n\n\tpublic T2 getValue2() {\n\t\treturn _value2;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"<%s,%s>\", _value1, _value2);\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn _hashcode;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (!(o instanceof FinalPair)) {\n\t\t\treturn false;\n\t\t}\n\t\tFinalPair<?, ?> p = (FinalPair<?, ?>) o;\n\t\treturn _value1.equals(p._value1) && _value2.equals(p._value2);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/FluidIdentifier.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Random;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReadWriteLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport net.minecraftforge.fluids.Fluid;\nimport net.minecraftforge.fluids.FluidRegistry;\nimport net.minecraftforge.fluids.FluidStack;\nimport net.minecraftforge.fluids.FluidUtil;\nimport net.minecraftforge.fluids.IFluidTank;\nimport net.minecraftforge.fluids.capability.CapabilityFluidHandler;\nimport net.minecraftforge.fluids.capability.IFluidHandlerItem;\nimport net.minecraftforge.fluids.capability.IFluidTankProperties;\n\nimport lombok.AllArgsConstructor;\n\nimport logisticspipes.asm.addinfo.IAddInfo;\nimport logisticspipes.asm.addinfo.IAddInfoProvider;\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class FluidIdentifier implements Comparable<FluidIdentifier>, ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate final static ReadWriteLock dblock = new ReentrantReadWriteLock();\n\tprivate final static Lock rlock = FluidIdentifier.dblock.readLock();\n\tprivate final static Lock wlock = FluidIdentifier.dblock.writeLock();\n\n\t//map uniqueID -> FluidIdentifier\n\tprivate final static HashMap<Integer, FluidIdentifier> _fluidIdentifierIdCache = new HashMap<>(256, 0.5f);\n\n\t//for fluids with tags, map fluidID -> map tag -> FluidIdentifier\n\tprivate final static Map<String, HashMap<FinalNBTTagCompound, FluidIdentifier>> _fluidIdentifierTagCache = new HashMap<>(256);\n\n\t//for fluids without tags, map fluidID -> FluidIdentifier\n\tprivate final static Map<String, FluidIdentifier> _fluidIdentifierCache = new HashMap<>(256);\n\n\tpublic final String fluidID;\n\tpublic final String name;\n\tpublic final FinalNBTTagCompound tag;\n\tpublic final int uniqueID;\n\n\t@Override\n\tpublic int compareTo(FluidIdentifier o) {\n\t\tint c = fluidID.compareTo(o.fluidID);\n\t\tif (c != 0) {\n\t\t\treturn c;\n\t\t}\n\t\tc = uniqueID - o.uniqueID;\n\t\treturn c;\n\t}\n\n\t@AllArgsConstructor\n\tprivate static class FluidStackAddInfo implements IAddInfo {\n\n\t\tprivate final FluidIdentifier fluid;\n\t}\n\n\t@AllArgsConstructor\n\tprivate static class FluidAddInfo implements IAddInfo {\n\n\t\tprivate final FluidIdentifier fluid;\n\t}\n\n\tprivate FluidIdentifier(String fluidID, String name, FinalNBTTagCompound tag, int uniqueID) {\n\t\tthis.fluidID = fluidID;\n\t\tthis.name = name;\n\t\tthis.tag = tag;\n\t\tthis.uniqueID = uniqueID;\n\t}\n\n\tpublic static FluidIdentifier get(Fluid fluid, NBTTagCompound tag, FluidIdentifier proposal) {\n\t\tString fluidID = fluid.getName();\n\t\tif (tag == null) {\n\t\t\tif (proposal != null) {\n\t\t\t\tif (proposal.fluidID.equals(fluidID) && proposal.tag == null) {\n\t\t\t\t\treturn proposal;\n\t\t\t\t}\n\t\t\t}\n\t\t\tproposal = null;\n\t\t\tIAddInfoProvider prov = null;\n\t\t\tif (fluid instanceof IAddInfoProvider) {\n\t\t\t\tprov = (IAddInfoProvider) fluid;\n\t\t\t\tFluidAddInfo info = prov.getLogisticsPipesAddInfo(FluidAddInfo.class);\n\t\t\t\tif (info != null) {\n\t\t\t\t\tproposal = info.fluid;\n\t\t\t\t}\n\t\t\t}\n\t\t\tFluidIdentifier ident = getFluidIdentifierWithoutTag(fluid, fluidID, proposal);\n\t\t\tif (proposal != ident && prov != null) {\n\t\t\t\tprov.setLogisticsPipesAddInfo(new FluidAddInfo(ident));\n\t\t\t}\n\t\t\treturn ident;\n\t\t} else {\n\t\t\tFluidIdentifier.rlock.lock();\n\t\t\t{\n\t\t\t\tHashMap<FinalNBTTagCompound, FluidIdentifier> fluidNBTList = FluidIdentifier._fluidIdentifierTagCache.get(fluidID);\n\t\t\t\tif (fluidNBTList != null) {\n\t\t\t\t\tFinalNBTTagCompound tagwithfixedname = new FinalNBTTagCompound(tag);\n\t\t\t\t\tFluidIdentifier unknownFluid = fluidNBTList.get(tagwithfixedname);\n\t\t\t\t\tif (unknownFluid != null) {\n\t\t\t\t\t\tFluidIdentifier.rlock.unlock();\n\t\t\t\t\t\treturn unknownFluid;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tFluidIdentifier.rlock.unlock();\n\t\t\tFluidIdentifier.wlock.lock();\n\t\t\t{\n\t\t\t\tHashMap<FinalNBTTagCompound, FluidIdentifier> fluidNBTList = FluidIdentifier._fluidIdentifierTagCache.get(fluidID);\n\t\t\t\tif (fluidNBTList != null) {\n\t\t\t\t\tFinalNBTTagCompound tagwithfixedname = new FinalNBTTagCompound(tag);\n\t\t\t\t\tFluidIdentifier unknownFluid = fluidNBTList.get(tagwithfixedname);\n\t\t\t\t\tif (unknownFluid != null) {\n\t\t\t\t\t\tFluidIdentifier.wlock.unlock();\n\t\t\t\t\t\treturn unknownFluid;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tHashMap<FinalNBTTagCompound, FluidIdentifier> fluidNBTList = FluidIdentifier._fluidIdentifierTagCache\n\t\t\t\t\t.computeIfAbsent(fluidID, k -> new HashMap<>(16, 0.5f));\n\t\t\tFinalNBTTagCompound finaltag = new FinalNBTTagCompound(tag);\n\t\t\tint id = FluidIdentifier.getUnusedId();\n\t\t\tFluidIdentifier unknownFluid = new FluidIdentifier(fluidID, FluidRegistry.getFluidName(fluid), finaltag, id);\n\t\t\tfluidNBTList.put(finaltag, unknownFluid);\n\t\t\tFluidIdentifier._fluidIdentifierIdCache.put(id, unknownFluid);\n\t\t\tFluidIdentifier.wlock.unlock();\n\t\t\treturn (unknownFluid);\n\t\t}\n\t}\n\n\tprivate static FluidIdentifier getFluidIdentifierWithoutTag(Fluid fluid, String fluidID, FluidIdentifier proposal) {\n\t\tif (proposal != null) {\n\t\t\tif (proposal.fluidID.equals(fluidID) && proposal.tag == null) {\n\t\t\t\treturn proposal;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier.rlock.lock();\n\t\t{\n\t\t\tFluidIdentifier unknownFluid = FluidIdentifier._fluidIdentifierCache.get(fluidID);\n\t\t\tif (unknownFluid != null) {\n\t\t\t\tFluidIdentifier.rlock.unlock();\n\t\t\t\treturn unknownFluid;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier.rlock.unlock();\n\t\tFluidIdentifier.wlock.lock();\n\t\t{\n\t\t\tFluidIdentifier unknownFluid = FluidIdentifier._fluidIdentifierCache.get(fluidID);\n\t\t\tif (unknownFluid != null) {\n\t\t\t\tFluidIdentifier.wlock.unlock();\n\t\t\t\treturn unknownFluid;\n\t\t\t}\n\t\t}\n\t\tint id = FluidIdentifier.getUnusedId();\n\t\tFluidIdentifier unknownFluid = new FluidIdentifier(fluidID, FluidRegistry.getFluidName(fluid), null, id);\n\t\tFluidIdentifier._fluidIdentifierCache.put(fluidID, unknownFluid);\n\t\tFluidIdentifier._fluidIdentifierIdCache.put(id, unknownFluid);\n\t\tFluidIdentifier.wlock.unlock();\n\t\treturn (unknownFluid);\n\t}\n\n\tpublic static FluidIdentifier get(FluidStack stack) {\n\t\tif (stack == null) {\n\t\t\treturn null;\n\t\t}\n\t\tFluidIdentifier proposal = null;\n\t\tIAddInfoProvider prov = null;\n\t\tif (stack instanceof IAddInfoProvider) {\n\t\t\tprov = (IAddInfoProvider) stack;\n\t\t\tFluidStackAddInfo info = prov.getLogisticsPipesAddInfo(FluidStackAddInfo.class);\n\t\t\tif (info != null) {\n\t\t\t\tproposal = info.fluid;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier ident = FluidIdentifier.get(stack.getFluid(), stack.tag, proposal);\n\t\tif (proposal != ident && stack.tag == null && prov != null) {\n\t\t\tprov.setLogisticsPipesAddInfo(new FluidStackAddInfo(ident));\n\t\t}\n\t\treturn ident;\n\t}\n\n\tpublic static FluidIdentifier get(ItemIdentifier stack) {\n\t\treturn FluidIdentifier.get(stack.makeStack(1));\n\t}\n\n\tpublic static FluidIdentifier get(@Nonnull ItemStack stack) {\n\t\treturn FluidIdentifier.get(ItemIdentifierStack.getFromStack(stack));\n\t}\n\n\tpublic static FluidIdentifier get(ItemIdentifierStack stack) {\n\t\tFluidStack f = null;\n\t\tFluidIdentifierStack fstack = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(stack);\n\t\tif (fstack != null) {\n\t\t\tf = fstack.makeFluidStack();\n\t\t}\n\t\tif (f == null) {\n\t\t\tItemStack itemStack = stack.unsafeMakeNormalStack();\n\t\t\tif (itemStack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null)) {\n\t\t\t\tIFluidHandlerItem capability = itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null);\n\t\t\t\tif (capability != null) {\n\t\t\t\t\tf = Arrays.stream(capability.getTankProperties()).map(IFluidTankProperties::getContents).filter(Objects::nonNull).findFirst().orElse(null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (f == null) {\n\t\t\tf = FluidUtil.getFluidContained(stack.unsafeMakeNormalStack());\n\t\t}\n\t\tif (f == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn FluidIdentifier.get(f);\n\t}\n\n\tprivate static FluidIdentifier get(Fluid fluid) {\n\t\treturn FluidIdentifier.get(fluid, null, null);\n\t}\n\n\tprivate static int getUnusedId() {\n\t\tint id = new Random().nextInt();\n\t\twhile (FluidIdentifier.isIdUsed(id)) {\n\t\t\tid = new Random().nextInt();\n\t\t}\n\t\treturn id;\n\t}\n\n\tprivate static boolean isIdUsed(int id) {\n\t\treturn FluidIdentifier._fluidIdentifierIdCache.containsKey(id);\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic FluidStack makeFluidStack(int amount) {\n\t\t//FluidStack constructor does the tag.copy(), so this is safe\n\t\treturn new FluidStack(getFluid(), amount, tag);\n\t}\n\n\tpublic FluidIdentifierStack makeFluidIdentifierStack(int amount) {\n\t\t//FluidStack constructor does the tag.copy(), so this is safe\n\t\treturn new FluidIdentifierStack(this, amount);\n\t}\n\n\tpublic Fluid getFluid() {\n\t\treturn FluidRegistry.getFluid(fluidID);\n\t}\n\n\tpublic int getFreeSpaceInsideTank(IFluidTank tank) {\n\t\tFluidStack liquid = tank.getFluid();\n\t\tif (liquid == null || liquid.getFluid() == null) {\n\t\t\treturn tank.getCapacity();\n\t\t}\n\t\tif (FluidIdentifier.get(liquid).equals(this)) {\n\t\t\treturn tank.getCapacity() - liquid.amount;\n\t\t}\n\t\treturn 0;\n\t}\n\n\tprivate static boolean init = false;\n\n\tpublic static void initFromForge(boolean flag) {\n\t\tif (FluidIdentifier.init) {\n\t\t\treturn;\n\t\t}\n\t\tMap<String, Fluid> fluids = FluidRegistry.getRegisteredFluids();\n\t\tfluids.values().forEach(FluidIdentifier::get);\n\t\tif (flag) {\n\t\t\tFluidIdentifier.init = true;\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\tString t = tag != null ? tag.toString() : \"null\";\n\t\treturn name + \"/\" + fluidID + \":\" + t;\n\t}\n\n\tpublic FluidIdentifier next() {\n\t\tFluidIdentifier.rlock.lock();\n\t\tboolean takeNext = false;\n\t\tfor (FluidIdentifier i : FluidIdentifier._fluidIdentifierCache.values()) {\n\t\t\tif (takeNext && i != null) {\n\t\t\t\tFluidIdentifier.rlock.unlock();\n\t\t\t\treturn i;\n\t\t\t}\n\t\t\tif (equals(i)) {\n\t\t\t\ttakeNext = true;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier.rlock.unlock();\n\t\treturn null;\n\t}\n\n\tpublic FluidIdentifier prev() {\n\t\tFluidIdentifier.rlock.lock();\n\t\tFluidIdentifier last = null;\n\t\tfor (FluidIdentifier i : FluidIdentifier._fluidIdentifierCache.values()) {\n\t\t\tif (equals(i)) {\n\t\t\t\tFluidIdentifier.rlock.unlock();\n\t\t\t\treturn last;\n\t\t\t}\n\t\t\tif (i != null) {\n\t\t\t\tlast = i;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier.rlock.unlock();\n\t\treturn last;\n\t}\n\n\tpublic static FluidIdentifier first() {\n\t\tFluidIdentifier.rlock.lock();\n\t\tfor (FluidIdentifier i : FluidIdentifier._fluidIdentifierCache.values()) {\n\t\t\tif (i != null) {\n\t\t\t\tFluidIdentifier.rlock.unlock();\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier.rlock.unlock();\n\t\treturn null;\n\t}\n\n\tpublic static FluidIdentifier last() {\n\t\tFluidIdentifier.rlock.lock();\n\t\tFluidIdentifier last = null;\n\t\tfor (FluidIdentifier i : FluidIdentifier._fluidIdentifierCache.values()) {\n\t\t\tif (i != null) {\n\t\t\t\tlast = i;\n\t\t\t}\n\t\t}\n\t\tFluidIdentifier.rlock.unlock();\n\t\treturn last;\n\t}\n\n\tpublic static Collection<FluidIdentifier> all() {\n\t\tFluidIdentifier.rlock.lock();\n\t\tCollection<FluidIdentifier> list = Collections.unmodifiableCollection(FluidIdentifier._fluidIdentifierCache.values());\n\t\tFluidIdentifier.rlock.unlock();\n\t\treturn list;\n\t}\n\n\tpublic ItemIdentifier getItemIdentifier() {\n\t\treturn SimpleServiceLocator.logisticsFluidManager.getFluidContainer(this.makeFluidIdentifierStack(1)).getItem();\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/FluidIdentifierStack.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraftforge.fluids.FluidStack;\n\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class FluidIdentifierStack implements Comparable<FluidIdentifierStack> {\n\n\tprivate Object ccType;\n\tprivate final FluidIdentifier _fluid;\n\tprivate int milliBuckets;\n\n\tpublic FluidIdentifierStack(FluidIdentifier fluid, int milliBuckets) {\n\t\t_fluid = fluid;\n\t\tsetAmount(milliBuckets);\n\t}\n\n\tpublic static FluidIdentifierStack getFromStack(FluidStack stack) {\n\t\tFluidIdentifier fluid = FluidIdentifier.get(stack);\n\t\tif (fluid == null) return null;\n\t\treturn new FluidIdentifierStack(fluid, stack.amount);\n\t}\n\n\tpublic static FluidIdentifierStack getFromStack(ItemIdentifierStack stack) {\n\t\tFluidIdentifier fluid = FluidIdentifier.get(stack);\n\t\tif (fluid == null) return null;\n\t\treturn new FluidIdentifierStack(fluid, stack.getStackSize());\n\t}\n\n\tpublic FluidIdentifier getFluid() {\n\t\treturn _fluid;\n\t}\n\n\t/**\n\t * @return the stackSize\n\t */\n\tpublic int getAmount() {\n\t\treturn milliBuckets;\n\t}\n\n\tpublic void setAmount(int milliBuckets) {\n\t\tthis.milliBuckets = milliBuckets;\n\t}\n\n\tpublic void lowerAmount(int milliBuckets) {\n\t\tthis.milliBuckets -= milliBuckets;\n\t}\n\n\tpublic void raiseAmount(int milliBuckets) {\n\t\tthis.milliBuckets += milliBuckets;\n\t}\n\n\tpublic FluidStack makeFluidStack() {\n\t\treturn _fluid.makeFluidStack(milliBuckets);\n\t}\n\n\t@Override\n\tpublic int compareTo(FluidIdentifierStack o) {\n\t\tint c = _fluid.compareTo(o._fluid);\n\t\tif (c == 0) {\n\t\t\treturn Integer.compare(getAmount(), o.getAmount());\n\t\t}\n\t\treturn c;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/FluidSinkReply.java",
    "content": "package logisticspipes.utils;\n\npublic final class FluidSinkReply {\n\n\tpublic enum FixedFluidPriority {\n\t\tTERMINUS,\n\t\tFLUID_SINK\n\t}\n\n\tpublic final FixedFluidPriority fixedPriority;\n\tpublic final long sinkAmount;\n\n\tpublic int getSinkAmountInt() {\n\t\treturn Math.max(0, (int) Math.min(Integer.MAX_VALUE, sinkAmount));\n\t}\n\n\tpublic FluidSinkReply(FixedFluidPriority fixedPriority, long sinkAmount) {\n\t\tthis.fixedPriority = fixedPriority;\n\t\tthis.sinkAmount = sinkAmount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/IHavePriority.java",
    "content": "package logisticspipes.utils;\n\npublic interface IHavePriority {\n\n\t// a simple interface, implemented by things which have an absolute priority, on a scale other than distance or workload.\n\tint getPriority();\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/IPositionRotateble.java",
    "content": "package logisticspipes.utils;\n\npublic interface IPositionRotateble {\n\n\tvoid rotateLeft();\n\n\tvoid rotateRight();\n\n\tvoid mirrorX();\n\n\tvoid mirrorZ();\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/ISimpleInventoryEventHandler.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.inventory.IInventory;\n\npublic interface ISimpleInventoryEventHandler {\n\n\tvoid InventoryChanged(IInventory inventory);\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/InventoryHelper.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.capabilities.ICapabilityProvider;\nimport net.minecraftforge.items.CapabilityItemHandler;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.transactor.ITransactor;\nimport logisticspipes.utils.transactor.TransactorSimple;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\n\npublic class InventoryHelper {\n\n\t//BC getTransactorFor using our getInventory\n\tpublic static ITransactor getTransactorFor(Object object, EnumFacing dir) {\n\t\tif (object instanceof TileEntity) {\n\t\t\tITransactor t = SimpleServiceLocator.inventoryUtilFactory.getSpecialHandlerFor((TileEntity) object, dir, ProviderMode.DEFAULT);\n\t\t\tif (t != null) {\n\t\t\t\treturn t;\n\t\t\t}\n\t\t}\n\n\t\tif (object instanceof ICapabilityProvider && ((ICapabilityProvider) object).hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir)) {\n\t\t\treturn new TransactorSimple(((ICapabilityProvider) object).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir));\n\t\t}\n\n\t\treturn null;\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/InventoryUtil.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.items.IItemHandler;\n\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.interfaces.ISpecialInsertion;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\n\npublic class InventoryUtil implements IInventoryUtil, ISpecialInsertion {\n\n\tprotected final IItemHandler inventory;\n\tprivate final ProviderMode mode;\n\n\tpublic InventoryUtil(IItemHandler inventory, ProviderMode mode) {\n\t\tthis.inventory = inventory;\n\t\tthis.mode = mode;\n\t}\n\n\t@Override\n\tpublic int itemCount(@Nonnull ItemIdentifier item) {\n\t\tint count = 0;\n\t\tboolean first = true;\n\t\tfor (int i = mode.getCropStart(); i < inventory.getSlots() - mode.getCropEnd(); i++) {\n\t\t\tItemStack stack = inventory.getStackInSlot(i);\n\t\t\tif (stack.isEmpty() || !ItemIdentifier.get(stack).equals(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (first) {\n\t\t\t\tcount = stack.getCount() - ((mode.getHideOnePerType() || mode.getHideOnePerStack()) ? 1 : 0);\n\t\t\t\tfirst = false;\n\t\t\t} else {\n\t\t\t\tcount += stack.getCount() - (mode.getHideOnePerStack() ? 1 : 0);\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Map<ItemIdentifier, Integer> getItemsAndCount() {\n\t\tMap<ItemIdentifier, Integer> items = new LinkedHashMap<>();\n\t\tfor (int i = mode.getCropStart(); i < inventory.getSlots() - mode.getCropEnd(); i++) {\n\t\t\tItemStack stack = inventory.getStackInSlot(i);\n\t\t\tif (stack.isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemIdentifier itemId = ItemIdentifier.get(stack);\n\t\t\tint stackSize = stack.getCount() - (mode.getHideOnePerStack() ? 1 : 0);\n\t\t\tInteger currentSize = items.get(itemId);\n\t\t\tif (currentSize == null) {\n\t\t\t\titems.put(itemId, stackSize - (mode.getHideOnePerType() ? 1 : 0));\n\t\t\t} else {\n\t\t\t\titems.put(itemId, currentSize + stackSize);\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Set<ItemIdentifier> getItems() {\n\t\tSet<ItemIdentifier> items = new TreeSet<>();\n\t\tfor (int i = mode.getCropStart(); i < inventory.getSlots() - mode.getCropEnd(); i++) {\n\t\t\tItemStack stack = inventory.getStackInSlot(i);\n\t\t\tif (stack.isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\titems.add(ItemIdentifier.get(stack));\n\t\t}\n\t\treturn items;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getSingleItem(ItemIdentifier item) {\n\t\treturn getMultipleItems(item, 1);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getMultipleItems(@Nonnull ItemIdentifier item, int count) {\n\t\tif (itemCount(item) < count) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tItemStack outputStack = ItemStack.EMPTY;\n\t\tboolean first = true;\n\n\t\tfor (int i = mode.getCropStart(); i < inventory.getSlots() - mode.getCropEnd() && count > 0; i++) {\n\t\t\tItemStack stack = inventory.getStackInSlot(i);\n\t\t\tif (stack.isEmpty() || (stack.getCount() == 1 && mode.getHideOnePerStack()) || !ItemIdentifier.get(stack).equals(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tint itemsToSplit = Math.min(count, stack.getCount() - (((first && mode.getHideOnePerType()) || mode.getHideOnePerStack()) ? 1 : 0));\n\t\t\tfirst = false;\n\t\t\tif (itemsToSplit == 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack removed = inventory.extractItem(i, itemsToSplit, false);\n\t\t\tif (outputStack.isEmpty()) {\n\t\t\t\toutputStack = removed;\n\t\t\t} else {\n\t\t\t\toutputStack.setCount(outputStack.getCount() + removed.getCount());\n\t\t\t}\n\t\t\tcount -= removed.getCount();\n\t\t}\n\t\treturn outputStack;\n\t}\n\n\t//Ignores slot/item hiding\n\t@Override\n\tpublic boolean containsUndamagedItem(@Nonnull ItemIdentifier item) {\n\t\tfor (int i = 0; i < inventory.getSlots(); i++) {\n\t\t\tItemStack stack = inventory.getStackInSlot(i);\n\t\t\tif (stack.isEmpty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ItemIdentifier.get(stack).getUndamaged().equals(item)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int roomForItem(@Nonnull ItemStack stack) {\n\t\t// Special casing for \"unlimited\" storage items\n\t\tif (inventory.getSlots() == 1 && inventory.getSlotLimit(0) == Integer.MAX_VALUE) {\n\t\t\tItemStack content = inventory.extractItem(0, Integer.MAX_VALUE, true);\n\t\t\tif (content.isEmpty()) {\n\t\t\t\treturn Integer.MAX_VALUE;\n\t\t\t}\n\t\t\treturn Integer.MAX_VALUE - content.getCount();\n\t\t}\n\n\t\tint totalRoom = 0;\n\t\tfor (int i = 0; i < inventory.getSlots() && stack.getCount() > totalRoom; i++) {\n\t\t\t// stack.copy() because other TileEntities might modify stack.\n\t\t\t// \"This must not be modified by the item handler.\" lol\n\t\t\tItemStack leftover = inventory.insertItem(i, stack.copy(), true);\n\t\t\ttotalRoom += stack.getCount() - leftover.getCount();\n\t\t}\n\t\treturn totalRoom;\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn inventory.getSlots();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getStackInSlot(int i) {\n\t\treturn inventory.getStackInSlot(i);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack decrStackSize(int i, int j) {\n\t\treturn inventory.extractItem(i, j, false);\n\t}\n\n\t@Override\n\tpublic int addToSlot(@Nonnull ItemStack stack, int slot) {\n\t\tint wanted = stack.getCount();\n\t\tItemStack rest = inventory.insertItem(slot, stack.copy(), false);\n\t\treturn wanted - rest.getCount();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/InventoryUtilFactory.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils;\n\nimport java.util.ArrayList;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.IInventoryUtil;\nimport logisticspipes.proxy.specialinventoryhandler.SpecialInventoryHandler;\nimport network.rs485.logisticspipes.connection.NeighborTileEntity;\nimport network.rs485.logisticspipes.inventory.ProviderMode;\n\npublic class InventoryUtilFactory {\n\n\tprivate final ArrayList<SpecialInventoryHandler.Factory> handlerFactories = new ArrayList<>();\n\n\tpublic void registerHandler(@Nonnull SpecialInventoryHandler.Factory handlerFactory) {\n\t\tif (handlerFactory.init()) {\n\t\t\thandlerFactories.add(handlerFactory);\n\t\t\tLogisticsPipes.log.info(\"Loaded SpecialInventoryHandler.Factory: \" + handlerFactory.getClass().getCanonicalName());\n\t\t} else {\n\t\t\tLogisticsPipes.log.warn(\"Could not load SpecialInventoryHandler.Factory: \" + handlerFactory.getClass().getCanonicalName());\n\t\t}\n\t}\n\n\t@Nullable\n\tpublic SpecialInventoryHandler getSpecialHandlerFor(TileEntity tile, EnumFacing direction, ProviderMode mode) {\n\t\treturn handlerFactories.stream()\n\t\t\t\t.filter(factory -> factory.isType(tile, direction))\n\t\t\t\t.map(factory -> factory.getUtilForTile(tile, direction, mode))\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.findAny()\n\t\t\t\t.orElse(null);\n\t}\n\n\t@Nullable\n\tpublic IInventoryUtil getInventoryUtil(@Nonnull NeighborTileEntity<TileEntity> adj) {\n\t\treturn getHidingInventoryUtil(adj.getTileEntity(), adj.getOurDirection(), ProviderMode.DEFAULT);\n\t}\n\n\t@Nullable\n\tpublic IInventoryUtil getInventoryUtil(TileEntity inv, EnumFacing dir) {\n\t\treturn getHidingInventoryUtil(inv, dir, ProviderMode.DEFAULT);\n\t}\n\n\t@Nullable\n\tpublic IInventoryUtil getHidingInventoryUtil(@Nullable TileEntity tile, @Nullable EnumFacing direction, @Nonnull ProviderMode mode) {\n\t\tif (tile != null) {\n\t\t\tIInventoryUtil util = getSpecialHandlerFor(tile, direction, mode);\n\t\t\tif (util != null) {\n\t\t\t\treturn util;\n\t\t\t} else if (tile.hasCapability(LogisticsPipes.ITEM_HANDLER_CAPABILITY, direction)) {\n\t\t\t\treturn new InventoryUtil(tile.getCapability(LogisticsPipes.ITEM_HANDLER_CAPABILITY, direction), mode);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/LPPositionSet.java",
    "content": "package logisticspipes.utils;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.HashSet;\n\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport lombok.SneakyThrows;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class LPPositionSet<T extends DoubleCoordinates> extends HashSet<T> implements IPositionRotateble {\n\n\tprivate static final long serialVersionUID = -3611750920959862658L;\n\tprivate Class<T> clazz;\n\n\tpublic LPPositionSet(Class<?> clazz) {\n\t\tthis.clazz = (Class<T>) clazz;\n\t}\n\n\tpublic int getMaxX() {\n\t\treturn (int) getMaxXD();\n\t}\n\n\tpublic int getMaxY() {\n\t\treturn (int) getMaxYD();\n\t}\n\n\tpublic int getMaxZ() {\n\t\treturn (int) getMaxZD();\n\t}\n\n\tpublic int getMinX() {\n\t\treturn (int) getMaxXD();\n\t}\n\n\tpublic int getMinY() {\n\t\treturn (int) getMaxYD();\n\t}\n\n\tpublic int getMinZ() {\n\t\treturn (int) getMaxZD();\n\t}\n\n\tpublic double getMaxXD() {\n\t\tdouble x = -Double.MAX_VALUE;\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\tx = Math.max(x, pos.getXDouble());\n\t\t}\n\t\treturn x;\n\t}\n\n\tpublic double getMaxYD() {\n\t\tdouble y = -Double.MAX_VALUE;\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\ty = Math.max(y, pos.getYDouble());\n\t\t}\n\t\treturn y;\n\t}\n\n\tpublic double getMaxZD() {\n\t\tdouble z = -Double.MAX_VALUE;\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\tz = Math.max(z, pos.getZDouble());\n\t\t}\n\t\treturn z;\n\t}\n\n\tpublic double getMinXD() {\n\t\tdouble x = Double.MAX_VALUE;\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\tx = Math.min(x, pos.getXDouble());\n\t\t}\n\t\treturn x;\n\t}\n\n\tpublic double getMinYD() {\n\t\tdouble y = Double.MAX_VALUE;\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\ty = Math.min(y, pos.getYDouble());\n\t\t}\n\t\treturn y;\n\t}\n\n\tpublic double getMinZD() {\n\t\tdouble z = Double.MAX_VALUE;\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\tz = Math.min(z, pos.getZDouble());\n\t\t}\n\t\treturn z;\n\t}\n\n\tpublic void addToAll(DoubleCoordinates lpPosition) {\n\t\tfor (DoubleCoordinates pos : this) {\n\t\t\tpos.add(lpPosition);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void rotateLeft() {\n\t\tthis.forEach(DoubleCoordinates::rotateLeft);\n\t}\n\n\t@Override\n\tpublic void rotateRight() {\n\t\tthis.forEach(DoubleCoordinates::rotateRight);\n\t}\n\n\tpublic AxisAlignedBB toABB() {\n\t\treturn new AxisAlignedBB(getMinXD(), getMinYD(), getMinZD(), getMaxXD(), getMaxYD(), getMaxZD());\n\t}\n\n\t@Override\n\tpublic void mirrorX() {\n\t\tthis.forEach(DoubleCoordinates::mirrorX);\n\t}\n\n\t@Override\n\tpublic void mirrorZ() {\n\t\tthis.forEach(DoubleCoordinates::mirrorZ);\n\t}\n\n\t@SneakyThrows({ NoSuchMethodException.class, IllegalAccessException.class, InvocationTargetException.class, InstantiationException.class })\n\tpublic void addFrom(AxisAlignedBB completeBox) {\n\t\tadd(clazz.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE).newInstance(completeBox.minX, completeBox.minY, completeBox.minZ));\n\t\tadd(clazz.getConstructor(Double.TYPE, Double.TYPE, Double.TYPE).newInstance(completeBox.maxX, completeBox.maxY, completeBox.maxZ));\n\t}\n\n\tpublic DoubleCoordinates getCenter() {\n\t\treturn new DoubleCoordinates((getMaxXD() - getMinXD()) / 2 + getMinXD(), (getMaxYD() - getMinYD()) / 2 + getMinYD(), (getMaxZD() - getMinZD()) / 2 + getMinZD());\n\t}\n\n\tpublic T findClosest(DoubleCoordinates posToLookFor) {\n\t\tdouble distance = Double.MAX_VALUE;\n\t\tT closest = null;\n\t\tfor (T posToLookAt : this) {\n\t\t\tif (closest == null || posToLookFor.distanceTo(posToLookAt) < distance) {\n\t\t\t\tclosest = posToLookAt;\n\t\t\t\tdistance = posToLookFor.distanceTo(posToLookAt);\n\t\t\t}\n\t\t}\n\t\treturn closest;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/MinecraftColor.java",
    "content": "package logisticspipes.utils;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.init.Items;\nimport net.minecraft.item.ItemStack;\n\npublic enum MinecraftColor {\n\tBLACK(0xff000000),\n\tRED(0xffff0000),\n\tGREEN(0xff00ff00),\n\tBROWN(0xff895836),\n\tBLUE(0xff0000ff),\n\tPURPLE(0xffB064D8),\n\tCYAN(0xff3C8EB0),\n\tLIGHT_GRAY(0xffBABAC1),\n\tGRAY(0xff848484),\n\tPINK(0xffF7B4D6),\n\tLIME(0xff83D41C),\n\tYELLOW(0xffE7E72A),\n\tLIGHT_BLUE(0xff82ACE7),\n\tMAGENTA(0xffDB7AD5),\n\tORANGE(0xffE69E34),\n\tWHITE(0xffffffff),\n\tBLANK(0x00000000);\n\n\tprivate final int colorCode;\n\n\tMinecraftColor(int colorCode) {\n\t\tthis.colorCode = colorCode;\n\t}\n\n\tpublic static MinecraftColor getColor(@Nonnull ItemStack item) {\n\t\tif (!item.isEmpty()) {\n\t\t\tif (item.getItem() == Items.DYE && item.getItemDamage() < 16) {\n\t\t\t\treturn MinecraftColor.values()[item.getItemDamage()];\n\t\t\t}\n\t\t}\n\t\treturn BLANK;\n\t}\n\n\tpublic int getColorCode() {\n\t\treturn colorCode;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getItemStack() {\n\t\tif (this == BLANK) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn new ItemStack(Items.DYE, 1, ordinal());\n\t}\n\n\tpublic MinecraftColor getNext() {\n\t\tif (this == BLANK) {\n\t\t\treturn BLACK;\n\t\t}\n\t\treturn MinecraftColor.values()[ordinal() + 1];\n\t}\n\n\tpublic MinecraftColor getPrev() {\n\t\tif (this == BLACK) {\n\t\t\treturn BLANK;\n\t\t}\n\t\treturn MinecraftColor.values()[ordinal() - 1];\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/ModStatusHelper.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraftforge.fml.common.Loader;\nimport net.minecraftforge.fml.common.ModAPIManager;\nimport net.minecraftforge.fml.common.ModContainer;\nimport net.minecraftforge.fml.common.versioning.ComparableVersion;\n\npublic class ModStatusHelper {\n\n\tpublic static boolean isModLoaded(String modId) {\n\t\tif (modId.contains(\"@\")) {\n\t\t\tString version = modId.substring(modId.indexOf('@') + 1);\n\t\t\tmodId = modId.substring(0, modId.indexOf('@'));\n\t\t\tif (Loader.isModLoaded(modId)) {\n\t\t\t\tModContainer mod = Loader.instance().getIndexedModList().get(modId);\n\t\t\t\tif (mod != null) {\n\t\t\t\t\treturn mod.getVersion().startsWith(version);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if (Loader.isModLoaded(modId)) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn ModAPIManager.INSTANCE.hasAPI(modId);\n\t\t}\n\t}\n\n\tpublic static boolean areModsLoaded(String modIds) {\n\t\tif (modIds.contains(\"+\")) {\n\t\t\tfor (String modId : modIds.split(\"\\\\+\")) {\n\t\t\t\tif (!isModLoaded(modId)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn isModLoaded(modIds);\n\t\t}\n\t}\n\n\tpublic static boolean isModVersionEqualsOrHigher(String modId, String version) {\n\t\tComparableVersion v1 = new ComparableVersion(version);\n\t\tModContainer mod = Loader.instance().getIndexedModList().get(modId);\n\t\tif (mod != null) {\n\t\t\tComparableVersion v2 = new ComparableVersion(mod.getVersion());\n\t\t\treturn v1.compareTo(v2) <= 0;\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/OneList.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ListIterator;\nimport javax.annotation.Nonnull;\n\npublic class OneList<E> implements List<E> {\n\n\tprivate final E content;\n\n\tpublic OneList(E object) {\n\t\tif (object == null) {\n\t\t\tthrow new NullPointerException(\"OneList content must not be null\");\n\t\t}\n\t\tthis.content = object;\n\t}\n\n\t@Override\n\tpublic boolean add(E e) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic void add(int index, E element) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic boolean addAll(@Nonnull Collection<? extends E> c) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic boolean addAll(int index, @Nonnull Collection<? extends E> c) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic void clear() {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic boolean contains(Object o) {\n\t\treturn content.equals(o);\n\t}\n\n\t@Override\n\tpublic boolean containsAll(Collection<?> c) {\n\t\treturn c.size() == 1 && content.equals(c.iterator().next());\n\t}\n\n\t@Override\n\tpublic E get(int index) {\n\t\tif (!checkRange(index)) {\n\t\t\tthrow new IndexOutOfBoundsException(\"OneList does not have an object at index \" + index);\n\t\t}\n\t\treturn content;\n\t}\n\n\t@Override\n\tpublic int indexOf(Object o) {\n\t\tif (content.equals(o)) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterator<E> iterator() {\n\t\treturn listIterator();\n\t}\n\n\t@Override\n\tpublic int lastIndexOf(Object o) {\n\t\treturn indexOf(o);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ListIterator<E> listIterator() {\n\t\treturn new ListIterator<E>() {\n\n\t\t\tprivate boolean handled = false;\n\n\t\t\t@Override\n\t\t\tpublic boolean hasNext() {\n\t\t\t\treturn !handled;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic E next() {\n\t\t\t\tif (handled) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\thandled = true;\n\t\t\t\treturn OneList.this.content;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic boolean hasPrevious() {\n\t\t\t\treturn handled;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic E previous() {\n\t\t\t\tif (!handled) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\thandled = false;\n\t\t\t\treturn OneList.this.content;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int nextIndex() {\n\t\t\t\treturn handled ? 1 : 0;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic int previousIndex() {\n\t\t\t\treturn handled ? 0 : -1;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void remove() {\n\t\t\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void set(E e) {\n\t\t\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void add(E e) {\n\t\t\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t\t\t}\n\t\t};\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ListIterator<E> listIterator(int index) {\n\t\tif (!checkRange(index)) {\n\t\t\tthrow new IndexOutOfBoundsException(\"OneList does not have an object at index \" + index);\n\t\t}\n\t\treturn listIterator();\n\t}\n\n\t@Override\n\tpublic boolean remove(Object o) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic E remove(int index) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic boolean removeAll(@Nonnull Collection<?> c) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic boolean retainAll(@Nonnull Collection<?> c) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic E set(int index, E element) {\n\t\tthrow new UnsupportedOperationException(\"Cannot modify OneList\");\n\t}\n\n\t@Override\n\tpublic int size() {\n\t\treturn 1;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<E> subList(int fromIndex, int toIndex) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Object[] toArray() {\n\t\treturn new Object[] { content };\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <T> T[] toArray(@Nonnull T[] a) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\treturn obj instanceof OneList && content.equals(((OneList<?>) obj).content);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"[\" + content.toString() + \"]\";\n\t}\n\n\tprivate boolean checkRange(int index) {\n\t\treturn index == 0;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/OrientationsUtil.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\n\npublic class OrientationsUtil {\n\n\tpublic static EnumFacing getOrientationOfTilewithTile(TileEntity pipeTile, TileEntity tileTile) {\n\t\tfinal BlockPos pipe = pipeTile.getPos();\n\t\tfinal BlockPos other = tileTile.getPos();\n\t\tif (pipe.getZ() == other.getZ()) {\n\t\t\tif (pipe.getY() == other.getY()) {\n\t\t\t\tif (pipe.getX() < other.getX()) {\n\t\t\t\t\treturn EnumFacing.EAST;\n\t\t\t\t} else if (pipe.getX() > other.getX()) {\n\t\t\t\t\treturn EnumFacing.WEST;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (pipe.getX() == other.getX()) {\n\t\t\tif (pipe.getZ() == other.getZ()) {\n\t\t\t\tif (pipe.getY() < other.getY()) {\n\t\t\t\t\treturn EnumFacing.UP;\n\t\t\t\t} else if (pipe.getY() > other.getY()) {\n\t\t\t\t\treturn EnumFacing.DOWN;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (pipe.getX() == other.getX()) {\n\t\t\tif (pipe.getY() == other.getY()) {\n\t\t\t\tif (pipe.getZ() < other.getZ()) {\n\t\t\t\t\treturn EnumFacing.SOUTH;\n\t\t\t\t} else if (pipe.getZ() > other.getZ()) {\n\t\t\t\t\treturn EnumFacing.NORTH;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/PlayerCollectionList.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\n\npublic class PlayerCollectionList {\n\n\tprivate List<EqualWeakReference<EntityPlayer>> players = new ArrayList<>();\n\tprivate boolean checkingPlayers = false;\n\n\tpublic void checkPlayers() {\n\t\tcheckingPlayers = true;\n\t\tIterator<EqualWeakReference<EntityPlayer>> iPlayers = players.iterator();\n\t\twhile (iPlayers.hasNext()) {\n\t\t\tEqualWeakReference<EntityPlayer> playerReference = iPlayers.next();\n\t\t\tboolean remove = false;\n\t\t\tif (playerReference.get() == null) {\n\t\t\t\tremove = true;\n\t\t\t} else if (playerReference.get().isDead) {\n\t\t\t\tremove = true;\n\t\t\t} else if (playerReference.get() instanceof EntityPlayerMP) {\n\t\t\t\tif (!((EntityPlayerMP) playerReference.get()).connection.netManager.isChannelOpen()) {\n\t\t\t\t\tremove = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (remove) {\n\t\t\t\tiPlayers.remove();\n\t\t\t}\n\t\t}\n\t\tcheckingPlayers = false;\n\t}\n\n\tpublic Iterable<EntityPlayer> players() {\n\t\tcheckPlayers();\n\t\treturn () -> new Itr(players.iterator());\n\t}\n\n\tpublic int size() {\n\t\tif (!checkingPlayers) {\n\t\t\tcheckPlayers();\n\t\t}\n\t\treturn players.size();\n\t}\n\n\tpublic boolean isEmpty() {\n\t\treturn size() == 0;\n\t}\n\n\tpublic boolean isEmptyWithoutCheck() {\n\t\treturn players.size() == 0;\n\t}\n\n\tpublic void add(EntityPlayer player) {\n\t\tplayers.add(new EqualWeakReference<>(player));\n\t}\n\n\tpublic boolean remove(EntityPlayer player) {\n\t\tif (contains(player) && players.size() > 0) {\n\t\t\treturn players.remove(new EqualWeakReference<>(player));\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic boolean contains(EntityPlayer player) {\n\t\tcheckPlayers();\n\t\treturn players.contains(new EqualWeakReference<>(player));\n\t}\n\n\tprivate static class Itr implements Iterator<EntityPlayer> {\n\n\t\tprivate final Iterator<EqualWeakReference<EntityPlayer>> iterator;\n\n\t\tprivate Itr(Iterator<EqualWeakReference<EntityPlayer>> source) {\n\t\t\titerator = source;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean hasNext() {\n\t\t\treturn iterator.hasNext();\n\t\t}\n\n\t\t@Override\n\t\tpublic EntityPlayer next() {\n\t\t\tEqualWeakReference<EntityPlayer> reference = iterator.next();\n\t\t\treturn reference.get();\n\t\t}\n\n\t\t@Override\n\t\tpublic void remove() {\n\t\t\titerator.remove();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/PlayerIdentifier.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport lombok.experimental.Accessors;\n\n@Accessors(chain = true)\npublic class PlayerIdentifier {\n\n\tprivate static Map<UUID, PlayerIdentifier> idBased = new HashMap<>();\n\tprivate static Map<String, PlayerIdentifier> nameBased = new HashMap<>();\n\n\tprivate PlayerIdentifier(String username, UUID id) {\n\t\tthis.username = username;\n\t\tthis.id = id;\n\t}\n\n\tprivate String username;\n\tprivate UUID id;\n\n\tpublic UUID getId() {\n\t\treturn id;\n\t}\n\n\tpublic String getUsername() {\n\t\treturn username;\n\t}\n\n\tpublic static PlayerIdentifier get(EntityPlayer player) {\n\t\treturn PlayerIdentifier.get(player.getGameProfile().getName(), player.getGameProfile().getId());\n\t}\n\n\tpublic static PlayerIdentifier get(String username, UUID id) {\n\t\tif (PlayerIdentifier.idBased.containsKey(id)) {\n\t\t\treturn PlayerIdentifier.idBased.get(id).setUsername(username);\n\t\t}\n\t\tif (PlayerIdentifier.nameBased.containsKey(username)) {\n\t\t\treturn PlayerIdentifier.nameBased.get(username);\n\t\t}\n\t\tif (id != null) {\n\t\t\tPlayerIdentifier ident = new PlayerIdentifier(username, id);\n\t\t\tPlayerIdentifier.idBased.put(id, ident);\n\t\t\treturn ident;\n\t\t}\n\t\tif (username == null) {\n\t\t\tthrow new NullPointerException();\n\t\t}\n\t\tPlayerIdentifier ident = new PlayerIdentifier(username, id);\n\t\tPlayerIdentifier.nameBased.put(username, ident);\n\t\treturn ident;\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbt, String prefix) {\n\t\tif (id != null) {\n\t\t\tnbt.setString(prefix + \"_id\", id.toString());\n\t\t}\n\t\tnbt.setString(prefix + \"_name\", username);\n\t}\n\n\tpublic static PlayerIdentifier readFromNBT(NBTTagCompound nbt, String prefix) {\n\t\tUUID id = null;\n\t\tif (nbt.hasKey(prefix + \"_id\")) {\n\t\t\tString tmp = nbt.getString(prefix + \"_id\");\n\t\t\ttry {\n\t\t\t\tid = UUID.fromString(tmp);\n\t\t\t} catch (Exception ignored) {}\n\t\t}\n\t\tString username = nbt.getString(prefix + \"_name\");\n\t\treturn PlayerIdentifier.get(username, id);\n\t}\n\n\tpublic static PlayerIdentifier convertFromUsername(String name) {\n\t\treturn PlayerIdentifier.get(name, null);\n\t}\n\n\tpublic PlayerIdentifier setUsername(String string) {\n\t\tif (username == null || username.isEmpty()) {\n\t\t\tusername = string;\n\t\t}\n\t\treturn this;\n\t}\n\n\tpublic PlayerIdentifier setID(UUID uuid) {\n\t\tif (id == null) {\n\t\t\tid = uuid;\n\t\t\tPlayerIdentifier.idBased.put(id, this);\n\t\t}\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn id.toString();\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn id.hashCode();\n\t}\n\n\t@Override\n\tpublic boolean equals(Object obj) {\n\t\tif (obj instanceof PlayerIdentifier) {\n\t\t\treturn id.equals(((PlayerIdentifier) obj).id);\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/QuickSortChestMarkerStorage.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Collection;\nimport java.util.HashMap;\n\nimport lombok.Getter;\n\nimport logisticspipes.utils.tuples.Quartet;\n\npublic class QuickSortChestMarkerStorage {\n\n\t@Getter\n\tprivate static final QuickSortChestMarkerStorage instance = new QuickSortChestMarkerStorage();\n\n\tprivate QuickSortChestMarkerStorage() {}\n\n\tprivate HashMap<Quartet<Integer, Integer, Integer, Integer>, Integer> marker = new HashMap<>();\n\n\t@Getter\n\tprivate boolean isActivated = false;\n\n\tpublic void setSlots(int x, int y, int z, int slot, int pos) {\n\t\tif (isActivated) {\n\t\t\tmarker.put(new Quartet<>(x, y, z, slot), pos);\n\t\t}\n\t}\n\n\tpublic void enable() {\n\t\tisActivated = true;\n\t}\n\n\tpublic void disable() {\n\t\tmarker.clear();\n\t\tisActivated = false;\n\t}\n\n\tpublic Collection<Integer> getMarker() {\n\t\treturn marker.values();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/ReflectionHelper.java",
    "content": "package logisticspipes.utils;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport lombok.SneakyThrows;\n\nimport logisticspipes.utils.tuples.Pair;\nimport logisticspipes.utils.tuples.Triplet;\n\npublic class ReflectionHelper {\n\n\tprivate static final Map<Triplet<Class<?>, String, List<Class<?>>>, Method> methodCache = new HashMap<>();\n\tprivate static final Map<Pair<Class<?>, String>, Field> fieldCache = new HashMap<>();\n\n\t@SuppressWarnings(\"unchecked\")\n\t@SneakyThrows\n\tpublic static <T> T invokePrivateMethod(Class<?> clazz, Object target, String name, String srgName, Class<?>[] classes, Object[] objects) {\n\t\tTriplet<Class<?>, String, List<Class<?>>> key = new Triplet<>(clazz, name, Arrays.asList(classes));\n\t\tMethod method = ReflectionHelper.methodCache.get(key);\n\t\tif (method == null) {\n\t\t\ttry {\n\t\t\t\tmethod = clazz.getDeclaredMethod(name, classes);\n\t\t\t} catch (NoSuchMethodException e1) {\n\t\t\t\ttry {\n\t\t\t\t\tmethod = clazz.getMethod(name, classes);\n\t\t\t\t} catch (NoSuchMethodException e2) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmethod = clazz.getDeclaredMethod(srgName, classes);\n\t\t\t\t\t} catch (NoSuchMethodException e3) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tmethod = clazz.getMethod(srgName, classes);\n\t\t\t\t\t\t} catch (NoSuchMethodException e4) {\n\t\t\t\t\t\t\tmethod = clazz.getDeclaredMethod(name, classes);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tmethod.setAccessible(true);\n\t\t\tReflectionHelper.methodCache.put(key, method);\n\t\t}\n\t\tObject result = method.invoke(target, objects);\n\t\treturn (T) result;\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\t@SneakyThrows\n\tpublic static <T> T getPrivateField(Class<?> clazz, Object target, String name, String srgName) {\n\t\tField field = getField(clazz, name, srgName);\n\t\tObject result = field.get(target);\n\t\treturn (T) result;\n\t}\n\n\t@SneakyThrows\n\tpublic static void setPrivateField(Class<?> clazz, Object target, String name, String srgName, Object value) {\n\t\tField field = getField(clazz, name, srgName);\n\t\tfield.set(target, value);\n\t}\n\n\tprivate static Field getField(Class<?> clazz, String name, String srgName) throws NoSuchFieldException {\n\t\tPair<Class<?>, String> key = new Pair<>(clazz, name);\n\t\tField field = ReflectionHelper.fieldCache.get(key);\n\t\tif (field == null) {\n\t\t\ttry {\n\t\t\t\tfield = clazz.getDeclaredField(name);\n\t\t\t} catch (NoSuchFieldException e1) {\n\t\t\t\ttry {\n\t\t\t\t\tfield = clazz.getField(name);\n\t\t\t\t} catch (NoSuchFieldException e2) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfield = clazz.getDeclaredField(srgName);\n\t\t\t\t\t} catch (NoSuchFieldException e3) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfield = clazz.getField(srgName);\n\t\t\t\t\t\t} catch (NoSuchFieldException e4) {\n\t\t\t\t\t\t\tfield = clazz.getDeclaredField(name);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfield.setAccessible(true);\n\t\t\tReflectionHelper.fieldCache.put(key, field);\n\t\t}\n\t\treturn field;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/RoutedItemHelper.java",
    "content": "package logisticspipes.utils;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.routing.ItemRoutingInformation;\nimport logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic class RoutedItemHelper {\n\n\tpublic LPTravelingItemServer createNewTravelItem(@Nonnull ItemStack item) {\n\t\treturn createNewTravelItem(ItemIdentifierStack.getFromStack(item));\n\t}\n\n\tpublic LPTravelingItemServer createNewTravelItem(ItemIdentifierStack item) {\n\t\treturn new LPTravelingItemServer(item);\n\t}\n\n\tpublic LPTravelingItemServer createNewTravelItem(ItemRoutingInformation info) {\n\t\treturn new LPTravelingItemServer(info);\n\t}\n\n\tpublic LPTravelingItemServer getServerTravelingItem(IRoutedItem item) {\n\t\treturn (LPTravelingItemServer) item;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/SafeTimeTracker.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.world.World;\n\npublic class SafeTimeTracker {\n\n\tprivate long lastMark = Long.MIN_VALUE;\n\tprivate long duration = -1;\n\tprivate long randomRange = 0;\n\tprivate long lastRandomDelay = 0;\n\tprivate long internalDelay;\n\n\tpublic SafeTimeTracker(long delay) {\n\t\tinternalDelay = delay;\n\t}\n\n\t/**\n\t * In many situations, it is a bad idea to have all objects of the same kind\n\t * to be waiting for the exact same amount of time, as that can lead to some\n\t * situation where they're all synchronized and got to work all at the same\n\t * time. When created with a random range, the mark that is set when\n\t * reaching the expect delay will be added with a random number between [0,\n\t * range[, meaning that the event will take between 0 and range more tick to\n\t * run.\n\t */\n\tpublic SafeTimeTracker(long delay, long random) {\n\t\tinternalDelay = delay;\n\t\trandomRange = random;\n\t}\n\n\tpublic boolean markTimeIfDelay(World world) {\n\t\treturn markTimeIfDelay(world, internalDelay);\n\t}\n\n\tprivate boolean markTimeIfDelay(World world, long delay) {\n\t\tif (world == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlong currentTime = world.getTotalWorldTime();\n\n\t\tif (currentTime < lastMark) {\n\t\t\tlastMark = currentTime;\n\t\t\treturn false;\n\t\t} else if (lastMark + delay + lastRandomDelay <= currentTime) {\n\t\t\tduration = currentTime - lastMark;\n\t\t\tlastMark = currentTime;\n\t\t\tlastRandomDelay = (int) (Math.random() * randomRange);\n\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tpublic long durationOfLastDelay() {\n\t\treturn duration > 0 ? duration : 0;\n\t}\n\n\tpublic void markTime(World world) {\n\t\tlastMark = world.getTotalWorldTime();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/SinkReply.java",
    "content": "package logisticspipes.utils;\n\nimport logisticspipes.interfaces.routing.IAdditionalTargetInformation;\n\npublic final class SinkReply {\n\n\tpublic enum FixedPriority {\n\t\tDefaultRoute,\n\t\tModBasedItemSink,\n\t\tOreDictItemSink,\n\t\tEnchantmentItemSink,\n\t\tTerminus,\n\t\tItemSink,\n\t\tPassiveSupplier,\n\t}\n\n\tpublic enum BufferMode {\n\t\tNONE,\n\t\tBUFFERED,\n\t\tDESTINATION_BUFFERED,\n\t}\n\n\tpublic final FixedPriority fixedPriority;\n\tpublic final int customPriority;\n\tpublic final boolean isPassive;\n\tpublic final boolean isDefault;\n\tpublic final int energyUse;\n\tpublic final int maxNumberOfItems;\n\tpublic final BufferMode bufferMode;\n\tpublic final IAdditionalTargetInformation addInfo;\n\n\tpublic SinkReply(FixedPriority fixedPriority, int customPriority, boolean isPassive, boolean isDefault, int energyUse, int maxNumberOfItems, IAdditionalTargetInformation addInfo) {\n\t\tthis.fixedPriority = fixedPriority;\n\t\tthis.customPriority = customPriority;\n\t\tthis.isPassive = isPassive;\n\t\tthis.isDefault = isDefault;\n\t\tthis.energyUse = energyUse;\n\t\tthis.maxNumberOfItems = maxNumberOfItems;\n\t\tbufferMode = BufferMode.NONE;\n\t\tthis.addInfo = addInfo;\n\t}\n\n\tpublic SinkReply(SinkReply base, int maxNumberOfItems) {\n\t\tfixedPriority = base.fixedPriority;\n\t\tcustomPriority = base.customPriority;\n\t\tisPassive = base.isPassive;\n\t\tisDefault = base.isDefault;\n\t\tenergyUse = base.energyUse;\n\t\tthis.maxNumberOfItems = maxNumberOfItems;\n\t\tbufferMode = BufferMode.NONE;\n\t\taddInfo = base.addInfo;\n\t}\n\n\tpublic SinkReply(SinkReply base, int maxNumberOfItems, BufferMode bufferMode) {\n\t\tfixedPriority = base.fixedPriority;\n\t\tcustomPriority = base.customPriority;\n\t\tisPassive = base.isPassive;\n\t\tisDefault = base.isDefault;\n\t\tenergyUse = base.energyUse;\n\t\tthis.maxNumberOfItems = maxNumberOfItems;\n\t\tthis.bufferMode = bufferMode;\n\t\taddInfo = base.addInfo;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/SlidingWindowBitSet.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.BitSet;\n\npublic class SlidingWindowBitSet {\n\n\tprivate final BitSet set = new BitSet();\n\tprivate final int window;\n\tprivate int currentEx = -1;\n\tprivate int cleared;\n\n\tpublic SlidingWindowBitSet(int window) {\n\t\tthis.window = window;\n\t}\n\n\tpublic void set(long i, boolean b) {\n\t\tint mod = (int) i & ((1 << window) - 1);\n\t\tcheckEx(i);\n\t\tset.set(mod, b);\n\t}\n\n\tpublic void set(long i) {\n\t\tint mod = (int) i & ((1 << window) - 1);\n\t\tcheckEx(i);\n\t\tset.set(mod);\n\t}\n\n\tpublic boolean get(long i) {\n\t\tint mod = (int) i & ((1 << window) - 1);\n\t\tcheckEx(i);\n\t\treturn set.get(mod);\n\t}\n\n\tprivate void checkEx(long i) {\n\t\tint bit = (1 << window);\n\t\tint mod = (int) i & bit - 1;\n\t\tint ex = (int) i >> window;\n\t\tif (currentEx < ex) {\n\t\t\tif (cleared < bit) {\n\t\t\t\tset.clear(cleared, bit);\n\t\t\t}\n\t\t\tcurrentEx = ex;\n\t\t\tcleared = 0;\n\t\t}\n\t\tif (cleared <= mod && currentEx == ex) {\n\t\t\tint clear_till = ((mod >> 6) + 1) << 6;\n\t\t\tset.clear(cleared, clear_till);\n\t\t\tcleared = clear_till;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/SpecialTankUtil.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.tileentity.TileEntity;\n\nimport net.minecraftforge.fluids.capability.IFluidHandler;\n\nimport logisticspipes.interfaces.ISpecialTankAccessHandler;\nimport logisticspipes.interfaces.ISpecialTankUtil;\n\npublic class SpecialTankUtil extends TankUtil implements ISpecialTankUtil {\n\n\tprivate TileEntity tile;\n\tprivate ISpecialTankAccessHandler handler;\n\n\tpublic SpecialTankUtil(IFluidHandler fluid, TileEntity tile, ISpecialTankAccessHandler handler) {\n\t\tsuper(fluid);\n\t\tthis.tile = tile;\n\t\tthis.handler = handler;\n\t}\n\n\t@Override\n\tpublic TileEntity getTileEntity() {\n\t\treturn tile;\n\t}\n\n\t@Override\n\tpublic ISpecialTankAccessHandler getSpecialHandler() {\n\t\treturn handler;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/StackTraceUtil.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.function.Supplier;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class StackTraceUtil {\n\n\tprivate static final Map<Thread, LinkedList<Pair<StackTraceElement, String>>> informationMap = new HashMap<>();\n\n\tpublic static abstract class Info {\n\n\t\tpublic abstract void end();\n\t}\n\n\tprivate static class DummyInfo extends Info {\n\n\t\t@Override\n\t\tpublic void end() {}\n\t}\n\n\tprivate static LinkedList<Pair<StackTraceElement, String>> getList() {\n\t\treturn StackTraceUtil.informationMap.computeIfAbsent(Thread.currentThread(), k -> new LinkedList<>());\n\t}\n\n\tpublic static Info addTraceInformation(final Supplier<String> informationSupplier, Info... infos) {\n\t\tif (!LogisticsPipes.isDEBUG()) {\n\t\t\treturn new DummyInfo();\n\t\t}\n\t\tStackTraceElement[] trace = Thread.currentThread().getStackTrace();\n\t\tfinal StackTraceElement calledFrom = trace[2];\n\t\treturn StackTraceUtil.addTraceInformationFor(calledFrom, informationSupplier.get(), infos);\n\t}\n\n\tpublic static Info addSuperTraceInformation(final Supplier<String> informationSupplier, Info... infos) {\n\t\tif (!LogisticsPipes.isDEBUG()) {\n\t\t\treturn new DummyInfo();\n\t\t}\n\t\tStackTraceElement[] trace = Thread.currentThread().getStackTrace();\n\t\tfinal StackTraceElement calledFrom = trace[3];\n\t\treturn StackTraceUtil.addTraceInformationFor(calledFrom, informationSupplier.get(), infos);\n\t}\n\n\tprivate static Info addTraceInformationFor(final StackTraceElement calledFrom, final String information, final Info... infos) {\n\t\tsynchronized (StackTraceUtil.informationMap) {\n\t\t\tStackTraceUtil.getList().addLast(new Pair<>(calledFrom, information));\n\t\t\treturn new Info() {\n\n\t\t\t\t@Override\n\t\t\t\tpublic void end() {\n\t\t\t\t\tsynchronized (StackTraceUtil.informationMap) {\n\t\t\t\t\t\tif (StackTraceUtil.getList().isEmpty()) {\n\t\t\t\t\t\t\tthrow new RuntimeException(\"There are to many end() calls\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tPair<StackTraceElement, String> pair = StackTraceUtil.getList().getLast();\n\t\t\t\t\t\t\tif (!pair.getValue1().equals(calledFrom)) {\n\t\t\t\t\t\t\t\tSystem.out.println(\"Found: \" + pair.getValue1());\n\t\t\t\t\t\t\t\tSystem.out.println(\"Looking for: \" + calledFrom);\n\t\t\t\t\t\t\t\tthrow new RuntimeException(\"There is an end() call missing\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tStackTraceUtil.getList().removeLast();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (infos != null) {\n\t\t\t\t\t\tfor (Info info : infos) {\n\t\t\t\t\t\t\tinfo.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t}\n\n\tpublic static void printTrace() {\n\t\tsynchronized (System.err) {\n\t\t\tsynchronized (StackTraceUtil.informationMap) {\n\t\t\t\t// Print our stack trace\n\t\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\t\tLinkedList<StackTraceElement> traceList = new LinkedList<>(Arrays.asList(Thread.currentThread().getStackTrace()));\n\t\t\t\ttraceList.removeFirst();\n\t\t\t\ttraceList.removeFirst();\n\t\t\t\tLinkedList<Pair<StackTraceElement, String>> paired = new LinkedList<>();\n\t\t\t\tPair<StackTraceElement, String> lastFound = null;\n\t\t\t\tStackTraceElement current = traceList.removeLast();\n\t\t\t\twhile (current != null) {\n\t\t\t\t\tIterator<Pair<StackTraceElement, String>> iter = StackTraceUtil.getList().iterator();\n\t\t\t\t\tif (lastFound != null) {\n\t\t\t\t\t\twhile (iter.hasNext()) {\n\t\t\t\t\t\t\tPair<StackTraceElement, String> pair = iter.next();\n\t\t\t\t\t\t\tif (pair == lastFound) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tString result = null;\n\t\t\t\t\twhile (iter.hasNext()) {\n\t\t\t\t\t\tPair<StackTraceElement, String> pair = iter.next();\n\t\t\t\t\t\tif (StackTraceUtil.compare(current, pair.getValue1())) {\n\t\t\t\t\t\t\tlastFound = pair;\n\t\t\t\t\t\t\tresult = pair.getValue2();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpaired.addFirst(new Pair<>(current, result));\n\t\t\t\t\tif (traceList.isEmpty()) {\n\t\t\t\t\t\tcurrent = null;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrent = traceList.removeLast();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tSystem.err.print(\"StackTrace\");\n\t\t\t\tSystem.err.print(System.lineSeparator());\n\t\t\t\tfor (Pair<StackTraceElement, String> pair : paired) {\n\t\t\t\t\tSystem.err.print(\"\\tat \" + pair.getValue1());\n\t\t\t\t\tif (pair.getValue2() != null) {\n\t\t\t\t\t\tSystem.err.print(\" [\" + pair.getValue2() + \"]\");\n\t\t\t\t\t}\n\t\t\t\t\tSystem.err.print(System.lineSeparator());\n\t\t\t\t}\n\t\t\t\tSystem.err.print(\"StackTrace end\");\n\t\t\t\tSystem.err.print(System.lineSeparator());\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static boolean compare(StackTraceElement called, StackTraceElement infoProvider) {\n\t\treturn called.getClassName().equals(infoProvider.getClassName()) && called.getMethodName().equals(infoProvider.getMethodName()) && called.getFileName().equals(infoProvider.getFileName()) && called.getLineNumber() >= infoProvider.getLineNumber();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/StaticResolve.java",
    "content": "package logisticspipes.utils;\n\n/**\n * Annotation for stuff that needs to be statically registered\n */\npublic @interface StaticResolve {}\n"
  },
  {
    "path": "common/logisticspipes/utils/StaticResolverUtil.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraftforge.fml.common.discovery.ASMDataTable;\n\nimport logisticspipes.LogisticsPipes;\n\npublic class StaticResolverUtil {\n\n\tprivate static Set<ASMDataTable.ASMData> data = new HashSet<>();\n\tprivate static Map<Class<?>, Set<Class<?>>> classes = new HashMap<>();\n\n\tpublic static void useASMDataTable(@Nullable ASMDataTable table) {\n\t\tdata.clear();\n\t\tclasses.clear();\n\t\tif (table == null) return;\n\t\tdata.addAll(table.getAll(StaticResolve.class.getCanonicalName()));\n\t}\n\n\t@Nonnull\n\tpublic static <T> Set<Class<? extends T>> findClassesByType(@Nonnull Class<T> cls) {\n\t\tif (data.isEmpty()) return Collections.emptySet();\n\n\t\tSet<Class<?>> classes = StaticResolverUtil.classes.computeIfAbsent(cls, c ->\n\t\t\t\tdata.parallelStream()\n\t\t\t\t\t\t.map(d -> loadClass(d.getClassName()))\n\t\t\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t\t\t.filter(cls::isAssignableFrom)\n\t\t\t\t\t\t.collect(Collectors.toSet())\n\t\t);\n\t\treturn (Set<Class<? extends T>>) (Set<?>) classes;\n\t}\n\n\t@Nullable\n\tprivate static Class<?> loadClass(@Nonnull String classPathSpec) {\n\t\ttry {\n\t\t\treturn LogisticsPipes.class.getClassLoader().loadClass(classPathSpec);\n\t\t} catch (ClassNotFoundException e) {\n\t\t\te.printStackTrace();\n\t\t\treturn null;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/StreamHelper.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Collector;\n\n/**\n * Created by David on 12.05.2017.\n * All rights reserved.\n */\npublic class StreamHelper {\n\n\tpublic static <T> Collector<T, List<T>, T> singletonCollector() {\n\t\treturn Collector.of(\n\t\t\t\tArrayList::new,\n\t\t\t\tList::add,\n\t\t\t\t(left, right) -> {\n\t\t\t\t\tleft.addAll(right);\n\t\t\t\t\treturn left;\n\t\t\t\t},\n\t\t\t\tlist -> {\n\t\t\t\t\tif (list.size() != 1) {\n\t\t\t\t\t\tthrow new IllegalStateException();\n\t\t\t\t\t}\n\t\t\t\t\treturn list.get(0);\n\t\t\t\t}\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/SyncList.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.ListIterator;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\n\nimport logisticspipes.network.abstractpackets.ListSyncPacket;\nimport logisticspipes.proxy.MainProxy;\n\npublic class SyncList<E> implements List<E> {\n\n\tprivate final List<E> list;\n\tprivate ListSyncPacket<E> packetType;\n\tprivate PlayerCollectionList watcherList = null;\n\tprivate boolean dirty = false;\n\tprivate int dim, x, z;\n\n\tpublic SyncList() {\n\t\tthis(null, new ArrayList<>());\n\t}\n\n\tpublic SyncList(ListSyncPacket<E> type) {\n\t\tthis(type, new ArrayList<>());\n\t}\n\n\tpublic SyncList(ListSyncPacket<E> type, List<E> list) {\n\t\tthis.packetType = type;\n\t\tthis.list = list;\n\t}\n\n\t/**\n\t * Can be used to trigger update manualy\n\t */\n\tpublic void markDirty() {\n\t\tif (packetType == null) {\n\t\t\treturn;\n\t\t}\n\t\tdirty = true;\n\t}\n\n\tpublic void sendUpdateToWaters() {\n\t\tif (packetType == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (dirty) {\n\t\t\tdirty = false;\n\t\t\tif (watcherList != null) {\n\t\t\t\tMainProxy.sendToPlayerList(packetType.template().setList(list), watcherList);\n\t\t\t} else {\n\t\t\t\tMainProxy.sendPacketToAllWatchingChunk(x, z, dim, packetType.template().setList(list));\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void setPacketType(ListSyncPacket<E> type, int dim, int x, int z) {\n\t\tpacketType = type;\n\t\tthis.dim = dim;\n\t\tthis.x = x;\n\t\tthis.z = z;\n\t\tif (watcherList != null) {\n\t\t\tMainProxy.sendToPlayerList(packetType.template().setList(list), watcherList);\n\t\t} else {\n\t\t\tMainProxy.sendPacketToAllWatchingChunk(x, z, dim, packetType.template().setList(list));\n\t\t}\n\t}\n\n\tpublic void addWatcher(EntityPlayer player) {\n\t\tif (watcherList == null) {\n\t\t\twatcherList = new PlayerCollectionList();\n\t\t}\n\t\tif (packetType != null) {\n\t\t\tMainProxy.sendPacketToPlayer(packetType.template().setList(list), player);\n\t\t}\n\t\twatcherList.add(player);\n\t}\n\n\tpublic boolean removeWatcher(EntityPlayer player) {\n\t\tif (watcherList == null) {\n\t\t\twatcherList = new PlayerCollectionList();\n\t\t}\n\t\treturn watcherList.remove(player);\n\t}\n\n\t@Override\n\tpublic int size() {\n\t\treturn list.size();\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn list.isEmpty();\n\t}\n\n\t@Override\n\tpublic boolean contains(Object paramObject) {\n\t\treturn list.contains(paramObject);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterator<E> iterator() {\n\t\treturn new SyncIter(list.iterator());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Object[] toArray() {\n\t\treturn list.toArray();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <T> T[] toArray(@Nonnull T[] paramArrayOfT) {\n\t\treturn list.toArray(paramArrayOfT);\n\t}\n\n\t@Override\n\tpublic boolean add(E paramE) {\n\t\tboolean flag = list.add(paramE);\n\t\tmarkDirty();\n\t\treturn flag;\n\t}\n\n\t@Override\n\tpublic boolean remove(Object paramObject) {\n\t\tboolean flag = list.remove(paramObject);\n\t\tmarkDirty();\n\t\treturn flag;\n\t}\n\n\t@Override\n\tpublic boolean containsAll(@Nonnull Collection<?> paramCollection) {\n\t\treturn list.containsAll(paramCollection);\n\t}\n\n\t@Override\n\tpublic boolean addAll(@Nonnull Collection<? extends E> paramCollection) {\n\t\tboolean flag = list.addAll(paramCollection);\n\t\tmarkDirty();\n\t\treturn flag;\n\t}\n\n\t@Override\n\tpublic boolean addAll(int paramInt, @Nonnull Collection<? extends E> paramCollection) {\n\t\tboolean flag = list.addAll(paramInt, paramCollection);\n\t\tmarkDirty();\n\t\treturn flag;\n\t}\n\n\t@Override\n\tpublic boolean removeAll(@Nonnull Collection<?> paramCollection) {\n\t\tboolean flag = list.removeAll(paramCollection);\n\t\tmarkDirty();\n\t\treturn flag;\n\t}\n\n\t@Override\n\tpublic boolean retainAll(@Nonnull Collection<?> paramCollection) {\n\t\tboolean flag = list.retainAll(paramCollection);\n\t\tmarkDirty();\n\t\treturn flag;\n\t}\n\n\t@Override\n\tpublic void clear() {\n\t\tlist.clear();\n\t\tmarkDirty();\n\t}\n\n\t@Override\n\tpublic E get(int paramInt) {\n\t\treturn list.get(paramInt);\n\t}\n\n\t@Override\n\tpublic E set(int paramInt, E paramE) {\n\t\tE object = list.set(paramInt, paramE);\n\t\tmarkDirty();\n\t\treturn object;\n\t}\n\n\t@Override\n\tpublic void add(int paramInt, E paramE) {\n\t\tlist.add(paramInt, paramE);\n\t\tmarkDirty();\n\t}\n\n\t@Override\n\tpublic E remove(int paramInt) {\n\t\tE object = list.remove(paramInt);\n\t\tmarkDirty();\n\t\treturn object;\n\t}\n\n\t@Override\n\tpublic int indexOf(Object paramObject) {\n\t\treturn list.indexOf(paramObject);\n\t}\n\n\t@Override\n\tpublic int lastIndexOf(Object paramObject) {\n\t\tint index = list.lastIndexOf(paramObject);\n\t\tmarkDirty();\n\t\treturn index;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ListIterator<E> listIterator() {\n\t\treturn new SyncListIter(list.listIterator());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ListIterator<E> listIterator(int paramInt) {\n\t\treturn new SyncListIter(list.listIterator(paramInt));\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic List<E> subList(int paramInt1, int paramInt2) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\tprivate class SyncIter implements Iterator<E> {\n\n\t\tprivate final Iterator<E> iter;\n\n\t\tprotected SyncIter(Iterator<E> iter) {\n\t\t\tthis.iter = iter;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean hasNext() {\n\t\t\treturn iter.hasNext();\n\t\t}\n\n\t\t@Override\n\t\tpublic E next() {\n\t\t\treturn iter.next();\n\t\t}\n\n\t\t@Override\n\t\tpublic void remove() {\n\t\t\titer.remove();\n\t\t\tmarkDirty();\n\t\t}\n\t}\n\n\tprivate class SyncListIter extends SyncIter implements ListIterator<E> {\n\n\t\tprivate final ListIterator<E> iter;\n\n\t\tprotected SyncListIter(ListIterator<E> iter) {\n\t\t\tsuper(iter);\n\t\t\tthis.iter = iter;\n\t\t}\n\n\t\t@Override\n\t\tpublic void add(E paramE) {\n\t\t\titer.add(paramE);\n\t\t\tmarkDirty();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean hasPrevious() {\n\t\t\treturn iter.hasPrevious();\n\t\t}\n\n\t\t@Override\n\t\tpublic int nextIndex() {\n\t\t\treturn iter.nextIndex();\n\t\t}\n\n\t\t@Override\n\t\tpublic E previous() {\n\t\t\treturn iter.previous();\n\t\t}\n\n\t\t@Override\n\t\tpublic int previousIndex() {\n\t\t\treturn iter.previousIndex();\n\t\t}\n\n\t\t@Override\n\t\tpublic void set(E paramE) {\n\t\t\titer.set(paramE);\n\t\t\tmarkDirty();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/TankUtil.java",
    "content": "package logisticspipes.utils;\n\nimport java.util.Arrays;\nimport java.util.stream.Stream;\n\nimport net.minecraftforge.fluids.FluidStack;\nimport net.minecraftforge.fluids.capability.IFluidHandler;\nimport net.minecraftforge.fluids.capability.IFluidTankProperties;\n\nimport logisticspipes.interfaces.ITankUtil;\n\npublic class TankUtil implements ITankUtil {\n\n\tprivate final IFluidHandler fluidhandler;\n\n\tpublic TankUtil(IFluidHandler fluidhandler) {\n\t\tthis.fluidhandler = fluidhandler;\n\t}\n\n\t@Override\n\tpublic boolean containsTanks() {\n\t\tIFluidTankProperties[] tanks = fluidhandler.getTankProperties();\n\t\treturn tanks != null && tanks.length > 0;\n\t}\n\n\t@Override\n\tpublic int fill(FluidIdentifierStack stack, boolean doFill) {\n\t\treturn fluidhandler.fill(stack.makeFluidStack(), doFill);\n\t}\n\n\t@Override\n\tpublic FluidIdentifierStack drain(FluidIdentifierStack stack, boolean doDrain) {\n\t\treturn FluidIdentifierStack.getFromStack(fluidhandler.drain(stack.makeFluidStack(), doDrain));\n\t}\n\n\t@Override\n\tpublic FluidIdentifierStack drain(int amount, boolean doDrain) {\n\t\treturn FluidIdentifierStack.getFromStack(fluidhandler.drain(amount, doDrain));\n\t}\n\n\t@Override\n\tpublic Stream<IFluidTankProperties> tanks() {\n\t\tfinal IFluidTankProperties[] tanks = fluidhandler.getTankProperties();\n\t\tif (tanks == null) return Stream.empty();\n\t\treturn Arrays.stream(tanks).filter(tank -> tank.getContents() != null);\n\t}\n\n\t@Override\n\tpublic boolean canDrain(FluidIdentifier fluid) {\n\t\tfinal FluidStack fluidStack = fluid.makeFluidStack(1);\n\t\treturn tanks().anyMatch(tank -> tank.canDrainFluidType(fluidStack));\n\t}\n\n\tpublic int getFreeSpaceInsideTank(FluidIdentifier type) {\n\t\tint free = 0;\n\t\tIFluidTankProperties[] tanks = fluidhandler.getTankProperties();\n\t\tif (tanks != null && tanks.length > 0) {\n\t\t\tfor (IFluidTankProperties tank : tanks) {\n\t\t\t\tFluidStack content = tank.getContents();\n\t\t\t\tif (content == null || FluidIdentifier.get(content) == type) {\n\t\t\t\t\tfree += getFreeSpaceInsideTank(tank);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn free;\n\t}\n\n\tprivate int getFreeSpaceInsideTank(IFluidTankProperties tanks) {\n\t\tif (tanks == null) {\n\t\t\treturn 0;\n\t\t}\n\t\tFluidStack liquid = tanks.getContents();\n\t\tif (liquid == null || liquid.getFluid() == null) {\n\t\t\treturn tanks.getCapacity();\n\t\t}\n\t\treturn tanks.getCapacity() - liquid.amount;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/TileBuffer.java",
    "content": "package logisticspipes.utils;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\npublic final class TileBuffer {\n\n\tprivate Block block = null;\n\tprivate TileEntity tile;\n\n\tprivate final SafeTimeTracker tracker = new SafeTimeTracker(20, 5);\n\tprivate final World world;\n\tprivate final int x, y, z;\n\tprivate final boolean loadUnloaded;\n\n\tpublic TileBuffer(World world, int x, int y, int z, boolean loadUnloaded) {\n\t\tthis.world = world;\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t\tthis.loadUnloaded = loadUnloaded;\n\n\t\trefresh();\n\t}\n\n\tpublic void refresh() {\n\t\tBlockPos pos = new BlockPos(x, y, z);\n\t\tIBlockState blockState = world.getBlockState(pos);\n\t\tif (tile instanceof LogisticsTileGenericPipe && ((LogisticsTileGenericPipe) tile).pipe != null && ((LogisticsTileGenericPipe) tile).pipe.preventRemove()) {\n\t\t\tif (blockState.getBlock().isAir(blockState, world, pos)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\ttile = null;\n\t\tblock = null;\n\n\t\tif (!loadUnloaded) {\n\t\t\treturn;\n\t\t}\n\n\t\tblock = blockState.getBlock();\n\n\t\tif (block.hasTileEntity(blockState)) {\n\t\t\ttile = world.getTileEntity(pos);\n\t\t}\n\t}\n\n\tpublic void set(Block block, TileEntity tile) {\n\t\tthis.block = block;\n\t\tthis.tile = tile;\n\t\ttracker.markTime(world);\n\t}\n\n\tpublic Block getBlock() {\n\t\tif (tile != null && !tile.isInvalid()) {\n\t\t\treturn block;\n\t\t}\n\n\t\tif (tracker.markTimeIfDelay(world)) {\n\t\t\trefresh();\n\n\t\t\tif (tile != null && !tile.isInvalid()) {\n\t\t\t\treturn block;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic TileEntity getTile() {\n\t\tif (tile != null && !tile.isInvalid()) {\n\t\t\treturn tile;\n\t\t}\n\n\t\tif (tracker.markTimeIfDelay(world)) {\n\t\t\trefresh();\n\n\t\t\tif (tile != null && !tile.isInvalid()) {\n\t\t\t\treturn tile;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic static TileBuffer[] makeBuffer(World world, BlockPos pos, boolean loadUnloaded) {\n\t\tTileBuffer[] buffer = new TileBuffer[6];\n\n\t\tfor (int i = 0; i < 6; i++) {\n\t\t\tEnumFacing d = EnumFacing.byIndex(i);\n\t\t\tbuffer[i] = new TileBuffer(world, pos.getX() + d.getXOffset(), pos.getY() + d.getYOffset(), pos.getZ() + d.getZOffset(), loadUnloaded);\n\t\t}\n\n\t\treturn buffer;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/ColorSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\n\npublic class ColorSlot extends Slot {\n\n\tpublic ColorSlot(IInventory par1iInventory, int par2, int par3, int par4) {\n\t\tsuper(par1iInventory, par2, par3, par4);\n\t}\n\n\tpublic ColorSlot(Slot slot) {\n\t\tsuper(slot.inventory, slot.getSlotIndex(), slot.xPos, slot.yPos);\n\t}\n\n\t@Override\n\tpublic boolean canTakeStack(EntityPlayer par1EntityPlayer) {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/DummyContainer.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.gui;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.entity.player.EntityPlayerMP;\nimport net.minecraft.entity.player.InventoryPlayer;\nimport net.minecraft.inventory.ClickType;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.inventory.IContainerListener;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.interfaces.IFuzzySlot;\nimport logisticspipes.interfaces.IGuiOpenControler;\nimport logisticspipes.interfaces.ISlotCheck;\nimport logisticspipes.interfaces.ISlotClick;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.logisticspipes.ItemModuleInformationManager;\nimport logisticspipes.modules.ChassisModule;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.FuzzySlotSettingsPacket;\nimport logisticspipes.pipes.PipeLogisticsChassis;\nimport logisticspipes.pipes.upgrades.UpgradeManager;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.MinecraftColor;\nimport logisticspipes.utils.ReflectionHelper;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport network.rs485.logisticspipes.property.IBitSet;\n\npublic class DummyContainer extends Container {\n\n\t@SideOnly(Side.CLIENT)\n\tpublic LogisticsBaseGuiScreen guiHolderForJEI; // This is not set for every GUI. Only for the one needed by JEI.\n\n\tpublic List<BitSet> slotsFuzzyFlags = new ArrayList<>();\n\tprotected IInventory _playerInventory;\n\tprotected IInventory _dummyInventory;\n\tprotected IGuiOpenControler[] _controler;\n\tboolean wasDummyLookup;\n\tboolean overrideMCAntiSend;\n\tprivate List<Slot> transferTop = new ArrayList<>();\n\tprivate List<Slot> transferBottom = new ArrayList<>();\n\tprivate long lastClicked;\n\tprivate long lastDragnDropLockup;\n\n\tpublic DummyContainer(IInventory playerInventory, IInventory dummyInventory) {\n\t\t_playerInventory = playerInventory;\n\t\t_dummyInventory = dummyInventory;\n\t\t_controler = null;\n\t}\n\n\tpublic DummyContainer(EntityPlayer player, IInventory dummyInventory, IGuiOpenControler... controler) {\n\t\t_playerInventory = player.inventory;\n\t\t_dummyInventory = dummyInventory;\n\t\t_controler = controler;\n\t\tif (MainProxy.isServer(player.world)) {\n\t\t\tfor (IGuiOpenControler element : _controler) {\n\t\t\t\telement.guiOpenedByPlayer(player);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean canInteractWith(@Nonnull EntityPlayer entityplayer) {\n\t\treturn true;\n\t}\n\n\t/***\n\t * Adds all slots for the player inventory and hotbar\n\t */\n\tpublic void addNormalSlotsForPlayerInventory(int xOffset, int yOffset) {\n\t\tif (_playerInventory == null) {\n\t\t\treturn;\n\t\t}\n\t\t// Player \"backpack\"\n\t\tfor (int row = 0; row < 3; row++) {\n\t\t\tfor (int column = 0; column < 9; column++) {\n\t\t\t\tSlot slot = new Slot(_playerInventory, column + row * 9 + 9, xOffset + column * 18, yOffset + row * 18);\n\t\t\t\taddSlotToContainer(slot);\n\t\t\t\ttransferBottom.add(slot);\n\t\t\t}\n\t\t}\n\n\t\t// Player \"hotbar\"\n\t\tfor (int i1 = 0; i1 < 9; i1++) {\n\t\t\tSlot slot = new Slot(_playerInventory, i1, xOffset + i1 * 18, yOffset + 58);\n\t\t\taddSlotToContainer(slot);\n\t\t\ttransferBottom.add(slot);\n\t\t}\n\t}\n\n\t/**\n\t * Add a dummy slot that will not consume players items\n\t *\n\t * @param slotId\n\t *            The slot number in the dummy IInventory this slot should map\n\t * @param xCoord\n\t *            xCoord of TopLeft corner of where the slot should be rendered\n\t * @param yCoord\n\t *            yCoord of TopLeft corner of where the slot should be rendered\n\t */\n\tpublic Slot addDummySlot(int slotId, int xCoord, int yCoord) {\n\t\treturn addSlotToContainer(new DummySlot(_dummyInventory, slotId, xCoord, yCoord));\n\t}\n\n\tpublic Slot addDummySlot(int slotId, IInventory dummy, int xCoord, int yCoord) {\n\t\treturn addSlotToContainer(new DummySlot(dummy, slotId, xCoord, yCoord));\n\t}\n\n\tpublic void addNormalSlot(int slotId, IInventory inventory, int xCoord, int yCoord) {\n\t\ttransferTop.add(addSlotToContainer(new Slot(inventory, slotId, xCoord, yCoord)));\n\t}\n\n\tpublic Slot addRestrictedSlot(int slotId, IInventory inventory, int xCoord, int yCoord, Class<? extends Item> itemClass) {\n\t\treturn addSlotToContainer(new RestrictedSlot(inventory, slotId, xCoord, yCoord, itemClass));\n\t}\n\n\tpublic Slot addRestrictedSlot(int slotId, IInventory inventory, int xCoord, int yCoord, Item item) {\n\t\treturn addSlotToContainer(new RestrictedSlot(inventory, slotId, xCoord, yCoord, item));\n\t}\n\n\tpublic Slot addStaticRestrictedSlot(int slotId, IInventory inventory, int xCoord, int yCoord, Item item, int stackLimit) {\n\t\treturn addSlotToContainer(new StaticRestrictedSlot(inventory, slotId, xCoord, yCoord, item, stackLimit));\n\t}\n\n\tpublic Slot addRestrictedSlot(int slotId, IInventory inventory, int xCoord, int yCoord, ISlotCheck slotCheck) {\n\t\treturn addSlotToContainer(new RestrictedSlot(inventory, slotId, xCoord, yCoord, slotCheck));\n\t}\n\n\tpublic Slot addStaticRestrictedSlot(int slotId, IInventory inventory, int xCoord, int yCoord, ISlotCheck slotCheck, int stackLimit) {\n\t\treturn addSlotToContainer(new StaticRestrictedSlot(inventory, slotId, xCoord, yCoord, slotCheck, stackLimit));\n\t}\n\n\tpublic void addModuleSlot(int slotId, IInventory inventory, int xCoord, int yCoord, PipeLogisticsChassis pipe) {\n\t\ttransferTop.add(addSlotToContainer(new ModuleSlot(inventory, slotId, xCoord, yCoord, pipe)));\n\t}\n\n\tpublic Slot addFluidSlot(int slotId, int xCoord, int yCoord) {\n\t\treturn addSlotToContainer(new FluidSlot(_dummyInventory, slotId, xCoord, yCoord));\n\t}\n\n\tpublic Slot addFluidSlot(int slotId, IInventory inventory, int xCoord, int yCoord) {\n\t\treturn addSlotToContainer(new FluidSlot(inventory, slotId, xCoord, yCoord));\n\t}\n\n\tpublic Slot addColorSlot(int slotId, IInventory inventory, int xCoord, int yCoord) {\n\t\treturn addSlotToContainer(new ColorSlot(inventory, slotId, xCoord, yCoord));\n\t}\n\n\tpublic Slot addUnmodifiableSlot(int slotId, IInventory inventory, int xCoord, int yCoord) {\n\t\treturn addSlotToContainer(new UnmodifiableSlot(inventory, slotId, xCoord, yCoord));\n\t}\n\n\tpublic Slot addCallableSlotHandler(int slotId, IInventory inventory, int xCoord, int yCoord, ISlotClick handler) {\n\t\treturn addSlotToContainer(new HandelableSlot(inventory, slotId, xCoord, yCoord, handler));\n\t}\n\n\tpublic Slot addFuzzyDummySlot(int slotId, int xCoord, int yCoord, IBitSet fuzzyFlags) {\n\t\treturn addSlotToContainer(new FuzzyDummySlot(_dummyInventory, slotId, xCoord, yCoord, fuzzyFlags));\n\t}\n\n\tpublic Slot addFuzzyUnmodifiableSlot(int slotId, IInventory inventory, int xCoord, int yCoord, IBitSet fuzzyFlags) {\n\t\treturn addSlotToContainer(new FuzzyUnmodifiableSlot(inventory, slotId, xCoord, yCoord, fuzzyFlags));\n\t}\n\n\tpublic Slot addUpgradeSlot(int slotId, ISlotUpgradeManager manager, int upgradeSlotId, int xCoord, int yCoord, ISlotCheck slotCheck) {\n\t\tSlot slot = addSlotToContainer(new UpgradeSlot(manager, upgradeSlotId, slotId, xCoord, yCoord, slotCheck));\n\t\ttransferTop.add(slot);\n\t\treturn slot;\n\t}\n\n\tpublic Slot addSneakyUpgradeSlot(int slotId, UpgradeManager manager, int upgradeSlotId, int xCoord, int yCoord, ISlotCheck slotCheck) {\n\t\tSlot slot = addSlotToContainer(new SneakyUpgradeSlot(manager, upgradeSlotId, slotId, xCoord, yCoord, slotCheck));\n\t\ttransferTop.add(slot);\n\t\treturn slot;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack transferStackInSlot(@Nonnull EntityPlayer player, int i) {\n\t\tif (transferTop.isEmpty() || transferBottom.isEmpty()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tSlot slot = inventorySlots.get(i);\n\t\tif (slot == null || slot instanceof DummySlot || slot instanceof UnmodifiableSlot || slot instanceof FluidSlot || slot instanceof ColorSlot || slot instanceof HandelableSlot || !slot.getHasStack()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tif (transferTop.contains(slot)) {\n\t\t\thandleShiftClickLists(slot, transferBottom, true, player);\n\t\t\thandleShiftClickLists(slot, transferBottom, false, player);\n\t\t} else if (transferBottom.contains(slot)) {\n\t\t\thandleShiftClickLists(slot, transferTop, true, player);\n\t\t\thandleShiftClickLists(slot, transferTop, false, player);\n\t\t}\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\tprivate void handleShiftClickLists(Slot from, List<Slot> toList, boolean ignoreEmpty, EntityPlayer player) {\n\t\tif (!from.getHasStack()) {\n\t\t\treturn;\n\t\t}\n\t\tfor (Slot to : toList) {\n\t\t\tif (handleShiftClickForSlots(from, to, ignoreEmpty, player)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate boolean handleShiftClickForSlots(Slot from, Slot to, boolean ignoreEmpty, EntityPlayer player) {\n\t\tif (!from.getHasStack()) {\n\t\t\treturn true;\n\t\t}\n\t\tItemStack out = from.getStack();\n\t\tif (!to.getHasStack() && !ignoreEmpty && to.isItemValid(out)) {\n\t\t\tboolean remove = true;\n\t\t\tif (out.getCount() > to.getSlotStackLimit()) {\n\t\t\t\tout = from.decrStackSize(to.getSlotStackLimit());\n\t\t\t\tremove = false;\n\t\t\t}\n\t\t\tto.putStack(from.onTake(player, out));\n\t\t\tif (remove) {\n\t\t\t\tfrom.putStack(ItemStack.EMPTY);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (from instanceof ModuleSlot || to instanceof ModuleSlot) {\n\t\t\treturn false;\n\t\t}\n\t\tout = from.onTake(player, out);\n\t\tif (to.getHasStack() && to.getStack().isItemEqual(out) && ItemStack.areItemStackTagsEqual(to.getStack(), from.getStack())) {\n\t\t\tint free = Math.min(to.getSlotStackLimit(), to.getStack().getMaxStackSize()) - to.getStack().getCount();\n\t\t\tif (free > 0) {\n\t\t\t\tItemStack toInsert = from.decrStackSize(free);\n\t\t\t\ttoInsert = from.onTake(player, toInsert);\n\t\t\t\tItemStack toStack = to.getStack();\n\t\t\t\tif (!toInsert.isEmpty() && !toStack.isEmpty()) {\n\t\t\t\t\ttoStack.grow(toInsert.getCount());\n\t\t\t\t\tto.putStack(toStack);\n\t\t\t\t\treturn !from.getHasStack();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack superSlotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player) {\n\t\tItemStack itemstack = ItemStack.EMPTY;\n\t\tInventoryPlayer inventoryplayer = player.inventory;\n\n\t\tif (clickTypeIn == ClickType.QUICK_CRAFT) {\n\t\t\tint j1 = this.dragEvent;\n\t\t\tthis.dragEvent = getDragEvent(dragType);\n\n\t\t\tif ((j1 != 1 || this.dragEvent != 2) && j1 != this.dragEvent) {\n\t\t\t\tthis.resetDrag();\n\t\t\t} else if (inventoryplayer.getItemStack().isEmpty()) {\n\t\t\t\tthis.resetDrag();\n\t\t\t} else if (this.dragEvent == 0) {\n\t\t\t\tthis.dragMode = extractDragMode(dragType);\n\n\t\t\t\tif (isValidDragMode(this.dragMode, player)) {\n\t\t\t\t\tthis.dragEvent = 1;\n\t\t\t\t\tthis.dragSlots.clear();\n\t\t\t\t} else {\n\t\t\t\t\tthis.resetDrag();\n\t\t\t\t}\n\t\t\t} else if (this.dragEvent == 1) {\n\t\t\t\tSlot slot7 = this.inventorySlots.get(slotId);\n\t\t\t\tItemStack itemstack12 = inventoryplayer.getItemStack();\n\n\t\t\t\tif (slot7 != null && canAddItemToSlot(slot7, itemstack12, true) && slot7.isItemValid(itemstack12) && (this.dragMode == 2\n\t\t\t\t\t\t|| itemstack12.getCount() > this.dragSlots.size()) && this.canDragIntoSlot(slot7)) {\n\t\t\t\t\tthis.dragSlots.add(slot7);\n\t\t\t\t}\n\t\t\t} else if (this.dragEvent == 2) {\n\t\t\t\tif (!this.dragSlots.isEmpty()) {\n\t\t\t\t\tItemStack itemstack9 = inventoryplayer.getItemStack().copy();\n\t\t\t\t\tint k1 = inventoryplayer.getItemStack().getCount();\n\n\t\t\t\t\tfor (Slot slot8 : this.dragSlots) {\n\t\t\t\t\t\tItemStack itemstack13 = inventoryplayer.getItemStack();\n\n\t\t\t\t\t\tif (slot8 != null && canAddItemToSlot(slot8, itemstack13, true) && slot8.isItemValid(itemstack13) && (this.dragMode == 2\n\t\t\t\t\t\t\t\t|| itemstack13.getCount() >= this.dragSlots.size()) && this.canDragIntoSlot(slot8)) {\n\t\t\t\t\t\t\tItemStack itemstack14 = itemstack9.copy();\n\t\t\t\t\t\t\tint j3 = slot8.getHasStack() ? slot8.getStack().getCount() : 0;\n\t\t\t\t\t\t\tcomputeStackSize(this.dragSlots, this.dragMode, itemstack14, j3);\n\t\t\t\t\t\t\tint k3 = Math.min(itemstack14.getMaxStackSize(), slot8.getItemStackLimit(itemstack14));\n\n\t\t\t\t\t\t\tif (itemstack14.getCount() > k3) {\n\t\t\t\t\t\t\t\titemstack14.setCount(k3);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tk1 -= itemstack14.getCount() - j3;\n\t\t\t\t\t\t\tslot8.putStack(itemstack14);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\titemstack9.setCount(k1);\n\t\t\t\t\tinventoryplayer.setItemStack(itemstack9);\n\t\t\t\t}\n\n\t\t\t\tthis.resetDrag();\n\t\t\t} else {\n\t\t\t\tthis.resetDrag();\n\t\t\t}\n\t\t} else if (this.dragEvent != 0) {\n\t\t\tthis.resetDrag();\n\t\t} else if ((clickTypeIn == ClickType.PICKUP || clickTypeIn == ClickType.QUICK_MOVE) && (dragType == 0 || dragType == 1)) {\n\t\t\tif (slotId == -999) {\n\t\t\t\tif (!inventoryplayer.getItemStack().isEmpty()) {\n\t\t\t\t\tif (dragType == 0) {\n\t\t\t\t\t\tplayer.dropItem(inventoryplayer.getItemStack(), true);\n\t\t\t\t\t\tinventoryplayer.setItemStack(ItemStack.EMPTY);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (dragType == 1) {\n\t\t\t\t\t\tplayer.dropItem(inventoryplayer.getItemStack().splitStack(1), true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (clickTypeIn == ClickType.QUICK_MOVE) {\n\t\t\t\tif (slotId < 0) {\n\t\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t\t}\n\n\t\t\t\tSlot slot5 = this.inventorySlots.get(slotId);\n\n\t\t\t\tif (slot5 == null || !slot5.canTakeStack(player)) {\n\t\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t\t}\n\n\t\t\t\tfor (ItemStack itemstack7 = this.transferStackInSlot(player, slotId);\n\t\t\t\t\t !itemstack7.isEmpty() && ItemStack.areItemsEqual(slot5.getStack(), itemstack7); itemstack7 = this.transferStackInSlot(player, slotId)) {\n\t\t\t\t\titemstack = itemstack7.copy();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (slotId < 0) {\n\t\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t\t}\n\n\t\t\t\tSlot slot6 = this.inventorySlots.get(slotId);\n\n\t\t\t\tif (slot6 != null) {\n\t\t\t\t\tItemStack itemstack8 = slot6.getStack();\n\t\t\t\t\tItemStack itemstack11 = inventoryplayer.getItemStack();\n\n\t\t\t\t\tif (!itemstack8.isEmpty()) {\n\t\t\t\t\t\titemstack = itemstack8.copy();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (itemstack8.isEmpty()) {\n\t\t\t\t\t\tif (!itemstack11.isEmpty() && slot6.isItemValid(itemstack11)) {\n\t\t\t\t\t\t\tint i3 = dragType == 0 ? itemstack11.getCount() : 1;\n\n\t\t\t\t\t\t\tif (i3 > slot6.getItemStackLimit(itemstack11)) {\n\t\t\t\t\t\t\t\ti3 = slot6.getItemStackLimit(itemstack11);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tslot6.putStack(itemstack11.splitStack(i3));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (slot6.canTakeStack(player)) {\n\t\t\t\t\t\tif (itemstack11.isEmpty()) {\n\t\t\t\t\t\t\tif (itemstack8.isEmpty()) {\n\t\t\t\t\t\t\t\tslot6.putStack(ItemStack.EMPTY);\n\t\t\t\t\t\t\t\tinventoryplayer.setItemStack(ItemStack.EMPTY);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tint l2 = dragType == 0 ? itemstack8.getCount() : (itemstack8.getCount() + 1) / 2;\n\t\t\t\t\t\t\t\tinventoryplayer.setItemStack(slot6.decrStackSize(l2));\n\n\t\t\t\t\t\t\t\tif (itemstack8.isEmpty()) {\n\t\t\t\t\t\t\t\t\tslot6.putStack(ItemStack.EMPTY);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tslot6.onTake(player, inventoryplayer.getItemStack());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (slot6.isItemValid(itemstack11)) {\n\t\t\t\t\t\t\tif (itemstack8.getItem() == itemstack11.getItem() && itemstack8.getMetadata() == itemstack11.getMetadata() && ItemStack\n\t\t\t\t\t\t\t\t\t.areItemStackTagsEqual(itemstack8, itemstack11)) {\n\t\t\t\t\t\t\t\tint k2 = dragType == 0 ? itemstack11.getCount() : 1;\n\n\t\t\t\t\t\t\t\tif (k2 > slot6.getItemStackLimit(itemstack11) - itemstack8.getCount()) {\n\t\t\t\t\t\t\t\t\tk2 = slot6.getItemStackLimit(itemstack11) - itemstack8.getCount();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (k2 > itemstack11.getMaxStackSize() - itemstack8.getCount()) {\n\t\t\t\t\t\t\t\t\tk2 = itemstack11.getMaxStackSize() - itemstack8.getCount();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\titemstack11.shrink(k2);\n\t\t\t\t\t\t\t\titemstack8.grow(k2);\n\n\t\t\t\t\t\t\t\tslot6.putStack(itemstack8); // XXX added reinserting of the modified itemStack (Fix ItemIdentifierInventory's disappearing items)\n\t\t\t\t\t\t\t} else if (itemstack11.getCount() <= slot6.getItemStackLimit(itemstack11)) {\n\t\t\t\t\t\t\t\thandleSwitch(slot6, itemstack8, itemstack11, player); // XXX added Slot switching handle method\n\t\t\t\t\t\t\t\tslot6.putStack(itemstack11);\n\t\t\t\t\t\t\t\tinventoryplayer.setItemStack(itemstack8);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (itemstack8.getItem() == itemstack11.getItem() && itemstack11.getMaxStackSize() > 1 && (!itemstack8.getHasSubtypes()\n\t\t\t\t\t\t\t\t|| itemstack8.getMetadata() == itemstack11.getMetadata()) && ItemStack.areItemStackTagsEqual(itemstack8, itemstack11)\n\t\t\t\t\t\t\t\t&& !itemstack8.isEmpty()) {\n\t\t\t\t\t\t\tint j2 = itemstack8.getCount();\n\n\t\t\t\t\t\t\tif (j2 + itemstack11.getCount() <= itemstack11.getMaxStackSize()) {\n\t\t\t\t\t\t\t\titemstack11.grow(j2);\n\t\t\t\t\t\t\t\titemstack8 = slot6.decrStackSize(j2);\n\n\t\t\t\t\t\t\t\tif (itemstack8.isEmpty()) {\n\t\t\t\t\t\t\t\t\tslot6.putStack(ItemStack.EMPTY);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tslot6.onTake(player, inventoryplayer.getItemStack());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tslot6.onSlotChanged();\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (clickTypeIn == ClickType.SWAP && dragType >= 0 && dragType < 9) {\n\t\t\tSlot slot4 = this.inventorySlots.get(slotId);\n\t\t\tItemStack itemstack6 = inventoryplayer.getStackInSlot(dragType);\n\t\t\tItemStack itemstack10 = slot4.getStack();\n\n\t\t\tif (!itemstack6.isEmpty() || !itemstack10.isEmpty()) {\n\t\t\t\tif (itemstack6.isEmpty()) {\n\t\t\t\t\tif (slot4.canTakeStack(player)) {\n\t\t\t\t\t\tinventoryplayer.setInventorySlotContents(dragType, itemstack10);\n\t\t\t\t\t\tReflectionHelper.invokePrivateMethod(Slot.class, slot4, \"onSwapCraft\", \"func_190900_b\", new Class[] { int.class }, new Object[] { itemstack10.getCount() });\n\t\t\t\t\t\tslot4.putStack(ItemStack.EMPTY);\n\t\t\t\t\t\tslot4.onTake(player, itemstack10);\n\t\t\t\t\t}\n\t\t\t\t} else if (itemstack10.isEmpty()) {\n\t\t\t\t\tif (slot4.isItemValid(itemstack6)) {\n\t\t\t\t\t\tint l1 = slot4.getItemStackLimit(itemstack6);\n\n\t\t\t\t\t\tif (itemstack6.getCount() > l1) {\n\t\t\t\t\t\t\tslot4.putStack(itemstack6.splitStack(l1));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tslot4.putStack(itemstack6);\n\t\t\t\t\t\t\tinventoryplayer.setInventorySlotContents(dragType, ItemStack.EMPTY);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (slot4.canTakeStack(player) && slot4.isItemValid(itemstack6)) {\n\t\t\t\t\tint i2 = slot4.getItemStackLimit(itemstack6);\n\n\t\t\t\t\tif (itemstack6.getCount() > i2) {\n\t\t\t\t\t\tslot4.putStack(itemstack6.splitStack(i2));\n\t\t\t\t\t\tslot4.onTake(player, itemstack10);\n\n\t\t\t\t\t\tif (!inventoryplayer.addItemStackToInventory(itemstack10)) {\n\t\t\t\t\t\t\tplayer.dropItem(itemstack10, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tslot4.putStack(itemstack6);\n\t\t\t\t\t\tinventoryplayer.setInventorySlotContents(dragType, itemstack10);\n\t\t\t\t\t\tslot4.onTake(player, itemstack10);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (clickTypeIn == ClickType.CLONE && player.capabilities.isCreativeMode && inventoryplayer.getItemStack().isEmpty() && slotId >= 0) {\n\t\t\tSlot slot3 = this.inventorySlots.get(slotId);\n\n\t\t\tif (slot3 != null && slot3.getHasStack()) {\n\t\t\t\tItemStack itemstack5 = slot3.getStack().copy();\n\t\t\t\titemstack5.setCount(itemstack5.getMaxStackSize());\n\t\t\t\tinventoryplayer.setItemStack(itemstack5);\n\t\t\t}\n\t\t} else if (clickTypeIn == ClickType.THROW && inventoryplayer.getItemStack().isEmpty() && slotId >= 0) {\n\t\t\tSlot slot2 = this.inventorySlots.get(slotId);\n\n\t\t\tif (slot2 != null && slot2.getHasStack() && slot2.canTakeStack(player)) {\n\t\t\t\tItemStack itemstack4 = slot2.decrStackSize(dragType == 0 ? 1 : slot2.getStack().getCount());\n\t\t\t\tslot2.onTake(player, itemstack4);\n\t\t\t\tplayer.dropItem(itemstack4, true);\n\t\t\t}\n\t\t} else if (clickTypeIn == ClickType.PICKUP_ALL && slotId >= 0) {\n\t\t\tSlot slot = this.inventorySlots.get(slotId);\n\t\t\tItemStack itemstack1 = inventoryplayer.getItemStack();\n\n\t\t\tif (!itemstack1.isEmpty() && (slot == null || !slot.getHasStack() || !slot.canTakeStack(player))) {\n\t\t\t\tint i = dragType == 0 ? 0 : this.inventorySlots.size() - 1;\n\t\t\t\tint j = dragType == 0 ? 1 : -1;\n\n\t\t\t\tfor (int k = 0; k < 2; ++k) {\n\t\t\t\t\tfor (int l = i; l >= 0 && l < this.inventorySlots.size() && itemstack1.getCount() < itemstack1.getMaxStackSize(); l += j) {\n\t\t\t\t\t\tSlot slot1 = this.inventorySlots.get(l);\n\n\t\t\t\t\t\tif (slot1.getHasStack() && canAddItemToSlot(slot1, itemstack1, true) && slot1.canTakeStack(player) && this\n\t\t\t\t\t\t\t\t.canMergeSlot(itemstack1, slot1)) {\n\t\t\t\t\t\t\tItemStack itemstack2 = slot1.getStack();\n\n\t\t\t\t\t\t\tif (k != 0 || itemstack2.getCount() != itemstack2.getMaxStackSize()) {\n\t\t\t\t\t\t\t\tint i1 = Math.min(itemstack1.getMaxStackSize() - itemstack1.getCount(), itemstack2.getCount());\n\t\t\t\t\t\t\t\tItemStack itemstack3 = slot1.decrStackSize(i1);\n\t\t\t\t\t\t\t\titemstack1.grow(i1);\n\n\t\t\t\t\t\t\t\tif (itemstack3.isEmpty()) {\n\t\t\t\t\t\t\t\t\tslot1.putStack(ItemStack.EMPTY);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tslot1.onTake(player, itemstack3);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.detectAndSendChanges();\n\t\t}\n\n\t\treturn itemstack;\n\t}\n\n\tprivate void handleSwitch(Slot slot2, @Nonnull ItemStack out, @Nonnull ItemStack in, EntityPlayer player) {\n\t\tif (slot2 instanceof ModuleSlot) {\n\t\t\tChassisModule chassis = (ChassisModule) ((ModuleSlot) slot2).get_pipe().getLogisticsModule();\n\t\t\tint moduleIndex = ((ModuleSlot) slot2).get_moduleIndex();\n\t\t\tif (out.getItem() instanceof ItemModule) {\n\t\t\t\tif (chassis.hasModule(moduleIndex)) {\n\t\t\t\t\tItemModuleInformationManager.saveInformation(out, chassis.getModule(moduleIndex));\n\t\t\t\t\tchassis.removeModule(moduleIndex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clone/clear itemstacks for items\n\t */\n\t@Nonnull\n\t@Override\n\tpublic ItemStack slotClick(int slotId, int mouseButton, @Nonnull ClickType shiftMode, @Nonnull EntityPlayer player) {\n\t\tlastClicked = System.currentTimeMillis();\n\t\tif (slotId < 0) {\n\t\t\treturn superSlotClick(slotId, mouseButton, shiftMode, player);\n\t\t}\n\t\tSlot slot = inventorySlots.get(slotId);\n\t\t//debug dump\n\t\tif (LogisticsPipes.isDEBUG() && slot != null) {\n\t\t\tItemStack stack = slot.getStack();\n\t\t\tif (!stack.isEmpty()) {\n\t\t\t\tItemIdentifier.get(stack).debugDumpData(player.world.isRemote);\n\t\t\t}\n\t\t}\n\t\tif (slot == null) return ItemStack.EMPTY;\n\t\tif ((!(slot instanceof DummySlot) && !(slot instanceof UnmodifiableSlot) && !(slot instanceof FluidSlot) && !(slot instanceof ColorSlot) && !(slot instanceof HandelableSlot))) {\n\t\t\tItemStack stack1 = superSlotClick(slotId, mouseButton, shiftMode, player);\n\t\t\tItemStack stack2 = slot.getStack();\n\t\t\tif (!stack2.isEmpty() && stack2.getItem() instanceof ItemModule) {\n\t\t\t\tif (player instanceof EntityPlayerMP && MainProxy.isServer(player.world)) {\n\t\t\t\t\t((EntityPlayerMP) player).sendSlotContents(this, slotId, stack2);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn stack1;\n\t\t}\n\n\t\tInventoryPlayer inventoryplayer = player.inventory;\n\n\t\tItemStack currentlyEquippedStack = inventoryplayer.getItemStack();\n\n\t\t// we get a leftclick *and* a doubleclick message if there's a doubleclick with no item on the pointer, filter it out\n\t\tif (currentlyEquippedStack.isEmpty() && shiftMode == ClickType.PICKUP_ALL) {\n\t\t\treturn currentlyEquippedStack;\n\t\t}\n\n\t\tif (slot instanceof HandelableSlot) {\n\t\t\toverrideMCAntiSend = true;\n\t\t\tif (currentlyEquippedStack.isEmpty()) {\n\t\t\t\tinventoryplayer.setItemStack(((HandelableSlot) slot).getProvidedStack());\n\t\t\t\treturn ItemStack.EMPTY;\n\t\t\t}\n\t\t\treturn currentlyEquippedStack;\n\t\t}\n\n\t\tif (slot instanceof UnmodifiableSlot) {\n\t\t\treturn currentlyEquippedStack;\n\t\t}\n\n\t\thandleDummyClick(slot, slotId, currentlyEquippedStack, mouseButton, shiftMode, player);\n\t\treturn currentlyEquippedStack;\n\t}\n\n\tpublic void handleDummyClick(Slot slot, int slotId, @Nonnull ItemStack currentlyEquippedStack, int mouseButton, ClickType shiftMode, EntityPlayer entityplayer) {\n\t\tif (slot instanceof FluidSlot) {\n\t\t\tif (!currentlyEquippedStack.isEmpty()) {\n\t\t\t\tFluidIdentifier ident = FluidIdentifier.get(currentlyEquippedStack);\n\t\t\t\tif (ident != null) {\n\t\t\t\t\tif (mouseButton == 0) {\n\t\t\t\t\t\tslot.putStack(ident.getItemIdentifier().unsafeMakeNormalStack(1));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tslot.putStack(ItemStack.EMPTY);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tFluidIdentifier ident = null;\n\t\t\tif (!slot.getStack().isEmpty()) {\n\t\t\t\tident = FluidIdentifier.get(ItemIdentifier.get(slot.getStack()));\n\t\t\t}\n\t\t\tif (ident == null) {\n\t\t\t\tif (MainProxy.isClient(entityplayer.getEntityWorld())) {\n\t\t\t\t\tMainProxy.proxy.openFluidSelectGui(slotId);\n\t\t\t\t}\n\t\t\t}\n\t\t\tslot.putStack(ItemStack.EMPTY);\n\t\t\treturn;\n\t\t}\n\n\t\tif (slot instanceof ColorSlot) {\n\t\t\tMinecraftColor equipped = MinecraftColor.getColor(currentlyEquippedStack);\n\t\t\tMinecraftColor color = MinecraftColor.getColor(slot.getStack());\n\t\t\tif (MinecraftColor.BLANK.equals(equipped)) {\n\t\t\t\tif (mouseButton == 0) {\n\t\t\t\t\tcolor = color.getNext();\n\t\t\t\t} else if (mouseButton == 1) {\n\t\t\t\t\tcolor = color.getPrev();\n\t\t\t\t} else {\n\t\t\t\t\tcolor = MinecraftColor.BLANK;\n\t\t\t\t}\n\t\t\t\tslot.putStack(color.getItemStack());\n\t\t\t} else {\n\t\t\t\tif (mouseButton == 1) {\n\t\t\t\t\tslot.putStack(MinecraftColor.BLANK.getItemStack());\n\t\t\t\t} else {\n\t\t\t\t\tslot.putStack(equipped.getItemStack());\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (entityplayer instanceof EntityPlayerMP && MainProxy.isServer(entityplayer.world)) {\n\t\t\t\t((EntityPlayerMP) entityplayer).sendSlotContents(this, slotId, slot.getStack());\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (slot instanceof DummySlot) {\n\t\t\t((DummySlot) slot).setRedirectCall(true);\n\t\t}\n\n\t\tif (mouseButton >= 1000) {\n\t\t\tif (mouseButton <= 1001) {\n\t\t\t\tif (slot.getHasStack()) {\n\t\t\t\t\tItemStack stack = slot.getStack().copy();\n\t\t\t\t\tif (mouseButton == 1000) {\n\t\t\t\t\t\tstack.grow(1);\n\t\t\t\t\t} else if (stack.getCount() > 1) {\n\t\t\t\t\t\tstack.shrink(1);\n\t\t\t\t\t}\n\t\t\t\t\tstack.setCount(Math.min(slot.getSlotStackLimit(), Math.max(1, stack.getCount())));\n\t\t\t\t\tslot.putStack(stack);\n\t\t\t\t}\n\t\t\t\tif (slot instanceof DummySlot) {\n\t\t\t\t\t((DummySlot) slot).setRedirectCall(false);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (currentlyEquippedStack.isEmpty()) {\n\t\t\tif (!slot.getStack().isEmpty() && mouseButton == 1) {\n\t\t\t\tItemStack tstack = slot.getStack();\n\t\t\t\tif (shiftMode == ClickType.QUICK_MOVE) {\n\t\t\t\t\ttstack.setCount(Math.min(slot.getSlotStackLimit(), tstack.getCount() * 2));\n\t\t\t\t} else {\n\t\t\t\t\ttstack.setCount(tstack.getCount() / 2);\n\t\t\t\t}\n\t\t\t\tslot.putStack(tstack);\n\t\t\t} else {\n\t\t\t\tslot.putStack(ItemStack.EMPTY);\n\t\t\t}\n\t\t\tif (slot instanceof DummySlot) {\n\t\t\t\t((DummySlot) slot).setRedirectCall(false);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!slot.getHasStack()) {\n\t\t\tItemStack tstack = currentlyEquippedStack.copy();\n\t\t\tif (mouseButton == 1) {\n\t\t\t\ttstack.setCount(1);\n\t\t\t}\n\t\t\tif (tstack.getCount() > slot.getSlotStackLimit()) {\n\t\t\t\ttstack.setCount(slot.getSlotStackLimit());\n\t\t\t}\n\t\t\tslot.putStack(tstack);\n\t\t\tif (slot instanceof DummySlot) {\n\t\t\t\t((DummySlot) slot).setRedirectCall(false);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tItemIdentifier currentItem = ItemIdentifier.get(currentlyEquippedStack);\n\t\tItemIdentifier slotItem = ItemIdentifier.get(slot.getStack());\n\t\tif (currentItem.equals(slotItem)) {\n\t\t\tItemStack tstack = slot.getStack();\n\t\t\t// Do manual shift-checking to play nice with NEI\n\t\t\tint counter = shiftMode == ClickType.QUICK_MOVE ? 10 : 1;\n\t\t\tif (mouseButton == 1) {\n\t\t\t\tif (tstack.getCount() + counter <= slot.getSlotStackLimit()) {\n\t\t\t\t\ttstack.grow(counter);\n\t\t\t\t} else {\n\t\t\t\t\ttstack.setCount(slot.getSlotStackLimit());\n\t\t\t\t}\n\t\t\t\tslot.putStack(tstack);\n\t\t\t} else if (mouseButton == 0) {\n\t\t\t\ttstack.shrink(counter);\n\t\t\t\tslot.putStack(tstack);\n\t\t\t}\n\t\t\tif (slot instanceof DummySlot) {\n\t\t\t\t((DummySlot) slot).setRedirectCall(false);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tItemStack tstack = currentlyEquippedStack.copy();\n\t\tif (tstack.getCount() > slot.getSlotStackLimit()) {\n\t\t\ttstack.setCount(slot.getSlotStackLimit());\n\t\t}\n\t\tslot.putStack(tstack);\n\t\tif (slot instanceof DummySlot) {\n\t\t\t((DummySlot) slot).setRedirectCall(false);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onContainerClosed(@Nonnull EntityPlayer player) {\n\t\tif (_controler != null) {\n\t\t\tfor (IGuiOpenControler element : _controler) {\n\t\t\t\telement.guiClosedByPlayer(player);\n\t\t\t}\n\t\t}\n\t\tsuper.onContainerClosed(player);\n\t}\n\n\tpublic void addRestrictedHotbarForPlayerInventory(int xOffset, int yOffset) {\n\t\tif (_playerInventory == null) {\n\t\t\treturn;\n\t\t}\n\t\t// Player \"hotbar\"\n\t\tfor (int i1 = 0; i1 < 9; i1++) {\n\t\t\taddSlotToContainer(new UnmodifiableSlot(_playerInventory, i1, xOffset + i1 * 18, yOffset));\n\t\t}\n\t}\n\n\tpublic void addRestrictedArmorForPlayerInventory(int xOffset, int yOffset) {\n\t\tif (_playerInventory == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (int i1 = 0; i1 < 4; i1++) {\n\t\t\taddSlotToContainer(new UnmodifiableSlot(_playerInventory, i1 + 36, xOffset, yOffset - i1 * 18));\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean canDragIntoSlot(@Nonnull Slot slot) {\n\t\tif (slot instanceof UnmodifiableSlot || slot instanceof FluidSlot || slot instanceof ColorSlot || slot instanceof HandelableSlot) {\n\t\t\treturn false;\n\t\t}\n\t\tif (lastDragnDropLockup <= lastClicked) { // Slot was clicked after last lookup\n\t\t\tlastDragnDropLockup = System.currentTimeMillis();\n\t\t\tif (slot instanceof DummySlot) {\n\t\t\t\twasDummyLookup = true;\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\twasDummyLookup = false;\n\t\t\treturn true;\n\t\t} else { // Still lookingUp (during drag'n'drop)\n\t\t\tlastDragnDropLockup = System.currentTimeMillis();\n\t\t\tif (slot instanceof DummySlot) {\n\t\t\t\treturn wasDummyLookup;\n\t\t\t}\n\t\t\treturn !wasDummyLookup;\n\t\t}\n\t}\n\n\t// Hacky overrides to handle client/server player inv sync with 0-slot containers\n\t@Override\n\tpublic Slot getSlotFromInventory(@Nonnull IInventory par1IInventory, int par2) {\n\t\tSlot s = super.getSlotFromInventory(par1IInventory, par2);\n\t\tif (s != null) {\n\t\t\treturn s;\n\t\t}\n\t\tif (inventorySlots.isEmpty() && par1IInventory == _playerInventory) {\n\t\t\ts = new Slot(_playerInventory, par2, 0, 0);\n\t\t\ts.slotNumber = par2;\n\t\t\treturn s;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void putStackInSlot(int par1, @Nonnull ItemStack par2ItemStack) {\n\t\tif (inventorySlots.isEmpty()) {\n\t\t\t_playerInventory.setInventorySlotContents(par1, par2ItemStack);\n\t\t\t_playerInventory.markDirty();\n\t\t\treturn;\n\t\t}\n\t\tsuper.putStackInSlot(par1, par2ItemStack);\n\t}\n\n\t@Override\n\tpublic void detectAndSendChanges() {\n\t\tfor (int i = 0; i < inventorySlots.size(); ++i) {\n\t\t\tif (inventorySlots.get(i) instanceof IFuzzySlot) {\n\t\t\t\tIFuzzySlot fuzzySlot = (IFuzzySlot) inventorySlots.get(i);\n\t\t\t\tBitSet slotFlags = fuzzySlot.getFuzzyFlags().copyValue();\n\t\t\t\tBitSet savedFlags = slotsFuzzyFlags.get(i);\n\t\t\t\tif (savedFlags == null || !savedFlags.equals(slotFlags)) {\n\t\t\t\t\tMainProxy.sendToPlayerList(\n\t\t\t\t\t\t\tPacketHandler.getPacket(FuzzySlotSettingsPacket.class)\n\t\t\t\t\t\t\t\t\t.setSlotNumber(fuzzySlot.getSlotId())\n\t\t\t\t\t\t\t\t\t.setFlags(slotFlags),\n\t\t\t\t\t\t\tlisteners.stream().filter(o -> o instanceof EntityPlayer).map(o -> (EntityPlayer) o));\n\t\t\t\t\tslotsFuzzyFlags.set(i, slotFlags);\n\t\t\t\t}\n\t\t\t}\n\t\t\tItemStack itemstack = inventorySlots.get(i).getStack();\n\t\t\tItemStack itemstack1 = inventoryItemStacks.get(i);\n\n\t\t\tif (!ItemStack.areItemStacksEqual(itemstack1, itemstack)) {\n\t\t\t\titemstack1 = itemstack.isEmpty() ? ItemStack.EMPTY : itemstack.copy();\n\t\t\t\tinventoryItemStacks.set(i, itemstack1);\n\n\t\t\t\tfor (IContainerListener crafter : listeners) {\n\t\t\t\t\tboolean revert = false;\n\t\t\t\t\tif (overrideMCAntiSend && crafter instanceof EntityPlayerMP\n\t\t\t\t\t\t\t&& ((EntityPlayerMP) crafter).isChangingQuantityOnly) {\n\t\t\t\t\t\t((EntityPlayerMP) crafter).isChangingQuantityOnly = false;\n\t\t\t\t\t\trevert = true;\n\t\t\t\t\t}\n\t\t\t\t\tcrafter.sendSlotContents(this, i, itemstack1);\n\t\t\t\t\tif (revert) {\n\t\t\t\t\t\t((EntityPlayerMP) crafter).isChangingQuantityOnly = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\toverrideMCAntiSend = false;\n\t}\n\n\t@Nonnull\n\t@Override\n\tprotected Slot addSlotToContainer(@Nonnull Slot slotIn) {\n\t\tthis.slotsFuzzyFlags.add(null);\n\t\treturn super.addSlotToContainer(slotIn);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/DummyModuleContainer.java",
    "content": "package logisticspipes.utils.gui;\n\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.logisticspipes.ItemModuleInformationManager;\nimport logisticspipes.modules.LogisticsModule;\nimport logisticspipes.modules.LogisticsModule.ModulePositionType;\nimport logisticspipes.utils.DummyWorldProvider;\n\npublic class DummyModuleContainer extends DummyContainer {\n\n\tprivate final LogisticsModule module;\n\tprivate final int slot;\n\n\tpublic DummyModuleContainer(EntityPlayer player, int slot) {\n\t\tsuper(player.inventory, null);\n\t\tthis.slot = slot;\n\t\tItemStack moduleStack = player.inventory.mainInventory.get(slot);\n\t\tif (moduleStack.isEmpty()) throw new IllegalStateException(\"Module stack is empty\");\n\t\tmodule = ((ItemModule) moduleStack.getItem()).getModuleForItem(moduleStack, null, new DummyWorldProvider(player.world), null);\n\t\tObjects.requireNonNull(module, \"module was null for item \" + moduleStack.toString());\n\t\tmodule.registerPosition(ModulePositionType.IN_HAND, slot);\n\t\tItemModuleInformationManager.readInformation(moduleStack, module);\n\t}\n\n\tpublic LogisticsModule getModule() {\n\t\treturn module;\n\t}\n\n\tpublic void setInventory(IInventory inv) {\n\t\t_dummyInventory = inv;\n\t}\n\n\t@Override\n\t@Nonnull\n\tprotected Slot addSlotToContainer(@Nonnull Slot slotIn) {\n\t\tif (slotIn.getSlotIndex() == slot && slotIn.inventory == _playerInventory) {\n\t\t\treturn super.addSlotToContainer(new UnmodifiableSlot(slotIn));\n\t\t}\n\t\treturn super.addSlotToContainer(slotIn);\n\t}\n\n\t@Override\n\tpublic void onContainerClosed(@Nonnull EntityPlayer player) {\n\t\tsuper.onContainerClosed(player);\n\t\tItemModuleInformationManager.saveInformation(player.inventory.mainInventory.get(slot), module);\n\t\tplayer.inventory.markDirty();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/DummySlot.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\n\nimport lombok.Setter;\n\npublic class DummySlot extends Slot {\n\n\t@Setter\n\tprivate boolean redirectCall = false;\n\n\tpublic DummySlot(IInventory iinventory, int i, int j, int k) {\n\t\tsuper(iinventory, i, j, k);\n\t}\n\n\t@Override\n\tpublic boolean canTakeStack(EntityPlayer par1EntityPlayer) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int getSlotStackLimit() {\n\t\tif (redirectCall) {\n\t\t\treturn super.getSlotStackLimit();\n\t\t}\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/FluidSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\n\npublic class FluidSlot extends Slot {\n\n\tpublic FluidSlot(IInventory par1iInventory, int par2, int par3, int par4) {\n\t\tsuper(par1iInventory, par2, par3, par4);\n\t}\n\n\tpublic FluidSlot(Slot slot) {\n\t\tsuper(slot.inventory, slot.getSlotIndex(), slot.xPos, slot.yPos);\n\t}\n\n\t@Override\n\tpublic boolean canTakeStack(EntityPlayer par1EntityPlayer) {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/FuzzyDummySlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.inventory.IInventory;\n\nimport logisticspipes.interfaces.IFuzzySlot;\nimport network.rs485.logisticspipes.property.IBitSet;\n\npublic class FuzzyDummySlot extends DummySlot implements IFuzzySlot {\n\n\tprivate final IBitSet fuzzyFlags;\n\n\tpublic FuzzyDummySlot(IInventory iinventory, int i, int j, int k, IBitSet fuzzyFlags) {\n\t\tsuper(iinventory, i, j, k);\n\t\tthis.fuzzyFlags = fuzzyFlags;\n\t}\n\n\t@Override\n\tpublic IBitSet getFuzzyFlags() {\n\t\treturn fuzzyFlags;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn xPos;\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn yPos;\n\t}\n\n\t@Override\n\tpublic int getSlotId() {\n\t\treturn this.slotNumber;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/FuzzyUnmodifiableSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.inventory.IInventory;\n\nimport logisticspipes.interfaces.IFuzzySlot;\nimport network.rs485.logisticspipes.property.IBitSet;\n\npublic class FuzzyUnmodifiableSlot extends UnmodifiableSlot implements IFuzzySlot {\n\n\tprivate IBitSet fuzzyFlags;\n\n\tpublic FuzzyUnmodifiableSlot(IInventory par1iInventory, int par2, int par3, int par4, IBitSet fuzzyFlags) {\n\t\tsuper(par1iInventory, par2, par3, par4);\n\t\tthis.fuzzyFlags = fuzzyFlags;\n\t}\n\n\t@Override\n\tpublic IBitSet getFuzzyFlags() {\n\t\treturn fuzzyFlags;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn xPos;\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn yPos;\n\t}\n\n\t@Override\n\tpublic int getSlotId() {\n\t\treturn this.slotNumber;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/GuiCheckBox.java",
    "content": "package logisticspipes.utils.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.util.ResourceLocation;\n\nimport org.lwjgl.opengl.GL11;\n\npublic class GuiCheckBox extends GuiButton {\n\n\tprivate boolean state;\n\n\tpublic GuiCheckBox(int par1, int par2, int par3, int par4, int par5, boolean startState) {\n\t\tsuper(par1, par2, par3, par4, par5, \"\");\n\t\tstate = startState;\n\t}\n\n\t/**\n\t * Draws this button to the screen.\n\t */\n\t@Override\n\tpublic void drawButton(@Nonnull Minecraft minecraft, int par2, int par3, float partial) {\n\t\tif (visible) {\n\t\t\tboolean var5 = par2 >= x && par3 >= y && par2 < x + width && par3 < y + height;\n\t\t\tint var6 = getHoverState(var5);\n\t\t\t//GL11.glBindTexture(GL11.GL_TEXTURE_2D, minecraft.renderEngine.getTexture(\"/logisticspipes/gui/checkbox-\" + (state?\"on\":\"out\") + \"\" + (var6 == 2?\"-mouse\":\"\") + \".png\"));\n\t\t\tminecraft.renderEngine.bindTexture(new ResourceLocation(\"logisticspipes\", \"textures/gui/checkbox-\" + (state ? \"on\" : \"out\") + \"\" + (var6 == 2 ? \"-mouse\" : \"\") + \".png\"));\n\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\n\t\t\tTessellator tessellator = Tessellator.getInstance();\n\t\t\tBufferBuilder vertexbuffer = tessellator.getBuffer();\n\t\t\tvertexbuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\n\t\t\tvertexbuffer.pos(x, y + height, zLevel).tex(0, 1).endVertex();\n\t\t\tvertexbuffer.pos(x + width, y + height, zLevel).tex(1, 1).endVertex();\n\t\t\tvertexbuffer.pos(x + width, y, zLevel).tex(1, 0).endVertex();\n\t\t\tvertexbuffer.pos(x, y, zLevel).tex(0, 0).endVertex();\n\n\t\t\ttessellator.draw();\n\n\t\t\tmouseDragged(minecraft, par2, par3);\n\t\t}\n\t}\n\n\tpublic boolean change() {\n\t\treturn state = !state;\n\t}\n\n\tpublic boolean getState() {\n\t\treturn state;\n\t}\n\n\tpublic void setState(boolean flag) {\n\t\tstate = flag;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/GuiGraphics.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/mc16/LICENSE.md\n */\n\npackage logisticspipes.utils.gui;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.text.TextFormatting;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.proxy.SimpleServiceLocator;\nimport logisticspipes.utils.Color;\n\n/**\n * Utils class for GUI-related drawing methods.\n */\n@SideOnly(Side.CLIENT)\npublic final class GuiGraphics {\n\n\tpublic static final ResourceLocation WIDGETS_TEXTURE = new ResourceLocation(\"textures/gui/widgets.png\");\n\tpublic static final ResourceLocation SLOT_TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/slot.png\");\n\tpublic static final ResourceLocation BIG_SLOT_TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/slot-big.png\");\n\tpublic static final ResourceLocation SMALL_SLOT_TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/slot-small.png\");\n\tpublic static final ResourceLocation BACKGROUND_TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/GuiBackground.png\");\n\tpublic static final ResourceLocation LOCK_ICON = new ResourceLocation(\"logisticspipes\", \"textures/gui/lock.png\");\n\tpublic static final ResourceLocation LINES_ICON = new ResourceLocation(\"logisticspipes\", \"textures/gui/lines.png\");\n\tpublic static final ResourceLocation STATS_ICON = new ResourceLocation(\"logisticspipes\", \"textures/gui/stats.png\");\n\tpublic static final ResourceLocation SLOT_DISK_TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/slot_disk.png\");\n\tpublic static final ResourceLocation SLOT_PROGRAMMER_TEXTURE = new ResourceLocation(\"logisticspipes\", \"textures/gui/slot_programmer.png\");\n\tpublic static float zLevel = 0.0F;\n\n\tprivate GuiGraphics() {}\n\n\t/**\n\t * Draws the durability bar for GUI items.\n\t *\n\t * @param itemstack the itemstack, from which the durability bar should be drawn\n\t * @param x         the x-coordinate for the bar\n\t * @param y         the y-coordinate for the bar\n\t * @param zLevel    the z-level for the bar\n\t * TextureManager, ItemStack, int, int, String)\n\t */\n\tpublic static void drawDurabilityBar(@Nonnull ItemStack itemstack, int x, int y, double zLevel) {\n\t\tif (itemstack.getItem().showDurabilityBar(itemstack)) {\n\t\t\tdouble health = itemstack.getItem().getDurabilityForDisplay(itemstack);\n\t\t\tint j1 = (int) Math.round(13.0D - health * 13.0D);\n\t\t\tint k = (int) Math.round(255.0D - health * 255.0D);\n\t\t\tGL11.glDisable(GL11.GL_TEXTURE_2D);\n\t\t\tTessellator tessellator = Tessellator.getInstance();\n\t\t\tint l = 255 - k << 16 | k << 8 | 255 << 24;\n\t\t\tint i1 = (255 - k) / 4 << 16 | 16128 | 255 << 24;\n\t\t\tSimpleGraphics.drawQuad(tessellator, x + 2, y + 15, 13, 2, Color.BLACK, zLevel);\n\t\t\tSimpleGraphics.drawQuad(tessellator, x + 2, y + 15, 12, 1, i1, zLevel + 1.0F);\n\t\t\tSimpleGraphics.drawQuad(tessellator, x + 2, y + 15, j1, 1, l, zLevel + 2.0F);\n\t\t\tGL11.glEnable(GL11.GL_TEXTURE_2D);\n\t\t}\n\t}\n\n\tpublic static void displayItemToolTip(Object[] tooltip, Gui gui, float pzLevel, int guiLeft, int guiTop) {\n\t\tGuiGraphics.displayItemToolTip(tooltip, pzLevel, guiLeft, guiTop, false);\n\t}\n\n\t@SuppressWarnings(\"unchecked\")\n\tpublic static void displayItemToolTip(Object[] tooltip, float pzLevel, int guiLeft, int guiTop, boolean forceAdd) {\n\t\tif (tooltip == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tGuiGraphics.zLevel = pzLevel;\n\n\t\tMinecraft mc = FMLClientHandler.instance().getClient();\n\t\tItemStack stack = (ItemStack) tooltip[2];\n\t\tif (stack == null) stack = ItemStack.EMPTY;\n\n\t\tList<String> tooltipLines;\n\t\tif (mc.currentScreen instanceof GuiContainer) {\n\t\t\ttooltipLines = SimpleServiceLocator.neiProxy.getItemToolTip(stack, mc.player, mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL, (GuiContainer) mc.currentScreen);\n\t\t} else {\n\t\t\ttooltipLines = stack.getTooltip(mc.player, mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL);\n\t\t}\n\n\t\tif (tooltip.length > 4) {\n\t\t\ttooltipLines.addAll(1, (List<String>) tooltip[4]);\n\t\t}\n\n\t\tif ((Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)) && (tooltip.length < 4 || (Boolean) tooltip[3])) {\n\t\t\ttooltipLines.add(1, \"\\u00a77\" + ((ItemStack) tooltip[2]).getCount());\n\t\t}\n\n\t\tint x = (Integer) tooltip[0] - (forceAdd ? 0 : guiLeft) + 12;\n\t\tint y = (Integer) tooltip[1] - (forceAdd ? 0 : guiTop) - 12;\n\t\tif (!SimpleServiceLocator.neiProxy.renderItemToolTip(x, y, tooltipLines, stack.getRarity().color, stack)) {\n\t\t\tGuiGraphics.drawToolTip(x, y, tooltipLines, stack.getRarity().color);\n\t\t}\n\n\t\tGuiGraphics.zLevel = 0;\n\t}\n\n\tpublic static void drawToolTip(int posX, int posY, List<String> msg, TextFormatting rarityColor) {\n\t\tif (msg.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\n\t\t// use vanilla Minecraft code\n\t\tint boxWidth = 0;\n\n\t\tfor (String str : msg) {\n\t\t\tint width = FMLClientHandler.instance().getClient().fontRenderer.getStringWidth(str);\n\n\t\t\tif (width > boxWidth) {\n\t\t\t\tboxWidth = width;\n\t\t\t}\n\t\t}\n\n\t\tint x = posX + 12;\n\t\tint y = posY - 12;\n\t\tint yHeight = 8;\n\n\t\tif (msg.size() > 1) {\n\t\t\tyHeight += 2 + (msg.size() - 1) * 10;\n\t\t}\n\n\t\tGlStateManager.disableDepth();\n\t\tGlStateManager.disableLighting();\n\n\t\tGuiGraphics.zLevel = 300.0F;\n\t\tint bgColor = 0xf0100010;\n\t\tint frameColor1 = 0x505000ff;\n\t\tint frameColor2 = (frameColor1 & 0xfefefe) >> 1 | frameColor1 & 0xff000000;\n\n\t\tSimpleGraphics.drawGradientRect(x - 3, y - 4, x + boxWidth + 3, y - 3, bgColor, bgColor, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x - 3, y + yHeight + 3, x + boxWidth + 3, y + yHeight + 4, bgColor, bgColor, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x - 3, y - 3, x + boxWidth + 3, y + yHeight + 3, bgColor, bgColor, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x - 4, y - 3, x - 3, y + yHeight + 3, bgColor, bgColor, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x + boxWidth + 3, y - 3, x + boxWidth + 4, y + yHeight + 3, bgColor, bgColor, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x - 3, y - 3 + 1, x - 3 + 1, y + yHeight + 3 - 1, frameColor1, frameColor2, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x + boxWidth + 2, y - 3 + 1, x + boxWidth + 3, y + yHeight + 3 - 1, frameColor1, frameColor2, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x - 3, y - 3, x + boxWidth + 3, y - 3 + 1, frameColor1, frameColor1, 0.0);\n\t\tSimpleGraphics.drawGradientRect(x - 3, y + yHeight + 2, x + boxWidth + 3, y + yHeight + 3, frameColor2, frameColor2, 0.0);\n\n\t\tfor (int i = 0; i < msg.size(); ++i) {\n\t\t\tString line = msg.get(i);\n\n\t\t\tif (i == 0) {\n\t\t\t\tline = rarityColor.toString() + line;\n\t\t\t} else {\n\t\t\t\tline = \"\\u00a77\" + line;\n\t\t\t}\n\n\t\t\tFMLClientHandler.instance().getClient().fontRenderer.drawStringWithShadow(line, x, y, -1);\n\n\t\t\tif (i == 0) {\n\t\t\t\ty += 2;\n\t\t\t}\n\n\t\t\ty += 10;\n\t\t}\n\n\t\tGuiGraphics.zLevel = 0.0F;\n\n\t\tGlStateManager.enableDepth();\n\t}\n\n\tpublic static void drawPlayerInventoryBackground(Minecraft mc, int xOffset, int yOffset) {\n\t\t//Player \"backpack\"\n\t\tfor (int row = 0; row < 3; row++) {\n\t\t\tfor (int column = 0; column < 9; column++) {\n\t\t\t\tGuiGraphics.drawSlotBackground(mc, xOffset + column * 18 - 1, yOffset + row * 18 - 1);\n\t\t\t}\n\t\t}\n\t\t//Player \"hotbar\"\n\t\tfor (int i1 = 0; i1 < 9; i1++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, xOffset + i1 * 18 - 1, yOffset + 58 - 1);\n\t\t}\n\t}\n\n\tpublic static void drawPlayerHotbarBackground(Minecraft mc, int xOffset, int yOffset) {\n\t\t//Player \"hotbar\"\n\t\tfor (int i1 = 0; i1 < 9; i1++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, xOffset + i1 * 18 - 1, yOffset - 1);\n\t\t}\n\t}\n\n\tpublic static void drawPlayerArmorBackground(Minecraft mc, int xOffset, int yOffset) {\n\t\t//Player \"armor\"\n\t\tfor (int i1 = 0; i1 < 4; i1++) {\n\t\t\tGuiGraphics.drawSlotBackground(mc, xOffset - 1, yOffset - 1 - i1 * 18);\n\t\t}\n\t}\n\n\tprivate static void doDrawSlotBackground(Minecraft mc, int x, int y, ResourceLocation slotDiskTexture) {\n\t\tGuiGraphics.zLevel = 0;\n\t\tmc.renderEngine.bindTexture(slotDiskTexture);\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\n\t\tbuf.pos(x, y + 18, GuiGraphics.zLevel).tex(0, 1).endVertex();\n\t\tbuf.pos(x + 18, y + 18, GuiGraphics.zLevel).tex(1, 1).endVertex();\n\t\tbuf.pos(x + 18, y, GuiGraphics.zLevel).tex(1, 0).endVertex();\n\t\tbuf.pos(x, y, GuiGraphics.zLevel).tex(0, 0).endVertex();\n\t\ttess.draw();\n\t}\n\n\tpublic static void drawSlotDiskBackground(Minecraft mc, int x, int y) {\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tdoDrawSlotBackground(mc, x, y, GuiGraphics.SLOT_DISK_TEXTURE);\n\t}\n\n\tpublic static void drawSlotProgrammerBackground(Minecraft mc, int x, int y) {\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tdoDrawSlotBackground(mc, x, y, GuiGraphics.SLOT_PROGRAMMER_TEXTURE);\n\t}\n\n\tpublic static void drawSlotBackground(Minecraft mc, int x, int y) {\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tdoDrawSlotBackground(mc, x, y, GuiGraphics.SLOT_TEXTURE);\n\t}\n\n\tpublic static void drawSlotBackground(Minecraft mc, int x, int y, int color) {\n\t\tGlStateManager.color(Color.getRed(color), Color.getGreen(color), Color.getBlue(color), Color.getAlpha(color));\n\t\tdoDrawSlotBackground(mc, x, y, GuiGraphics.SLOT_TEXTURE);\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t}\n\n\tpublic static void drawBigSlotBackground(Minecraft mc, int x, int y) {\n\t\tGuiGraphics.zLevel = 0;\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiGraphics.BIG_SLOT_TEXTURE);\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\tbuf.pos(x, y + 26, GuiGraphics.zLevel).tex(0, 1).endVertex();\n\t\tbuf.pos(x + 26, y + 26, GuiGraphics.zLevel).tex(1, 1).endVertex();\n\t\tbuf.pos(x + 26, y, GuiGraphics.zLevel).tex(1, 0).endVertex();\n\t\tbuf.pos(x, y, GuiGraphics.zLevel).tex(0, 0).endVertex();\n\t\ttess.draw();\n\t}\n\n\tpublic static void drawSmallSlotBackground(Minecraft mc, int x, int y) {\n\t\tGuiGraphics.zLevel = 0;\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiGraphics.SMALL_SLOT_TEXTURE);\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\tbuf.pos(x, y + 8, GuiGraphics.zLevel).tex(0, 1).endVertex();\n\t\tbuf.pos(x + 8, y + 8, GuiGraphics.zLevel).tex(1, 1).endVertex();\n\t\tbuf.pos(x + 8, y, GuiGraphics.zLevel).tex(1, 0).endVertex();\n\t\tbuf.pos(x, y, GuiGraphics.zLevel).tex(0, 0).endVertex();\n\t\ttess.draw();\n\t}\n\n\tpublic static void renderIconAt(Minecraft mc, int x, int y, float zLevel, TextureAtlasSprite icon) {\n\t\tif (icon == null) {\n\t\t\treturn;\n\t\t}\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(new ResourceLocation(icon.getIconName()));\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\tbuf.pos(x, y + 16, GuiGraphics.zLevel).tex(icon.getMinU(), icon.getMaxV()).endVertex();\n\t\tbuf.pos(x + 16, y + 16, GuiGraphics.zLevel).tex(icon.getMaxU(), icon.getMaxV()).endVertex();\n\t\tbuf.pos(x + 16, y, GuiGraphics.zLevel).tex(icon.getMaxU(), icon.getMinV()).endVertex();\n\t\tbuf.pos(x, y, GuiGraphics.zLevel).tex(icon.getMinU(), icon.getMinV()).endVertex();\n\t\ttess.draw();\n\t}\n\n\tpublic static void drawLockBackground(Minecraft mc, int x, int y) {\n\t\tGuiGraphics.zLevel = 0;\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(GuiGraphics.LOCK_ICON);\n\t\tGlStateManager.enableBlend();\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\tbuf.pos(x, y + 15, GuiGraphics.zLevel).tex(0, 1).endVertex();\n\t\tbuf.pos(x + 14, y + 15, GuiGraphics.zLevel).tex(1, 1).endVertex();\n\t\tbuf.pos(x + 14, y, GuiGraphics.zLevel).tex(1, 0).endVertex();\n\t\tbuf.pos(x, y, GuiGraphics.zLevel).tex(0, 0).endVertex();\n\t\ttess.draw();\n\n\t\tGlStateManager.disableBlend();\n\t}\n\n\tprivate static void drawTexture16by16(Minecraft mc, int x, int y, ResourceLocation tex) {\n\t\tGuiGraphics.zLevel = 0;\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tmc.renderEngine.bindTexture(tex);\n\t\tGlStateManager.enableBlend();\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\tbuf.pos(x, y + 16, GuiGraphics.zLevel).tex(0, 1).endVertex();\n\t\tbuf.pos(x + 16, y + 16, GuiGraphics.zLevel).tex(1, 1).endVertex();\n\t\tbuf.pos(x + 16, y, GuiGraphics.zLevel).tex(1, 0).endVertex();\n\t\tbuf.pos(x, y, GuiGraphics.zLevel).tex(0, 0).endVertex();\n\t\ttess.draw();\n\n\t\tGlStateManager.disableBlend();\n\t}\n\n\tpublic static void drawLinesBackground(Minecraft mc, int x, int y) {\n\t\tdrawTexture16by16(mc, x, y, GuiGraphics.LINES_ICON);\n\t}\n\n\tpublic static void drawStatsBackground(Minecraft mc, int x, int y) {\n\t\tdrawTexture16by16(mc, x, y, GuiGraphics.STATS_ICON);\n\t}\n\n\tpublic static void drawGuiBackGround(Minecraft mc, int guiLeft, int guiTop, int right, int bottom, float zLevel, boolean resetColor) {\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop, right, bottom, zLevel, resetColor, true, true, true, true);\n\t}\n\n\tpublic static void drawGuiBackGround(Minecraft mc, int guiLeft, int guiTop, int right, int bottom, float zLevel, boolean resetColor, boolean displayTop, boolean displayLeft, boolean displayBottom, boolean displayRight) {\n\t\tif (resetColor) {\n\t\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t}\n\t\tmc.renderEngine.bindTexture(GuiGraphics.BACKGROUND_TEXTURE);\n\n\t\tTessellator tess = Tessellator.getInstance();\n\t\tBufferBuilder buf = tess.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\n\t\tif (displayTop) {\n\t\t\t//Top Side\n\t\t\tbuf.pos(guiLeft + 15, guiTop + 15, zLevel).tex(0.33, 0.33).endVertex();\n\t\t\tbuf.pos(right - 15, guiTop + 15, zLevel).tex(0.66, 0.33).endVertex();\n\t\t\tbuf.pos(right - 15, guiTop, zLevel).tex(0.66, 0).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, guiTop, zLevel).tex(0.33, 0).endVertex();\n\t\t}\n\n\t\tif (displayLeft) {\n\t\t\t//Left Side\n\t\t\tbuf.pos(guiLeft, bottom - 15, zLevel).tex(0, 0.66).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, bottom - 15, zLevel).tex(0.33, 0.66).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, guiTop + 15, zLevel).tex(0.33, 0.33).endVertex();\n\t\t\tbuf.pos(guiLeft, guiTop + 15, zLevel).tex(0, 0.33).endVertex();\n\t\t}\n\n\t\tif (displayBottom) {\n\t\t\t//Bottom Side\n\t\t\tbuf.pos(guiLeft + 15, bottom, zLevel).tex(0.33, 1).endVertex();\n\t\t\tbuf.pos(right - 15, bottom, zLevel).tex(0.66, 1).endVertex();\n\t\t\tbuf.pos(right - 15, bottom - 15, zLevel).tex(0.66, 0.66).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, bottom - 15, zLevel).tex(0.33, 0.66).endVertex();\n\t\t}\n\n\t\tif (displayRight) {\n\t\t\t//Right Side\n\t\t\tbuf.pos(right - 15, bottom - 15, zLevel).tex(0.66, 0.66).endVertex();\n\t\t\tbuf.pos(right, bottom - 15, zLevel).tex(1, 0.66).endVertex();\n\t\t\tbuf.pos(right, guiTop + 15, zLevel).tex(1, 0.33).endVertex();\n\t\t\tbuf.pos(right - 15, guiTop + 15, zLevel).tex(0.66, 0.33).endVertex();\n\t\t}\n\n\t\tif (displayTop && displayLeft) {\n\t\t\t//Top Left\n\t\t\tbuf.pos(guiLeft, guiTop + 15, zLevel).tex(0, 0.33).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, guiTop + 15, zLevel).tex(0.33, 0.33).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, guiTop, zLevel).tex(0.33, 0).endVertex();\n\t\t\tbuf.pos(guiLeft, guiTop, zLevel).tex(0, 0).endVertex();\n\t\t}\n\n\t\tif (displayBottom && displayLeft) {\n\t\t\t//Bottom Left\n\t\t\tbuf.pos(guiLeft, bottom, zLevel).tex(0, 1).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, bottom, zLevel).tex(0.33, 1).endVertex();\n\t\t\tbuf.pos(guiLeft + 15, bottom - 15, zLevel).tex(0.33, 0.66).endVertex();\n\t\t\tbuf.pos(guiLeft, bottom - 15, zLevel).tex(0, 0.66).endVertex();\n\t\t}\n\n\t\tif (displayBottom && displayRight) {\n\t\t\t//Bottom Right\n\t\t\tbuf.pos(right - 15, bottom, zLevel).tex(0.66, 1).endVertex();\n\t\t\tbuf.pos(right, bottom, zLevel).tex(1, 1).endVertex();\n\t\t\tbuf.pos(right, bottom - 15, zLevel).tex(1, 0.66).endVertex();\n\t\t\tbuf.pos(right - 15, bottom - 15, zLevel).tex(0.66, 0.66).endVertex();\n\t\t}\n\n\t\tif (displayTop && displayRight) {\n\t\t\t//Top Right\n\t\t\tbuf.pos(right - 15, guiTop + 15, zLevel).tex(0.66, 0.33).endVertex();\n\t\t\tbuf.pos(right, guiTop + 15, zLevel).tex(1, 0.33).endVertex();\n\t\t\tbuf.pos(right, guiTop, zLevel).tex(1, 0).endVertex();\n\t\t\tbuf.pos(right - 15, guiTop, zLevel).tex(0.66, 0).endVertex();\n\t\t}\n\n\t\t//Center\n\t\tbuf.pos(guiLeft + 15, bottom - 15, zLevel).tex(0.33, 0.66).endVertex();\n\t\tbuf.pos(right - 15, bottom - 15, zLevel).tex(0.66, 0.66).endVertex();\n\t\tbuf.pos(right - 15, guiTop + 15, zLevel).tex(0.66, 0.33).endVertex();\n\t\tbuf.pos(guiLeft + 15, guiTop + 15, zLevel).tex(0.33, 0.33).endVertex();\n\n\t\ttess.draw();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/GuiStringHandlerButton.java",
    "content": "package logisticspipes.utils.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\n\npublic class GuiStringHandlerButton extends GuiButton {\n\n\tprivate final StringHandler handler;\n\n\tpublic GuiStringHandlerButton(int par1, int par2, int par3, StringHandler handler) {\n\t\tsuper(par1, par2, par3, \"\");\n\t\tthis.handler = handler;\n\t}\n\n\tpublic GuiStringHandlerButton(int par1, int par2, int par3, int par4, int par5, StringHandler handler) {\n\t\tsuper(par1, par2, par3, par4, par5, \"\");\n\t\tthis.handler = handler;\n\t}\n\n\t@Override\n\tpublic void drawButton(@Nonnull Minecraft par1Minecraft, int par2, int par3, float partial) {\n\t\tdisplayString = handler.getContent();\n\t\tsuper.drawButton(par1Minecraft, par2, par3, partial);\n\t}\n\n\tpublic interface StringHandler {\n\n\t\tString getContent();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/HandelableSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.interfaces.ISlotClick;\n\npublic class HandelableSlot extends Slot {\n\n\tprivate final ISlotClick _handler;\n\n\tpublic HandelableSlot(IInventory inventory, int slotId, int xCoord, int yCoord, ISlotClick handler) {\n\t\tsuper(inventory, slotId, xCoord, yCoord);\n\t\t_handler = handler;\n\t}\n\n\t@Override\n\tpublic boolean isItemValid(@Nonnull ItemStack par1ItemStack) {\n\t\treturn par1ItemStack.isEmpty();\n\t}\n\n\t@Nonnull\n\tpublic ItemStack getProvidedStack() {\n\t\treturn _handler.getResultForClick();\n\t}\n\n\t@Override\n\tpublic boolean canTakeStack(EntityPlayer p_82869_1_) {\n\t\treturn false;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/HudGraphics.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/mc16/LICENSE.md\n */\n\npackage logisticspipes.utils.gui;\n\n/**\n * Utils class for HUD-related drawing methods.\n */\npublic final class HudGraphics {\n\n\tprivate HudGraphics() {}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/IGuiAccess.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.client.Minecraft;\n\npublic interface IGuiAccess {\n\n\tint getGuiLeft();\n\n\tint getGuiTop();\n\n\tint getXSize();\n\n\tint getYSize();\n\n\tint getRight();\n\n\tint getBottom();\n\n\tMinecraft getMC();\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/IItemSearch.java",
    "content": "package logisticspipes.utils.gui;\n\nimport logisticspipes.utils.item.ItemIdentifier;\n\npublic interface IItemSearch {\n\n\tboolean itemSearched(ItemIdentifier item);\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/IItemTextureRenderSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\npublic abstract class IItemTextureRenderSlot implements IRenderSlot {\n\n\t@SideOnly(Side.CLIENT)\n\tpublic abstract TextureAtlasSprite getTextureIcon();\n\n\tpublic abstract boolean drawSlotIcon();\n\n\tpublic abstract boolean customRender(Minecraft mc, float zLevel);\n\n\t@Override\n\tpublic int getSize() {\n\t\treturn 18;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/IRenderSlot.java",
    "content": "package logisticspipes.utils.gui;\n\npublic interface IRenderSlot {\n\n\tvoid mouseClicked(int button);\n\n\tboolean drawSlotBackground();\n\n\tint getXPos();\n\n\tint getYPos();\n\n\tString getToolTipText();\n\n\tboolean displayToolTip();\n\n\tint getSize();\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/ISmallColorRenderSlot.java",
    "content": "package logisticspipes.utils.gui;\n\npublic abstract class ISmallColorRenderSlot implements IRenderSlot {\n\n\tpublic abstract int getColor();\n\n\tpublic abstract boolean drawColor();\n\n\t@Override\n\tpublic int getSize() {\n\t\treturn 8;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/ISubGuiControler.java",
    "content": "package logisticspipes.utils.gui;\n\npublic interface ISubGuiControler {\n\n\tvoid setSubGui(SubGuiScreen gui);\n\n\tvoid resetSubGui();\n\n\tboolean hasSubGui();\n\n\tSubGuiScreen getSubGui();\n\n\tLogisticsBaseGuiScreen getBaseScreen();\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/InputBar.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.client.gui.FontRenderer;\n\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.client.gui.GuiTextField;\nimport net.minecraft.util.ChatAllowedCharacters;\n\nimport org.lwjgl.input.Keyboard;\n\npublic class InputBar extends GuiTextField implements LogisticsBaseGuiScreen.EventListener {\n\n\tpublic enum Align {\n\t\tLEFT,\n\t\tCENTER,\n\t\tRIGHT\n\t}\n\n\tpublic int minNumber = 0;\n\n\tpublic InputBar(FontRenderer fontRenderer, LogisticsBaseGuiScreen screen, int left, int top, int width, int height) {\n\t\tthis(fontRenderer, screen, left, top, width, height, true);\n\t}\n\n\tpublic InputBar(FontRenderer fontRenderer, LogisticsBaseGuiScreen screen, int left, int top, int width, int height, boolean isActive) {\n\t\tthis(fontRenderer, screen, left, top, width, height, isActive, false);\n\t}\n\n\tpublic InputBar(FontRenderer fontRenderer, LogisticsBaseGuiScreen screen, int left, int top, int width, int height, boolean isActive, boolean numberOnly) {\n\t\tthis(fontRenderer, screen, left, top, width, height, isActive, numberOnly, Align.LEFT);\n\t}\n\n\tpublic InputBar(FontRenderer fontRenderer, LogisticsBaseGuiScreen screen, int left, int top, int width, int height, boolean isActive, boolean numberOnly, Align align) {\n\t\tsuper(0, fontRenderer, left+2, top, width-4, height-2);\n\t\tscreen.onGuiEvents.add(this);\n\t\tif (numberOnly) {\n\t\t\tsetValidator((String s) -> {\n\t\t\t\ttry {\n\t\t\t\t\treturn Integer.parseInt(s) >= minNumber;\n\t\t\t\t} catch (NumberFormatException ignored) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t\tsetMaxStringLength(5);\n\t\t} else\n\t\t\tsetMaxStringLength(128);\n\t}\n\n\tpublic void reposition(int left, int top, int width, int height) {\n\t\tx = left+2;\n\t\ty = top;\n\t\tthis.width = width-4;\n\t\tthis.height = height-2;\n\t}\n\n\t@Override\n\tpublic void onUpdateScreen() {\n\t\tupdateCursorCounter();\n\t}\n\n\t@Override\n\tpublic boolean onKeyboardInput() {\n\t\treturn (isFocused() || GuiScreen.isAltKeyDown()) && ChatAllowedCharacters.isAllowedCharacter(Keyboard.getEventCharacter());\n\t}\n\n\t/**\n\t * @return Boolean, true if click was handled.\n\t */\n\tpublic boolean handleClick(int x, int y, int k) {\n\t\tif (k == 1 && x >= this.x && x < this.x + width && y >= this.y && y < y + height)\n\t\t\tsetText(\"\");\n\t\treturn mouseClicked(x, y, k);\n\t}\n\n\t/**\n\t * @return Boolean, true if key was handled.\n\t */\n\tpublic boolean handleKey(char c, int i) {\n\t\tif (GuiScreen.isKeyComboCtrlC(i) && (getSelectedText().isEmpty()))\n\t\t\tGuiScreen.setClipboardString(this.getText());\n\t\treturn textboxKeyTyped(c, i);\n\t}\n\n\tpublic void setInteger(int newValue) {\n\t\tsetText(Integer.toString(Math.max(minNumber, newValue)));\n\t}\n\n\tpublic int getInteger() {\n\t\ttry {\n\t\t\treturn Math.max(minNumber, Integer.parseInt(getText()));\n\t\t} catch (NumberFormatException ignored) {\n\t\t\treturn minNumber;\n\t\t}\n\t}\n\n\tpublic boolean isEmpty() {\n\t\treturn getText().isEmpty();\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/ItemDisplay.java",
    "content": "package logisticspipes.utils.gui;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.Map;\nimport java.util.Map.Entry;\nimport java.util.Objects;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.gui.ScaledResolution;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.util.ResourceLocation;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport lombok.Getter;\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.config.Configs;\nimport logisticspipes.interfaces.ISpecialItemRenderer;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\nimport logisticspipes.utils.item.ItemStackRenderer;\nimport logisticspipes.utils.item.ItemStackRenderer.DisplayAmount;\nimport logisticspipes.utils.tuples.Pair;\n\npublic class ItemDisplay {\n\n\tpublic enum DisplayOption {\n\t\tID,\n\t\tID_DOWN,\n\t\tSIZE,\n\t\tSIZE_DOWN,\n\t\tNAME,\n\t\tNAME_DOWN,\n\t}\n\n\tprivate static final ResourceLocation TEXTURE = new ResourceLocation(\"textures/gui/icons.png\");\n\tprivate static final int PANELSIZEX = 20;\n\tprivate static final int PANELSIZEY = 20;\n\n\tprivate ItemIdentifierStack selectedItem = null;\n\tpublic final LinkedList<ItemIdentifierStack> _allItems = new LinkedList<>();\n\tprivate final Map<Pair<Integer, Integer>, ItemIdentifierStack> map = new HashMap<>();\n\n\t@Getter\n\tprivate int page = 0;\n\tprivate int maxPage = 0;\n\t//private int requestCount = 1;\n\tprivate InputBar requestCountBar;\n\tprivate Object[] tooltip = null;\n\tprivate boolean listbyserver = false;\n\n\tprivate final IItemSearch search;\n\tprivate final FontRenderer fontRenderer;\n\tprivate final LogisticsBaseGuiScreen screen;\n\tprivate final ISpecialItemRenderer renderer;\n\tprivate int left, top, height, width, amountPosLeft, amountPosTop, amountWidth;\n\tprivate int itemsPerPage;\n\tprivate final int[] amountChangeMode;\n\tprivate final boolean shiftPageChange;\n\tprivate final Minecraft mc = FMLClientHandler.instance().getClient();\n\tprivate static DisplayOption option = DisplayOption.ID;\n\tprivate final ItemStackRenderer stackRenderer = new ItemStackRenderer(0, 0, 100.0F, false, false);\n\n\tpublic ItemDisplay(IItemSearch search, FontRenderer fontRenderer, LogisticsBaseGuiScreen screen, ISpecialItemRenderer renderer, int left, int top, int width, int height, int amountPosLeft, int amountPosTop, int amountWidth, int[] amountChangeMode, boolean shiftPageChange) {\n\t\tthis.search = search;\n\t\tthis.fontRenderer = fontRenderer;\n\t\tthis.screen = screen;\n\t\tthis.renderer = renderer;\n\t\tthis.left = left;\n\t\tthis.top = top;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.amountPosLeft = amountPosLeft;\n\t\tthis.amountPosTop = amountPosTop;\n\t\tthis.amountWidth = amountWidth;\n\t\titemsPerPage = this.width * this.height / (20 * 20);\n\t\tif (amountChangeMode.length != 4) {\n\t\t\tthrow new UnsupportedOperationException(\"amountChangeMode.length needs to be 4\");\n\t\t}\n\t\tthis.amountChangeMode = amountChangeMode;\n\t\tthis.shiftPageChange = shiftPageChange;\n\t\tthis.requestCountBar = new InputBar(this.fontRenderer, screen, amountPosLeft - (amountWidth / 2), amountPosTop - 5, amountWidth, 12, false, true, InputBar.Align.CENTER);\n\t\tthis.requestCountBar.minNumber = 1;\n\t\tthis.requestCountBar.setInteger(1);\n\t}\n\n\tpublic void reposition(int left, int top, int width, int height, int amountPosLeft, int amountPosTop) {\n\t\tthis.left = left;\n\t\tthis.top = top;\n\t\tthis.width = width;\n\t\tthis.height = height;\n\t\tthis.amountPosLeft = amountPosLeft;\n\t\tthis.amountPosTop = amountPosTop;\n\t\titemsPerPage = this.width * this.height / (20 * 20);\n\t\tthis.requestCountBar.reposition(amountPosLeft - (this.amountWidth / 2), amountPosTop - 2, this.amountWidth, 12);\n\t}\n\n\tpublic void setItemList(Collection<ItemIdentifierStack> allItems) {\n\t\tlistbyserver = true;\n\t\t_allItems.clear();\n\t\tallItems.stream().sorted(new ItemidStackDisplayOptionComparator()).forEach(_allItems::add);\n\t\tboolean found = false;\n\t\tif (selectedItem == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (ItemIdentifierStack itemStack : _allItems) {\n\t\t\tif (itemStack.getItem().equals(selectedItem.getItem())) {\n\t\t\t\tselectedItem = itemStack;\n\t\t\t\tfound = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!found) {\n\t\t\tselectedItem = null;\n\t\t}\n\t}\n\n\tprivate static class ItemidStackDisplayOptionComparator implements Comparator<ItemIdentifierStack> {\n\n\t\t@Override\n\t\tpublic int compare(ItemIdentifierStack o1, ItemIdentifierStack o2) {\n\t\t\tif (ItemDisplay.option == DisplayOption.ID) {\n\t\t\t\tint c = basicCompare(o1, o2);\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn o2.getStackSize() - o1.getStackSize();\n\t\t\t} else if (ItemDisplay.option == DisplayOption.ID_DOWN) {\n\t\t\t\tint c = basicCompare(o2, o1);\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn o1.getStackSize() - o2.getStackSize();\n\t\t\t} else if (ItemDisplay.option == DisplayOption.SIZE) {\n\t\t\t\tint c = o2.getStackSize() - o1.getStackSize();\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn basicCompare(o1, o2);\n\t\t\t} else if (ItemDisplay.option == DisplayOption.SIZE_DOWN) {\n\t\t\t\tint c = o1.getStackSize() - o2.getStackSize();\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn basicCompare(o2, o1);\n\t\t\t} else if (ItemDisplay.option == DisplayOption.NAME) {\n\t\t\t\tint c = o1.getItem().getFriendlyName().compareToIgnoreCase(o2.getItem().getFriendlyName());\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\tc = basicCompare(o1, o2);\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn o2.getStackSize() - o1.getStackSize();\n\t\t\t} else if (ItemDisplay.option == DisplayOption.NAME_DOWN) {\n\t\t\t\tint c = o2.getItem().getFriendlyName().compareToIgnoreCase(o1.getItem().getFriendlyName());\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\tc = basicCompare(o2, o1);\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn o1.getStackSize() - o2.getStackSize();\n\t\t\t} else {\n\t\t\t\tint c = basicCompare(o1, o2);\n\t\t\t\tif (c != 0) {\n\t\t\t\t\treturn c;\n\t\t\t\t}\n\t\t\t\treturn o2.getStackSize() - o1.getStackSize();\n\t\t\t}\n\t\t}\n\n\t\tprivate int basicCompare(ItemIdentifierStack o1, ItemIdentifierStack o2) {\n\t\t\treturn o1.compareTo(o2);\n\t\t}\n\t}\n\n\tpublic void cycle() {\n\t\tint i = ItemDisplay.option.ordinal();\n\t\ti++;\n\t\tif (i >= DisplayOption.values().length) {\n\t\t\ti = 0;\n\t\t}\n\t\tItemDisplay.option = DisplayOption.values()[i];\n\t\t_allItems.sort(new ItemidStackDisplayOptionComparator());\n\t}\n\n\tpublic void renderSortMode(int x, int y) {\n\t\tString name = ItemDisplay.option.name();\n\t\tboolean up = true;\n\t\tif (name.endsWith(\"_DOWN\")) {\n\t\t\tname = name.substring(0, name.length() - 5);\n\t\t\tup = false;\n\t\t}\n\t\tname += !up ? \" /\\\\\" : \" \\\\/\";\n\t\tfontRenderer.drawString(name, x - fontRenderer.getStringWidth(name) / 2, y, 0x404040);\n\t}\n\n\tpublic void renderPageNumber(int x, int y) {\n\t\tmaxPage = (getSearchedItemNumber() - 1) / itemsPerPage;\n\t\tif (maxPage == -1) {\n\t\t\tmaxPage = 0;\n\t\t}\n\t\tif (page > maxPage) {\n\t\t\tpage = maxPage;\n\t\t}\n\t\tString pageString = \"Page \" + (page + 1) + \" / \" + (maxPage + 1);\n\t\tfontRenderer.drawString(pageString, x - fontRenderer.getStringWidth(pageString) / 2, y, 0x404040);\n\t}\n\n\tprivate int getSearchedItemNumber() {\n\t\tint count = 0;\n\t\tfor (ItemIdentifierStack item : _allItems) {\n\t\t\tif (search == null || search.itemSearched(item.getItem())) {\n\t\t\t\tcount++;\n\t\t\t}\n\t\t}\n\t\treturn count;\n\t}\n\n\tpublic void renderAmount(int stackAmount) {\n\t\tint requestCount = requestCountBar.getInteger();\n\t\tString StackrequestCount = \"\" + (requestCount / stackAmount) + \"+\" + (requestCount % stackAmount);\n\t\t//fontRenderer.drawString(requestCount + \"\", x - fontRenderer.getStringWidth(requestCount + \"\") / 2, y, 0x404040);\n\t\tfontRenderer.drawString(StackrequestCount + \"\", this.amountPosLeft - fontRenderer.getStringWidth(StackrequestCount + \"\") / 2, this.amountPosTop + 11, 0x404040);\n\n\t\trequestCountBar.drawTextBox();\n\t}\n\n\tpublic void renderItemArea(double zLevel) {\n\t\tGlStateManager.pushMatrix();\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tscreen.drawRect(left, top, left + width, top + height, Color.GREY);\n\n\t\ttooltip = null;\n\t\tint ppi = 0;\n\t\tint panelxSize = 20;\n\t\tint panelySize = 20;\n\t\tint x = 2;\n\t\tint y = 2;\n\t\tScaledResolution scaledresolution = new ScaledResolution(mc);\n\t\tint scaleX = scaledresolution.getScaledWidth();\n\t\tint scaleY = scaledresolution.getScaledHeight();\n\t\tint mouseX = Mouse.getX() * scaleX / mc.displayWidth - left;\n\t\tint mouseY = scaleY - Mouse.getY() * scaleY / mc.displayHeight - top;\n\n\t\tGlStateManager.translate(left, top, 0.0F);\n\n\t\tif (!listbyserver) {\n\t\t\tint graphic = ((int) (System.currentTimeMillis() / 250) % 5);\n\t\t\tscreen.getMC().renderEngine.bindTexture(ItemDisplay.TEXTURE);\n\t\t\tTessellator tess = Tessellator.getInstance();\n\t\t\tBufferBuilder buf = tess.getBuffer();\n\t\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\t\tint xPosition = (width / 2) - 50;\n\t\t\tint yPosition = 40;\n\t\t\tbuf.pos(xPosition, yPosition + 100, zLevel).tex(0.04, 0.72 + (graphic * 0.03125)).endVertex();\n\t\t\tbuf.pos(xPosition + 100, yPosition + 100, zLevel).tex(0.08, 0.72 + (graphic * 0.03125)).endVertex();\n\t\t\tbuf.pos(xPosition + 100, yPosition, zLevel).tex(0.08, 0.69 + (graphic * 0.03125)).endVertex();\n\t\t\tbuf.pos(xPosition, yPosition, zLevel).tex(0.04, 0.69 + (graphic * 0.03125)).endVertex();\n\t\t\ttess.draw();\n\t\t} else {\n\n\t\t\tfor (ItemIdentifierStack itemIdentifierStack : _allItems) {\n\t\t\t\tItemIdentifier item = itemIdentifierStack.getItem();\n\t\t\t\tif (search != null && !search.itemSearched(item)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tppi++;\n\n\t\t\t\tif (ppi <= itemsPerPage * page) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (ppi > itemsPerPage * (page + 1)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t//\n\t\t\t\t// -2 on both, because field starts there (see black rect below)\n\t\t\t\tint realX = x - 2;\n\t\t\t\tint realY = y - 2;\n\n\t\t\t\tPair<Integer, Integer> pair = new Pair<>(realX, realY);\n\t\t\t\tif (map.get(pair) != itemIdentifierStack) {\n\t\t\t\t\tmap.put(pair, itemIdentifierStack);\n\t\t\t\t}\n\n\t\t\t\tif (mouseX >= realX && mouseX < realX + panelxSize && mouseY >= realY && mouseY < realY + panelySize) {\n\t\t\t\t\tscreen.drawRect(x - 2, y - 2, x + panelxSize - 2, y + panelySize - 2, Color.BLACK);\n\t\t\t\t\tscreen.drawRect(x - 1, y - 1, x + panelxSize - 3, y + panelySize - 3, Color.DARKER_GREY);\n\n\t\t\t\t\tif (itemIdentifierStack.getStackSize() > 0) {\n\t\t\t\t\t\ttooltip = new Object[] { mouseX + left, mouseY + top, itemIdentifierStack.unsafeMakeNormalStack() };\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttooltip = new Object[] { mouseX + left, mouseY + top, itemIdentifierStack.getItem().unsafeMakeNormalStack(1) };\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/*if (lastClickedx >= realX && lastClickedx < realX + panelxSize && lastClickedy >= realY && lastClickedy < realY + panelySize) {\n\t\t\t\t\tselectedItem = itemIdentifierStack;\n\t\t\t\t\tscreen.drawRect(x - 2, y - 2, x + panelxSize - 2, y + panelySize - 2, Color.BLACK);\n\t\t\t\t\tscreen.drawRect(x - 1, y - 1, x + panelxSize - 3, y + panelySize - 3, Color.LIGHTER_GREY);\n\t\t\t\t\tscreen.drawRect(x, y, x + panelxSize - 4, y + panelySize - 4, Color.DARKER_GREY);\n\t\t\t\t}\n\t\t\t\t */\n\t\t\t\tif (selectedItem == itemIdentifierStack) {\n\t\t\t\t\tscreen.drawRect(x - 2, y - 2, x + panelxSize - 2, y + panelySize - 2, Color.BLACK);\n\t\t\t\t\tscreen.drawRect(x - 1, y - 1, x + panelxSize - 3, y + panelySize - 3, Color.LIGHTER_GREY);\n\t\t\t\t\tscreen.drawRect(x, y, x + panelxSize - 4, y + panelySize - 4, Color.DARKER_GREY);\n\t\t\t\t\tif (renderer != null) {\n\t\t\t\t\t\trenderer.specialItemRendering(itemIdentifierStack.getItem(), x, y);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tGlStateManager.enableLighting();\n\t\t\t\t// use GuiGraphics to render the ItemStacks\n\t\t\t\tstackRenderer.setPosX(x).setPosY(y).setItemIdentStack(itemIdentifierStack).setDisplayAmount(DisplayAmount.HIDE_ONE).renderInGui();\n\t\t\t\tGlStateManager.disableLighting();\n\n\t\t\t\tx += panelxSize;\n\t\t\t\tif (x > width) {\n\t\t\t\t\tx = 2;\n\t\t\t\t\ty += panelySize;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\tGlStateManager.popMatrix();\n\n\t}\n\n\tpublic void handleMouse() {\n\t\tboolean isShift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);\n\t\tboolean isControl = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL);\n\t\tint wheel = Mouse.getEventDWheel() / 120;\n\t\tif (wheel == 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (isShift && !isControl && isShiftPageChange()) {\n\t\t\tif (wheel > 0) {\n\t\t\t\tif (!Configs.LOGISTICS_ORDERER_PAGE_INVERTWHEEL) {\n\t\t\t\t\tprevPage();\n\t\t\t\t} else {\n\t\t\t\t\tnextPage();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (!Configs.LOGISTICS_ORDERER_PAGE_INVERTWHEEL) {\n\t\t\t\t\tnextPage();\n\t\t\t\t} else {\n\t\t\t\t\tprevPage();\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (!requestCountBar.isFocused()) {\n\t\t\tint requestCount = requestCountBar.getInteger();\n\t\t\tif (isShift && !isControl && !isShiftPageChange()) {\n\t\t\t\tif (wheel > 0) {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount - (wheel * getAmountChangeMode(4)));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (requestCount == 1) {\n\t\t\t\t\t\t\trequestCount -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequestCount += wheel * getAmountChangeMode(4);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\tif (requestCount == 1) {\n\t\t\t\t\t\t\trequestCount -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequestCount += -(wheel * getAmountChangeMode(4));\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount + wheel * getAmountChangeMode(4));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (!isControl) {\n\t\t\t\tif (wheel > 0) {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount - (wheel * getAmountChangeMode(1)));\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequestCount += wheel * getAmountChangeMode(1);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\trequestCount += -(wheel * getAmountChangeMode(1));\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount + wheel * getAmountChangeMode(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (isControl && !isShift) {\n\t\t\t\tif (wheel > 0) {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount - wheel * getAmountChangeMode(2));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (requestCount == 1) {\n\t\t\t\t\t\t\trequestCount -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequestCount += wheel * getAmountChangeMode(2);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\tif (requestCount == 1) {\n\t\t\t\t\t\t\trequestCount -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequestCount += -wheel * getAmountChangeMode(2);\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount + wheel * getAmountChangeMode(2));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (isControl && isShift) {\n\t\t\t\tif (wheel > 0) {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount - wheel * getAmountChangeMode(3));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (requestCount == 1) {\n\t\t\t\t\t\t\trequestCount -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequestCount += wheel * getAmountChangeMode(3);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (!Configs.LOGISTICS_ORDERER_COUNT_INVERTWHEEL) {\n\t\t\t\t\t\tif (requestCount == 1) {\n\t\t\t\t\t\t\trequestCount -= 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequestCount += -wheel * getAmountChangeMode(3);\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequestCount = Math.max(1, requestCount + wheel * getAmountChangeMode(3));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\trequestCountBar.setInteger(requestCount);\n\t\t}\n\t}\n\n\tprivate int getAmountChangeMode(int step) {\n\t\treturn amountChangeMode[step - 1];\n\t}\n\n\tprivate boolean isShiftPageChange() {\n\t\treturn shiftPageChange;\n\t}\n\n\tpublic Object[] getToolTip() {\n\t\treturn tooltip;\n\t}\n\n\tpublic void resetAmount() {\n\t\trequestCountBar.setInteger(1);\n\t}\n\n\tpublic void setMaxAmount() {\n\t\tif (selectedItem != null && selectedItem.getStackSize() != 0) {\n\t\t\trequestCountBar.setInteger(selectedItem.getStackSize());\n\t\t}\n\t}\n\n\tpublic void nextPage() {\n\t\tif (page < maxPage) {\n\t\t\tpage++;\n\t\t} else {\n\t\t\tpage = 0;\n\t\t}\n\t}\n\n\tpublic void prevPage() {\n\t\tif (page > 0) {\n\t\t\tpage--;\n\t\t} else {\n\t\t\tpage = maxPage;\n\t\t}\n\t}\n\n\tpublic void add(int i) {\n\t\tint requestCount = requestCountBar.getInteger();\n\t\tif (i != 1 && requestCount == 1) {\n\t\t\trequestCount -= 1;\n\t\t}\n\t\trequestCountBar.setInteger(requestCount + getAmountChangeMode(i));\n\t}\n\n\tpublic void sub(int i) {\n\t\trequestCountBar.setInteger(requestCountBar.getInteger() - getAmountChangeMode(i));\n\t}\n\n\tpublic ItemIdentifierStack getSelectedItem() {\n\t\treturn selectedItem;\n\t}\n\n\tpublic int getRequestCount() {\n\t\treturn requestCountBar.getInteger();\n\t}\n\n\tpublic boolean handleClick(int x, int y, int k) {\n\t\tif (requestCountBar.handleClick(x, y, k)) {\n\t\t\treturn true;\n\t\t}\n\t\tx -= left;\n\t\ty -= top;\n\t\tif (x < 0 || y < 0 || x > width || y > height) {\n\t\t\treturn false;\n\t\t}\n\t\tselectedItem = null;\n\t\tfor (Entry<Pair<Integer, Integer>, ItemIdentifierStack> entry : map.entrySet()) {\n\t\t\tif (x >= entry.getKey().getValue1() && x < entry.getKey().getValue1() + ItemDisplay.PANELSIZEX && y >= entry.getKey().getValue2() && y < entry.getKey().getValue2() + ItemDisplay.PANELSIZEY) {\n\t\t\t\tselectedItem = entry.getValue();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic boolean keyTyped(char c, int i) {\n\t\tif (!requestCountBar.handleKey(c, i)) {\n\t\t\tif (i == 30 && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { //Ctrl-a\n\t\t\t\tsetMaxAmount();\n\t\t\t\treturn true;\n\t\t\t} else if (i == 32 && Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { //Ctrl-d\n\t\t\t\tresetAmount();\n\t\t\t\treturn true;\n\t\t\t} else if (i == 201) { //PgUp\n\t\t\t\tprevPage();\n\t\t\t\treturn true;\n\t\t\t} else if (i == 209) { //PgDn\n\t\t\t\tnextPage();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\tpublic void setFocused(boolean value) {\n\t\trequestCountBar.setFocused(value);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/LogisticsBaseGuiScreen.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.gui;\n\nimport java.awt.Rectangle;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.Queue;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.inventory.ClickType;\nimport net.minecraft.inventory.Container;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.text.TextFormatting;\n\nimport codechicken.nei.api.INEIGuiHandler;\nimport codechicken.nei.api.TaggedInventoryArea;\nimport lombok.Getter;\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.LPConstants;\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.asm.ModDependentInterface;\nimport logisticspipes.asm.ModDependentMethod;\nimport logisticspipes.interfaces.IChainAddList;\nimport logisticspipes.interfaces.IFuzzySlot;\nimport logisticspipes.network.PacketHandler;\nimport logisticspipes.network.packets.gui.DummyContainerSlotClick;\nimport logisticspipes.network.packets.gui.FuzzySlotSettingsPacket;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.ChainAddArrayList;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.extension.GuiExtensionController;\nimport logisticspipes.utils.gui.extension.GuiExtensionController.GuiSide;\nimport network.rs485.logisticspipes.property.IBitSet;\nimport network.rs485.logisticspipes.util.FuzzyFlag;\nimport network.rs485.logisticspipes.util.FuzzyUtil;\nimport network.rs485.logisticspipes.util.TextUtil;\n\n@ModDependentInterface(modId = { LPConstants.neiModID }, interfacePath = { \"codechicken.nei.api.INEIGuiHandler\" })\npublic abstract class LogisticsBaseGuiScreen extends GuiContainer implements ISubGuiControler, INEIGuiHandler, IGuiAccess {\n\n\tprotected static final ResourceLocation ITEMSINK = new ResourceLocation(\"logisticspipes\", \"textures/gui/itemsink.png\");\n\n\t@Getter\n\tprotected int right;\n\t@Getter\n\tprotected int bottom;\n\tprotected int xCenter;\n\tprotected int yCenter;\n\tprotected final int xCenterOffset;\n\tprotected final int yCenterOffset;\n\n\tprivate SubGuiScreen subGui;\n\tprotected List<IRenderSlot> slots = new ArrayList<>();\n\tprotected GuiExtensionController extensionControllerLeft = new GuiExtensionController(GuiSide.LEFT);\n\tprotected GuiExtensionController extensionControllerRight = new GuiExtensionController(GuiSide.RIGHT);\n\tprivate GuiButton selectedButton;\n\n\tprivate int currentDrawScreenMouseX;\n\tprivate int currentDrawScreenMouseY;\n\n\tprivate IFuzzySlot fuzzySlot;\n\tprivate boolean fuzzySlotActiveGui;\n\tprivate int fuzzySlotGuiHoverTime;\n\tprivate Queue<Runnable> renderAtTheEnd = new LinkedList<>();\n\n\tpublic LogisticsBaseGuiScreen(int xSize, int ySize, int xCenterOffset, int yCenterOffset) {\n\t\tthis(new DummyContainer(null, null), xSize, ySize, xCenterOffset, yCenterOffset);\n\t}\n\n\tpublic LogisticsBaseGuiScreen(Container container) {\n\t\tsuper(container);\n\t\txCenterOffset = 0;\n\t\tyCenterOffset = 0;\n\t}\n\n\tpublic LogisticsBaseGuiScreen(Container container, int xSize, int ySize, int xCenterOffset, int yCenterOffset) {\n\t\tsuper(container);\n\t\tthis.xSize = xSize;\n\t\tthis.ySize = ySize;\n\t\tthis.xCenterOffset = xCenterOffset;\n\t\tthis.yCenterOffset = yCenterOffset;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tguiLeft = width / 2 - xSize / 2 + xCenterOffset;\n\t\tguiTop = height / 2 - ySize / 2 + yCenterOffset;\n\n\t\tright = width / 2 + xSize / 2 + xCenterOffset;\n\t\tbottom = height / 2 + ySize / 2 + yCenterOffset;\n\n\t\txCenter = (right + guiLeft) / 2;\n\t\tyCenter = (bottom + guiTop) / 2;\n\t\textensionControllerLeft.setMaxBottom(bottom);\n\t\textensionControllerRight.setMaxBottom(bottom);\n\t}\n\n\t@Override\n\tpublic boolean hasSubGui() {\n\t\treturn subGui != null;\n\t}\n\n\t@Override\n\tpublic SubGuiScreen getSubGui() {\n\t\treturn subGui;\n\t}\n\n\t@Override\n\tpublic void setSubGui(SubGuiScreen gui) {\n\t\tif (subGui == null) {\n\t\t\tsubGui = gui;\n\t\t\tsubGui.register(this);\n\t\t\tsubGui.setWorldAndResolution(mc, width, height);\n\t\t\tsubGui.initGui();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setWorldAndResolution(Minecraft mc, int width, int height) {\n\t\tsuper.setWorldAndResolution(mc, width, height);\n\t\tif (subGui != null) {\n\t\t\tsubGui.setWorldAndResolution(mc, width, height);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void resetSubGui() {\n\t\tsubGui = null;\n\t}\n\n\t@Override\n\tpublic void drawDefaultBackground() {\n\t\tif (subGui == null) {\n\t\t\tsuper.drawDefaultBackground();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void drawScreen(int mouseX, int mouseY, float partialTicks) {\n\t\tcurrentDrawScreenMouseX = mouseX;\n\t\tcurrentDrawScreenMouseY = mouseY;\n\t\tcheckButtons();\n\t\tif (subGui != null) {\n\t\t\t//Save Mouse Pos\n\t\t\tint x = Mouse.getX();\n\t\t\tint y = Mouse.getY();\n\t\t\t//Set Pos 0,0\n\t\t\ttry {\n\t\t\t\tField fX = Mouse.class.getDeclaredField(\"x\");\n\t\t\t\tField fY = Mouse.class.getDeclaredField(\"y\");\n\t\t\t\tfX.setAccessible(true);\n\t\t\t\tfY.setAccessible(true);\n\t\t\t\tfX.set(null, 0);\n\t\t\t\tfY.set(null, 0);\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t\t//Draw super class (maybe NEI)\n\t\t\tsuper.drawScreen(0, 0, partialTicks);\n\t\t\t//Resore Mouse Pos\n\t\t\ttry {\n\t\t\t\tField fX = Mouse.class.getDeclaredField(\"x\");\n\t\t\t\tField fY = Mouse.class.getDeclaredField(\"y\");\n\t\t\t\tfX.setAccessible(true);\n\t\t\t\tfY.setAccessible(true);\n\t\t\t\tfX.set(null, x);\n\t\t\t\tfY.set(null, y);\n\t\t\t} catch (Exception e) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t\tGL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\tif (!subGui.hasSubGui()) {\n\t\t\t\tGL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\t\tsuper.drawDefaultBackground();\n\t\t\t}\n\t\t\tGL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\tsubGui.drawScreen(mouseX, mouseY, partialTicks);\n\t\t\tGL11.glPopAttrib();\n\t\t} else {\n\t\t\tdrawDefaultBackground();\n\t\t\tsuper.drawScreen(mouseX, mouseY, partialTicks);\n\t\t\tRenderHelper.disableStandardItemLighting();\n\t\t\tfor (IRenderSlot slot : slots) {\n\t\t\t\tint localMouseX = mouseX - guiLeft;\n\t\t\t\tint localMouseY = mouseY - guiTop;\n\t\t\t\tint mouseXMax = localMouseX - slot.getSize();\n\t\t\t\tint mouseYMax = localMouseY - slot.getSize();\n\t\t\t\tif (slot.getXPos() < localMouseX && slot.getXPos() > mouseXMax && slot.getYPos() < localMouseY && slot.getYPos() > mouseYMax) {\n\t\t\t\t\tif (slot.displayToolTip()) {\n\t\t\t\t\t\tif (slot.getToolTipText() != null && !slot.getToolTipText().equals(\"\")) {\n\t\t\t\t\t\t\tArrayList<String> list = new ArrayList<>();\n\t\t\t\t\t\t\tlist.add(slot.getToolTipText());\n\t\t\t\t\t\t\tGuiGraphics.drawToolTip(mouseX, mouseY, list, TextFormatting.WHITE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.renderHoveredToolTip(mouseX, mouseY);\n\t\t\tRenderHelper.enableStandardItemLighting();\n\t\t}\n\t\tRunnable run = renderAtTheEnd.poll();\n\t\twhile (run != null) {\n\t\t\trun.run();\n\t\t\trun = renderAtTheEnd.poll();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int i, int j) {\n\t\trenderExtensions();\n\t}\n\n\tprotected void renderExtensions() {\n\t\textensionControllerLeft.render(guiLeft, guiTop);\n\t\textensionControllerRight.render(guiLeft + xSize, guiTop);\n\t}\n\n\t@Override\n\tprotected void drawSlot(Slot slot) {\n\t\tif (extensionControllerLeft.renderSlot(slot) && extensionControllerRight.renderSlot(slot)) {\n\t\t\tif (subGui == null) {\n\t\t\t\tonRenderSlot(slot);\n\t\t\t}\n\t\t\tsuper.drawSlot(slot);\n\t\t}\n\t}\n\n\tprivate void onRenderSlot(Slot slot) {\n\t\tif (slot instanceof IFuzzySlot) {\n\t\t\tfinal IBitSet set = ((IFuzzySlot) slot).getFuzzyFlags();\n\t\t\tint x1 = slot.xPos;\n\t\t\tint y1 = slot.yPos;\n\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\tfinal boolean useOreDict = FuzzyUtil.INSTANCE.get(set, FuzzyFlag.USE_ORE_DICT);\n\t\t\tif (useOreDict) {\n\t\t\t\tGui.drawRect(x1 + 8, y1 - 1, x1 + 17, y1, 0xFFFF4040);\n\t\t\t\tGui.drawRect(x1 + 16, y1, x1 + 17, y1 + 8, 0xFFFF4040);\n\t\t\t}\n\t\t\tfinal boolean ignoreDamage = FuzzyUtil.INSTANCE.get(set, FuzzyFlag.IGNORE_DAMAGE);\n\t\t\tif (ignoreDamage) {\n\t\t\t\tGui.drawRect(x1 - 1, y1 - 1, x1 + 8, y1, 0xFF40FF40);\n\t\t\t\tGui.drawRect(x1 - 1, y1, x1, y1 + 8, 0xFF40FF40);\n\t\t\t}\n\t\t\tfinal boolean ignoreNBT = FuzzyUtil.INSTANCE.get(set, FuzzyFlag.IGNORE_NBT);\n\t\t\tif (ignoreNBT) {\n\t\t\t\tGui.drawRect(x1 - 1, y1 + 16, x1 + 8, y1 + 17, 0xFF4040FF);\n\t\t\t\tGui.drawRect(x1 - 1, y1 + 8, x1, y1 + 17, 0xFF4040FF);\n\t\t\t}\n\t\t\tfinal boolean useOreCategory = FuzzyUtil.INSTANCE.get(set, FuzzyFlag.USE_ORE_CATEGORY);\n\t\t\tif (useOreCategory) {\n\t\t\t\tGui.drawRect(x1 + 8, y1 + 16, x1 + 17, y1 + 17, 0xFF7F7F40);\n\t\t\t\tGui.drawRect(x1 + 16, y1 + 8, x1 + 17, y1 + 17, 0xFF7F7F40);\n\t\t\t}\n\t\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\tfinal boolean mouseOver = this.isMouseOverSlot(slot, currentDrawScreenMouseX, currentDrawScreenMouseY);\n\t\t\tif (mouseOver) {\n\t\t\t\tif (fuzzySlot == slot) {\n\t\t\t\t\tfuzzySlotGuiHoverTime++;\n\t\t\t\t\tif (fuzzySlotGuiHoverTime >= 10) {\n\t\t\t\t\t\tfuzzySlotActiveGui = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfuzzySlot = (IFuzzySlot) slot;\n\t\t\t\t\tfuzzySlotGuiHoverTime = 0;\n\t\t\t\t\tfuzzySlotActiveGui = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (fuzzySlotActiveGui && fuzzySlot == slot) {\n\t\t\t\tif (!mouseOver) {\n\t\t\t\t\t//Check within FuzzyGui\n\t\t\t\t\tif (!isPointInRegion(slot.xPos, slot.yPos + 16, 60, 52, currentDrawScreenMouseX, currentDrawScreenMouseY)) {\n\t\t\t\t\t\tfuzzySlotActiveGui = false;\n\t\t\t\t\t\tfuzzySlot = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfinal int posX = slot.xPos + guiLeft;\n\t\t\t\tfinal int posY = slot.yPos + 17 + guiTop;\n\t\t\t\trenderAtTheEnd.add(() -> {\n\t\t\t\t\tGL11.glDisable(GL11.GL_DEPTH_TEST);\n\t\t\t\t\tGL11.glDisable(GL11.GL_LIGHTING);\n\t\t\t\t\tGuiGraphics.drawGuiBackGround(mc, posX, posY, posX + 61, posY + 47, zLevel, true, true, true, true, true);\n\t\t\t\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\t\t\t\tfinal String PREFIX = \"gui.crafting.\";\n\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(PREFIX + \"OreDict\"), posX + 5, posY + 5,\n\t\t\t\t\t\t\t(useOreDict ? 0xFF4040 : 0x404040));\n\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(PREFIX + \"IgnDamage\"), posX + 5, posY + 15,\n\t\t\t\t\t\t\t(ignoreDamage ? 0x40FF40 : 0x404040));\n\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(PREFIX + \"IgnNBT\"), posX + 5, posY + 25,\n\t\t\t\t\t\t\t(ignoreNBT ? 0x4040FF : 0x404040));\n\t\t\t\t\tmc.fontRenderer.drawString(TextUtil.translate(PREFIX + \"OrePrefix\"), posX + 5, posY + 35,\n\t\t\t\t\t\t\t(useOreCategory ? 0x7F7F40 : 0x404040));\n\t\t\t\t\tGL11.glEnable(GL11.GL_LIGHTING);\n\t\t\t\t\tGL11.glEnable(GL11.GL_DEPTH_TEST);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected boolean isMouseOverSlot(Slot par1Slot, int par2, int par3) {\n\t\tif (!extensionControllerLeft.renderSelectSlot(par1Slot)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!extensionControllerRight.renderSelectSlot(par1Slot)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (isMouseInFuzzyPanel(currentDrawScreenMouseX, currentDrawScreenMouseY)) return false;\n\t\treturn super.isMouseOverSlot(par1Slot, par2, par3);\n\t}\n\n\tprivate boolean isMouseInFuzzyPanel(int x, int y) {\n\t\tif (!fuzzySlotActiveGui || fuzzySlot == null) return false;\n\t\treturn isPointInRegion(fuzzySlot.getX(), fuzzySlot.getY() + 16, 60, 52, x, y);\n\t}\n\n\tprotected void checkButtons() {\n\t\tfor (GuiButton button : buttonList) {\n\t\t\tif (extensionControllerLeft.renderButtonControlled(button)) {\n\t\t\t\tbutton.visible = extensionControllerLeft.renderButton(button);\n\t\t\t}\n\t\t\tif (extensionControllerRight.renderButtonControlled(button)) {\n\t\t\t\tbutton.visible = extensionControllerRight.renderButton(button);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Nonnull\n\tpublic <T extends GuiButton> T addButton(@Nonnull T button) {\n\t\tbuttonList.add(button);\n\t\treturn button;\n\t}\n\n\t@Override\n\tpublic final void handleMouseInput() throws IOException {\n\t\tif (subGui != null) {\n\t\t\tsubGui.handleMouseInput();\n\t\t} else {\n\t\t\thandleMouseInputSub();\n\t\t}\n\t}\n\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tsuper.handleMouseInput();\n\t\tint x = Mouse.getEventX() * this.width / this.mc.displayWidth;\n\t\tint y = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;\n\t\tint dWheel = Mouse.getEventDWheel();\n\t\tif (dWheel != 0 && !mouseHandled) {\n\t\t\tOptional<DummySlot> slotOpt = this.inventorySlots.inventorySlots.stream().filter(it -> it instanceof DummySlot).map(it -> (DummySlot) it).filter(it -> isMouseOverSlot(it, x, y)).findFirst();\n\t\t\tif (slotOpt.isPresent()) {\n\t\t\t\tDummySlot slot = slotOpt.get();\n\t\t\t\tslot.setRedirectCall(true);\n\t\t\t\tif (slot.getSlotStackLimit() > 0 && slot.getHasStack()) {\n\t\t\t\t\tint buttonActionID = dWheel > 0 ? 1000 : 1001;\n\t\t\t\t\tthis.mc.playerController.windowClick(this.inventorySlots.windowId, slot.slotNumber, buttonActionID, ClickType.SWAP, this.mc.player);\n\t\t\t\t}\n\t\t\t\tslot.setRedirectCall(false);\n\t\t\t\tmouseHandled = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void handleKeyboardInput() throws IOException {\n\t\tif (subGui != null) {\n\t\t\tsubGui.handleKeyboardInput();\n\t\t} else {\n\t\t\tsuper.handleKeyboardInput();\n\t\t}\n\t\tfor (EventListener el : onGuiEvents)\n\t\t\tkeyHandled |= el.onKeyboardInput();\n\t}\n\n\tpublic void addRenderSlot(IRenderSlot slot) {\n\t\tslots.add(slot);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tif (par1 < guiLeft) {\n\t\t\textensionControllerLeft.mouseOver(par1, par2);\n\t\t}\n\t\tif (par1 > guiLeft + xSize) {\n\t\t\textensionControllerRight.mouseOver(par1, par2);\n\t\t}\n\t\tfor (IRenderSlot slot : slots) {\n\t\t\tif (slot instanceof IItemTextureRenderSlot) {\n\t\t\t\tif (slot.drawSlotBackground()) {\n\t\t\t\t\tGuiGraphics.drawSlotBackground(mc, slot.getXPos(), slot.getYPos());\n\t\t\t\t}\n\t\t\t\tif (((IItemTextureRenderSlot) slot).drawSlotIcon() && !((IItemTextureRenderSlot) slot).customRender(mc, zLevel)) {\n\t\t\t\t\tGuiGraphics.renderIconAt(mc, slot.getXPos() + 1, slot.getYPos() + 1, zLevel, ((IItemTextureRenderSlot) slot).getTextureIcon());\n\t\t\t\t}\n\t\t\t} else if (slot instanceof ISmallColorRenderSlot) {\n\t\t\t\tif (slot.drawSlotBackground()) {\n\t\t\t\t\tGuiGraphics.drawSmallSlotBackground(mc, slot.getXPos(), slot.getYPos());\n\t\t\t\t}\n\t\t\t\tif (((ISmallColorRenderSlot) slot).drawColor()) {\n\t\t\t\t\tGui.drawRect(slot.getXPos() + 1, slot.getYPos() + 1, slot.getXPos() + 7, slot.getYPos() + 7, ((ISmallColorRenderSlot) slot).getColor());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int par1, int par2, int par3) throws IOException {\n\t\tfor (IRenderSlot slot : slots) {\n\t\t\tint mouseX = par1 - guiLeft;\n\t\t\tint mouseY = par2 - guiTop;\n\t\t\tint mouseXMax = mouseX - slot.getSize();\n\t\t\tint mouseYMax = mouseY - slot.getSize();\n\t\t\tif (slot.getXPos() < mouseX && slot.getXPos() > mouseXMax && slot.getYPos() < mouseY && slot.getYPos() > mouseYMax) {\n\t\t\t\tslot.mouseClicked(par3);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (isMouseInFuzzyPanel(par1, par2)) {\n\t\t\tfinal int posX = fuzzySlot.getX() + guiLeft;\n\t\t\tfinal int posY = fuzzySlot.getY() + 17 + guiTop;\n\t\t\tint sel = -1;\n\t\t\tif (par1 >= posX + 5 && par1 <= posX + 56) {\n\t\t\t\tif (par2 >= posY + 5 && par2 <= posY + 45) {\n\t\t\t\t\tsel = (par2 - posY - 4) / 10;\n\t\t\t\t}\n\t\t\t}\n\t\t\tIBitSet set = fuzzySlot.getFuzzyFlags();\n\t\t\tFuzzyFlag flag = null;\n\t\t\tswitch (sel) {\n\t\t\t\tcase 0:\n\t\t\t\t\tflag = FuzzyFlag.USE_ORE_DICT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 1:\n\t\t\t\t\tflag = FuzzyFlag.IGNORE_DAMAGE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tflag = FuzzyFlag.IGNORE_NBT;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:\n\t\t\t\t\tflag = FuzzyFlag.USE_ORE_CATEGORY;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (flag == null) return;\n\t\t\tset.flip(flag.getBit());\n\t\t\tMainProxy.sendPacketToServer(\n\t\t\t\t\tPacketHandler.getPacket(FuzzySlotSettingsPacket.class)\n\t\t\t\t\t\t\t.setSlotNumber(fuzzySlot.getSlotId())\n\t\t\t\t\t\t\t.setFlags(set.copyValue()));\n\t\t\treturn;\n\t\t}\n\t\tboolean handledButton = false;\n\t\tif (par3 == 0) {\n\t\t\tfor (Object aButtonList : buttonList) {\n\t\t\t\tGuiButton guibutton = (GuiButton) aButtonList;\n\t\t\t\tif (guibutton.mousePressed(mc, par1, par2)) {\n\t\t\t\t\tselectedButton = guibutton;\n\t\t\t\t\tguibutton.playPressSound(mc.getSoundHandler());\n\t\t\t\t\tactionPerformed(guibutton);\n\t\t\t\t\thandledButton = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (!handledButton) {\n\t\t\tsuper.mouseClicked(par1, par2, par3);\n\t\t}\n\t\tif (par3 == 0 && par1 < guiLeft && !mouseCanPressButton(par1, par2) && !isOverSlot(par1, par2)) {\n\t\t\textensionControllerLeft.mouseClicked(par1, par2, par3);\n\t\t}\n\t\tif (par3 == 0 && par1 > guiLeft + xSize && !mouseCanPressButton(par1, par2) && !isOverSlot(par1, par2)) {\n\t\t\textensionControllerRight.mouseClicked(par1, par2, par3);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void mouseReleased(int par1, int par2, int par3) {\n\t\tif (selectedButton != null && par3 == 0) {\n\t\t\tselectedButton.mouseReleased(par1, par2);\n\t\t\tselectedButton = null;\n\t\t} else if (isMouseInFuzzyPanel(par1 - guiLeft, par2 - guiTop)) {\n\t\t} else {\n\t\t\tsuper.mouseReleased(par1, par2, par3);\n\t\t}\n\t}\n\n\tprivate boolean mouseCanPressButton(int par1, int par2) {\n\t\tfor (Object aButtonList : buttonList) {\n\t\t\tGuiButton guibutton = (GuiButton) aButtonList;\n\t\t\tif (guibutton.mousePressed(mc, par1, par2)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean isOverSlot(int par1, int par2) {\n\t\tfor (int k = 0; k < inventorySlots.inventorySlots.size(); ++k) {\n\t\t\tSlot slot = inventorySlots.inventorySlots.get(k);\n\t\t\tif (isMouseOverSlot(slot, par1, par2)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void drawPoint(int x, int y, int color) {\n\t\tGui.drawRect(x, y, x + 1, y + 1, color);\n\t}\n\n\tpublic void drawPoint(int x, int y, Color color) {\n\t\tGui.drawRect(x, y, x + 1, y + 1, Color.getValue(color));\n\t}\n\n\tpublic void drawRect(int x1, int y1, int x2, int y2, Color color) {\n\t\tGui.drawRect(x1, y1, x2, y2, Color.getValue(color));\n\t}\n\n\tpublic void drawLine(int x1, int y1, int x2, int y2, Color color) {\n\t\tint lasty = y1;\n\t\tfor (int dx = 0; x1 + dx < x2; dx++) {\n\t\t\tint plotx = x1 + dx;\n\t\t\tint ploty;\n\n\t\t\tif (x2 - x1 == 1) ploty = y1 + (y2 - y1) / (x2 - x1) * dx;\n\t\t\telse ploty = y1 + (y2 - y1) / (x2 - x1 - 1) * dx;\n\n\t\t\tdrawPoint(plotx, ploty, color);\n\t\t\twhile (lasty < ploty) {\n\t\t\t\tdrawPoint(plotx, ++lasty, color);\n\t\t\t}\n\t\t\twhile (lasty > ploty) {\n\t\t\t\tdrawPoint(plotx, --lasty, color);\n\t\t\t}\n\t\t}\n\t\twhile (lasty < y2) {\n\t\t\tdrawPoint(x2, ++lasty, color);\n\t\t}\n\t\twhile (lasty > y2) {\n\t\t\tdrawPoint(x2, --lasty, color);\n\t\t}\n\t}\n\n\tpublic void closeGui() throws IOException {\n\t\tkeyTyped(' ', 1);\n\t}\n\n\t@Override\n\tpublic Minecraft getMC() {\n\t\treturn mc;\n\t}\n\n\t@Override\n\tpublic LogisticsBaseGuiScreen getBaseScreen() {\n\t\treturn this;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.neiModID)\n\tpublic List<TaggedInventoryArea> getInventoryAreas(GuiContainer gui) {\n\t\treturn null;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.neiModID)\n\tpublic Iterable<Integer> getItemSpawnSlots(GuiContainer gui, @Nonnull ItemStack stack) {\n\t\treturn null;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.neiModID)\n\tpublic boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, @Nonnull ItemStack stack, int button) {\n\t\tif (gui instanceof LogisticsBaseGuiScreen && gui.inventorySlots instanceof DummyContainer && !stack.isEmpty()) {\n\t\t\tSlot result = null;\n\t\t\tint pos = -1;\n\t\t\tfor (int k = 0; k < inventorySlots.inventorySlots.size(); ++k) {\n\t\t\t\tSlot slot = inventorySlots.inventorySlots.get(k);\n\t\t\t\tif (isMouseOverSlot(slot, mouseX, mouseY)) {\n\t\t\t\t\tresult = slot;\n\t\t\t\t\tpos = k;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (result != null) {\n\t\t\t\tif (result instanceof DummySlot || result instanceof ColorSlot || result instanceof FluidSlot) {\n\t\t\t\t\t((DummyContainer) gui.inventorySlots).handleDummyClick(result, pos, stack, button, ClickType.PICKUP, mc.player);\n\t\t\t\t\tMainProxy.sendPacketToServer(PacketHandler.getPacket(DummyContainerSlotClick.class).setSlotId(pos).setStack(stack).setButton(button));\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\t@ModDependentMethod(modId = LPConstants.neiModID)\n\tpublic boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {\n\t\tif (gui instanceof LogisticsBaseGuiScreen) {\n\t\t\treturn ((LogisticsBaseGuiScreen) gui).extensionControllerRight.isOverPanel(x, y, w, h);\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic IChainAddList<EventListener> onGuiEvents = new ChainAddArrayList<>();\n\n\tpublic List<Rectangle> getGuiExtraAreas() {\n\t\treturn Stream.concat(\n\t\t\textensionControllerLeft.getGuiExtraAreas().stream(), extensionControllerRight.getGuiExtraAreas().stream()).collect(Collectors.toList());\n\t}\n\n\tpublic interface EventListener {\n\n\t\tvoid onUpdateScreen();\n\n\t\tboolean onKeyboardInput();\n\n\t}\n\n\tpublic void updateScreen() {\n\t\tfor (EventListener el : onGuiEvents)\n\t\t\tel.onUpdateScreen();\n\t}\n\n\tpublic void drawCenteredString(String text, int x, int y, int color) {\n\t\tint actualX = x - mc.fontRenderer.getStringWidth(text) / 2;\n\t\tmc.fontRenderer.drawString(text, actualX, y, color);\n\t}\n\n\t@Deprecated\n\tpublic static void drawHorizontalGradientRect(int left, int top, int right, int bottom, int z, int colorLeft, int colorRight){\n\t\tfloat aL = (float)(colorLeft >> 24 & 255) / 255.0F;\n\t\tfloat rL = (float)(colorLeft >> 16 & 255) / 255.0F;\n\t\tfloat gL = (float)(colorLeft >> 8 & 255) / 255.0F;\n\t\tfloat bL = (float)(colorLeft & 255) / 255.0F;\n\t\tfloat aR = (float)(colorRight >> 24 & 255) / 255.0F;\n\t\tfloat rR = (float)(colorRight >> 16 & 255) / 255.0F;\n\t\tfloat gR = (float)(colorRight >> 8 & 255) / 255.0F;\n\t\tfloat bR = (float)(colorRight & 255) / 255.0F;\n\t\tGlStateManager.disableTexture2D();\n\t\tGlStateManager.enableBlend();\n\t\tGlStateManager.disableAlpha();\n\t\tGlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);\n\t\tGlStateManager.shadeModel(7425);\n\t\tTessellator tessellator = Tessellator.getInstance();\n\t\tBufferBuilder bufferbuilder = tessellator.getBuffer();\n\t\tbufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR);\n\t\tbufferbuilder.pos((double)right, (double)top, (double)z).color(rR, gR, bR, aR).endVertex();\n\t\tbufferbuilder.pos((double)left, (double)top, (double)z).color(rL, gL, bL, aL).endVertex();\n\t\tbufferbuilder.pos((double)left, (double)bottom, (double)z).color(rL, gL, bL, aL).endVertex();\n\t\tbufferbuilder.pos((double)right, (double)bottom, (double)z).color(rR, gR, bR, aR).endVertex();\n\t\ttessellator.draw();\n\t\tGlStateManager.shadeModel(7424);\n\t\tGlStateManager.disableBlend();\n\t\tGlStateManager.enableAlpha();\n\t\tGlStateManager.enableTexture2D();\n\t}\n\n\t@Deprecated\n\tpublic static void drawVerticalGradientRect(int left, int top, int right, int bottom, int z, int colorTop, int colorBottom){\n\t\tfloat aT = (float)(colorTop >> 24 & 255) / 255.0F;\n\t\tfloat rT = (float)(colorTop >> 16 & 255) / 255.0F;\n\t\tfloat gT = (float)(colorTop >> 8 & 255) / 255.0F;\n\t\tfloat bT = (float)(colorTop & 255) / 255.0F;\n\t\tfloat aB = (float)(colorBottom >> 24 & 255) / 255.0F;\n\t\tfloat rB = (float)(colorBottom >> 16 & 255) / 255.0F;\n\t\tfloat gB = (float)(colorBottom >> 8 & 255) / 255.0F;\n\t\tfloat bB = (float)(colorBottom & 255) / 255.0F;\n\t\tGlStateManager.disableTexture2D();\n\t\tGlStateManager.enableBlend();\n\t\tGlStateManager.disableAlpha();\n\t\tGlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);\n\t\tGlStateManager.shadeModel(7425);\n\t\tTessellator tessellator = Tessellator.getInstance();\n\t\tBufferBuilder bufferbuilder = tessellator.getBuffer();\n\t\tbufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR);\n\t\tbufferbuilder.pos((double)right, (double)top, (double)z).color(rT, gT, bT, aT).endVertex();\n\t\tbufferbuilder.pos((double)left, (double)top, (double)z).color(rT, gT, bT, aT).endVertex();\n\t\tbufferbuilder.pos((double)left, (double)bottom, (double)z).color(rB, gB, bB, aB).endVertex();\n\t\tbufferbuilder.pos((double)right, (double)bottom, (double)z).color(rB, gB, bB, aB).endVertex();\n\t\ttessellator.draw();\n\t\tGlStateManager.shadeModel(7424);\n\t\tGlStateManager.disableBlend();\n\t\tGlStateManager.enableAlpha();\n\t\tGlStateManager.enableTexture2D();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/LogisticsBaseTabGuiScreen.java",
    "content": "package logisticspipes.utils.gui;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.Slot;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.opengl.GL11;\n\npublic class LogisticsBaseTabGuiScreen extends LogisticsBaseGuiScreen {\n\n\tprivate int current_Tab;\n\n\tprivate int buttonNextFreeId = 0;\n\n\tprivate final List<TabSubGui> tabList = new ArrayList<>();\n\tprivate final List<Slot> hiddenSlots = new ArrayList<>();\n\n\tpublic LogisticsBaseTabGuiScreen(int xSize, int ySize) {\n\t\tsuper(xSize, ySize, 0, 0);\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tbuttonList.clear();\n\t\ttabList.forEach(TabSubGui::initTab);\n\t}\n\n\t@Override\n\tpublic void closeGui() throws IOException {\n\t\tsuper.closeGui();\n\t\tKeyboard.enableRepeatEvents(false);\n\t\tinitGui();\n\t}\n\n\tprotected int getFreeButtonId() {\n\t\treturn buttonNextFreeId++;\n\t}\n\n\t@Override\n\tprotected void actionPerformed(GuiButton button) {\n\t\ttabList.stream().filter(aTabList -> aTabList.isButtonFromGui(button)).forEach(aTabList -> aTabList.buttonClicked(button));\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int mouse_x, int mouse_y) {\n\t\tGL11.glColor4d(1.0D, 1.0D, 1.0D, 1.0D);\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft + (25 * i) + 2, guiTop - 2, guiLeft + 27 + (25 * i), guiTop + 35, zLevel, false, true, true, false, true);\n\t\t}\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft, guiTop + 20, right, bottom, zLevel, true);\n\t\tGuiGraphics.drawGuiBackGround(mc, guiLeft + (25 * current_Tab) + 2, guiTop - 2, guiLeft + 27 + (25 * current_Tab), guiTop + 38, zLevel, true, true, true, false, true);\n\t\tGuiGraphics.drawPlayerInventoryBackground(mc, guiLeft + 10, guiTop + 135);\n\n\t\tint x = 6;\n\t\tfor (TabSubGui aTabList : tabList) {\n\t\t\taTabList.renderIcon(guiLeft + x, guiTop + 3);\n\t\t\tx += 25;\n\t\t}\n\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tif (current_Tab == i) {\n\t\t\t\ttabList.get(i).renderBackgroundContent();\n\t\t\t}\n\t\t}\n\n\t\tsuper.drawGuiContainerBackgroundLayer(f, mouse_x, mouse_y);\n\t}\n\n\t@Override\n\tprotected void mouseClicked(int par1, int par2, int par3) throws IOException {\n\t\tif (par3 == 0 && par1 > guiLeft && par1 < guiLeft + 220 && par2 > guiTop && par2 < guiTop + 20) {\n\t\t\tpar1 -= guiLeft + 3;\n\t\t\tint select = Math.max(0, Math.min(par1 / 25, tabList.size() - 1));\n\t\t\tif (current_Tab != select) {\n\t\t\t\ttabList.get(current_Tab).leavingTab();\n\t\t\t\ttabList.get(select).enteringTab();\n\t\t\t}\n\t\t\tcurrent_Tab = select;\n\t\t} else {\n\t\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\t\tif (current_Tab == i) {\n\t\t\t\t\tif (tabList.get(i).handleClick(par1, par2, par3)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsuper.mouseClicked(par1, par2, par3);\n\t\t}\n\t}\n\n\t@Override\n\tprotected void keyTyped(char p_73869_1_, int p_73869_2_) throws IOException {\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tif (current_Tab == i) {\n\t\t\t\tif (tabList.get(i).handleKey(p_73869_2_, p_73869_1_)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (p_73869_2_ == 1 || p_73869_2_ == mc.gameSettings.keyBindInventory.getKeyCode()) {\n\t\t\ttabList.forEach(TabSubGui::guiClose);\n\t\t}\n\t\tsuper.keyTyped(p_73869_1_, p_73869_2_);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerForegroundLayer(int par1, int par2) {\n\t\tsuper.drawGuiContainerForegroundLayer(par1, par2);\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tif (current_Tab == i) {\n\t\t\t\ttabList.get(i).renderForegroundContent();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tprotected void drawSlot(Slot slot) {\n\t\tif (hiddenSlots.contains(slot)) return;\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tif (tabList.get(i).isSlotForTab(slot)) {\n\t\t\t\tif (current_Tab != i || !tabList.get(i).showSlot(slot)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsuper.drawSlot(slot);\n\t}\n\n\t@Override\n\tprotected boolean isMouseOverSlot(Slot slot, int par2, int par3) {\n\t\tif (!super.isMouseOverSlot(slot, par2, par3)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (hiddenSlots.contains(slot)) return false;\n\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\tif (tabList.get(i).isSlotForTab(slot)) {\n\t\t\t\tif (current_Tab != i || !tabList.get(i).showSlot(slot)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tprotected void checkButtons() {\n\t\tsuper.checkButtons();\n\t\tfor (GuiButton button : buttonList) {\n\t\t\tfor (int i = 0; i < tabList.size(); i++) {\n\t\t\t\tif (tabList.get(i).isButtonFromGui(button)) {\n\t\t\t\t\ttabList.get(i).checkButton(button, current_Tab == i);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected void addTab(TabSubGui gui) {\n\t\ttabList.add(gui);\n\t}\n\n\tprotected Slot addHiddenSlot(Slot slot) {\n\t\thiddenSlots.add(slot);\n\t\treturn slot;\n\t}\n\n\tprotected abstract class TabSubGui {\n\n\t\tprivate final List<Slot> TAB_SLOTS = new ArrayList<>();\n\t\tprivate final List<GuiButton> TAB_BUTTONS = new ArrayList<>();\n\n\t\tpublic abstract void renderIcon(int x, int y);\n\n\t\tpublic abstract void renderBackgroundContent();\n\n\t\tpublic abstract void renderForegroundContent();\n\n\t\tpublic boolean isSlotForTab(Slot slot) {\n\t\t\treturn TAB_SLOTS.contains(slot);\n\t\t}\n\n\t\tpublic Slot addSlot(Slot slot) {\n\t\t\tTAB_SLOTS.add(slot);\n\t\t\treturn slot;\n\t\t}\n\n\t\tpublic GuiButton addButton(GuiButton button) {\n\t\t\tTAB_BUTTONS.add(LogisticsBaseTabGuiScreen.this.addButton(button));\n\t\t\treturn button;\n\t\t}\n\n\t\tpublic boolean isButtonFromGui(GuiButton button) {\n\t\t\treturn TAB_BUTTONS.contains(button);\n\t\t}\n\n\t\tpublic void initTab() {}\n\n\t\tpublic void checkButton(GuiButton button, boolean isTabActive) {\n\t\t\tif (TAB_BUTTONS.contains(button)) {\n\t\t\t\tbutton.visible = isTabActive;\n\t\t\t}\n\t\t}\n\n\t\tpublic void buttonClicked(GuiButton button) {}\n\n\t\tpublic boolean handleClick(int x, int y, int type) {\n\t\t\treturn false;\n\t\t}\n\n\t\tpublic boolean handleKey(int code, char c) {\n\t\t\treturn false;\n\t\t}\n\n\t\tpublic void guiClose() {}\n\n\t\tpublic boolean showSlot(Slot slot) {\n\t\t\treturn true;\n\t\t}\n\n\t\tpublic void leavingTab() {}\n\n\t\tpublic void enteringTab() {}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/ModuleSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\n\nimport lombok.Getter;\n\nimport logisticspipes.items.ItemModule;\nimport logisticspipes.logisticspipes.ItemModuleInformationManager;\nimport logisticspipes.pipes.PipeLogisticsChassis;\n\npublic class ModuleSlot extends RestrictedSlot {\n\n\t@Getter\n\tprivate final PipeLogisticsChassis _pipe;\n\t@Getter\n\tprivate final int _moduleIndex;\n\n\tpublic ModuleSlot(IInventory iinventory, int i, int j, int k, PipeLogisticsChassis pipe) {\n\t\tsuper(iinventory, i, j, k, ItemModule.class);\n\t\t_pipe = pipe;\n\t\t_moduleIndex = i;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack onTake(@Nonnull EntityPlayer player, @Nonnull ItemStack itemStack) {\n\t\tItemModuleInformationManager.saveInformation(itemStack, _pipe.getSubModule(_moduleIndex));\n\t\treturn super.onTake(player, itemStack);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/RestrictedSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\n\nimport logisticspipes.interfaces.ISlotCheck;\n\npublic class RestrictedSlot extends Slot {\n\n\tprivate final Item item;\n\tprivate final ISlotCheck slotCheck;\n\n\tpublic RestrictedSlot(IInventory iinventory, int i, int j, int k, Class<? extends Item> itemClass) {\n\t\tsuper(iinventory, i, j, k);\n\t\tthis.item = null;\n\t\tslotCheck = itemStack -> !itemStack.isEmpty() && itemClass.isAssignableFrom(itemStack.getItem().getClass());\n\t}\n\n\tpublic RestrictedSlot(IInventory iinventory, int i, int j, int k, Item item) {\n\t\tsuper(iinventory, i, j, k);\n\t\tthis.item = item;\n\t\tslotCheck = null;\n\t}\n\n\tpublic RestrictedSlot(IInventory iinventory, int i, int j, int k, ISlotCheck slotCheck) {\n\t\tsuper(iinventory, i, j, k);\n\t\titem = null;\n\t\tthis.slotCheck = slotCheck;\n\t}\n\n\t/**\n\t * Check if the stack is a valid item for this slot. Always true beside for\n\t * the armor slots.\n\t */\n\t@Override\n\tpublic boolean isItemValid(@Nonnull ItemStack par1ItemStack) {\n\t\tif (slotCheck == null) {\n\t\t\treturn par1ItemStack.getItem() == item;\n\t\t} else {\n\t\t\treturn slotCheck.isStackAllowed(par1ItemStack);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/SimpleGraphics.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/mc16/LICENSE.md\n */\n\npackage logisticspipes.utils.gui;\n\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.utils.Color;\n\n/**\n * Utils class for simple drawing methods.\n */\n@SuppressWarnings(\"JavadocReference\")\n@SideOnly(Side.CLIENT)\npublic final class SimpleGraphics {\n\n\tprivate SimpleGraphics() {}\n\n\t/**\n\t * Takes colors as enum values from {@link logisticspipes.utils.Color}.\n\t *\n\t * @see #drawHorizontalLine(int, int, int, int, int)\n\t */\n\tpublic static void drawHorizontalLine(int x1, int x2, int y, Color color, int thickness) {\n\t\tSimpleGraphics.drawHorizontalLine(x1, x2, y, Color.getValue(color), thickness);\n\t}\n\n\t/**\n\t * Draws a horizontal line from x1 to x2.\n\t *\n\t * @param x1        the start coordinate\n\t * @param x2        the end coordinate\n\t * @param y         the y-coordinate the line is on\n\t * @param color     the color, which the line will have\n\t * @param thickness the thickness, which the line will have\n\t * @see net.minecraft.client.gui.Gui#drawHorizontalLine(int, int, int, int)\n\t */\n\tpublic static void drawHorizontalLine(int x1, int x2, int y, int color, int thickness) {\n\t\tif (x2 < x1) {\n\t\t\tint temp = x1;\n\t\t\tx1 = x2;\n\t\t\tx2 = temp;\n\t\t}\n\n\t\tGui.drawRect(x1, y, x2 + 1, y + thickness, color);\n\t}\n\n\t/**\n\t * Takes colors as enum values from {@link logisticspipes.utils.Color}.\n\t *\n\t * @see #drawVerticalLine(int, int, int, int, int)\n\t */\n\tpublic static void drawVerticalLine(int x, int y1, int y2, Color color, int thickness) {\n\t\tSimpleGraphics.drawVerticalLine(x, y1, y2, Color.getValue(color), thickness);\n\t}\n\n\t/**\n\t * Draws a vertical line from y1 to y2.\n\t *\n\t * @param x         the x-coordinate the line is on\n\t * @param y1        the start coordinate\n\t * @param y2        the end coordinate\n\t * @param color     the color, which the line will have\n\t * @param thickness the thickness, which the line will have\n\t * @see net.minecraft.client.gui.Gui#drawVerticalLine(int, int, int, int)\n\t */\n\tpublic static void drawVerticalLine(int x, int y1, int y2, int color, int thickness) {\n\t\tif (y2 < y1) {\n\t\t\tint temp = y1;\n\t\t\ty1 = y2;\n\t\t\ty2 = temp;\n\t\t}\n\n\t\tGui.drawRect(x, y1 + 1, x + thickness, y2, color);\n\t}\n\n\t/**\n\t * Takes colors as enum values from {@link logisticspipes.utils.Color}.\n\t *\n\t * @see #drawRectNoBlend(int, int, int, int, int, double)\n\t */\n\tpublic static void drawRectNoBlend(int x1, int y1, int x2, int y2, Color color, double zLevel) {\n\t\tSimpleGraphics.drawRectNoBlend(x1, y1, x2, y2, Color.getValue(color), zLevel);\n\t}\n\n\t/**\n\t * Draws a solid color rectangle with the specified coordinates and color.\n\t * This variation does not use GL_BLEND.\n\t *\n\t * @param x1     the first x-coordinate of the rectangle\n\t * @param y1     the first y-coordinate of the rectangle\n\t * @param x2     the second x-coordinate of the rectangle\n\t * @param y2     the second y-coordinate of the rectangle\n\t * @param color  the color of the rectangle\n\t * @param zLevel the z-level of the graphic\n\t * @see net.minecraft.client.gui.Gui#drawRect(int, int, int, int, int)\n\t */\n\tpublic static void drawRectNoBlend(int x1, int y1, int x2, int y2, int color, double zLevel) {\n\t\tint temp;\n\n\t\tif (x1 < x2) {\n\t\t\ttemp = x1;\n\t\t\tx1 = x2;\n\t\t\tx2 = temp;\n\t\t}\n\n\t\tif (y1 < y2) {\n\t\t\ttemp = y1;\n\t\t\ty1 = y2;\n\t\t\ty2 = temp;\n\t\t}\n\n\t\t// no blend //GlStateManager.enableBlend();\n\t\tGlStateManager.disableTexture2D();\n\t\t// no blend //GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);\n\t\tGL11.glColor4f(Color.getRed(color), Color.getGreen(color), Color.getBlue(color), Color.getAlpha(color));\n\n\t\tTessellator tessellator = Tessellator.getInstance();\n\t\tBufferBuilder buf = tessellator.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);\n\t\tbuf.pos(x1, y2, zLevel).endVertex();\n\t\tbuf.pos(x2, y2, zLevel).endVertex();\n\t\tbuf.pos(x2, y1, zLevel).endVertex();\n\t\tbuf.pos(x1, y1, zLevel).endVertex();\n\t\ttessellator.draw();\n\n\t\tGlStateManager.enableTexture2D();\n\t\t// no blend //GlStateManager.disableBlend();\n\t}\n\n\t/**\n\t * Takes colors as enum values from {@link logisticspipes.utils.Color}.\n\t *\n\t * @see #drawGradientRect(int, int, int, int, int, int, double)\n\t */\n\tpublic static void drawGradientRect(int x1, int y1, int x2, int y2, Color colorA, Color colorB, double zLevel) {\n\t\tSimpleGraphics.drawGradientRect(x1, y1, x2, y2, Color.getValue(colorA), Color.getValue(colorB), zLevel);\n\t}\n\n\t/**\n\t * Draws a rectangle with a vertical gradient between the specified colors.\n\t *\n\t * @param x1     the first x-coordinate of the rectangle\n\t * @param y1     the first y-coordinate of the rectangle\n\t * @param x2     the second x-coordinate of the rectangle\n\t * @param y2     the second y-coordinate of the rectangle\n\t * @param colorA the first color, starting from y1\n\t * @param colorB the second color, ending in y2\n\t * @param zLevel the z-level of the graphic\n\t * @see net.minecraft.client.gui.Gui#drawGradientRect(int, int, int, int, int, int)\n\t */\n\tpublic static void drawGradientRect(int x1, int y1, int x2, int y2, int colorA, int colorB, double zLevel) { // TODO\n\t\tGlStateManager.disableTexture2D();\n\t\tGlStateManager.enableBlend();\n\t\tGlStateManager.disableAlpha();\n\t\tGlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);\n\t\tGlStateManager.shadeModel(7425);\n\n\t\tTessellator tessellator = Tessellator.getInstance();\n\t\tBufferBuilder buf = tessellator.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\tbuf.pos(x2, y1, zLevel).color(Color.getRed(colorA), Color.getGreen(colorA), Color.getBlue(colorA), Color.getAlpha(colorA)).endVertex();\n\t\tbuf.pos(x1, y1, zLevel).color(Color.getRed(colorA), Color.getGreen(colorA), Color.getBlue(colorA), Color.getAlpha(colorA)).endVertex();\n\t\tbuf.pos(x1, y2, zLevel).color(Color.getRed(colorB), Color.getGreen(colorB), Color.getBlue(colorB), Color.getAlpha(colorB)).endVertex();\n\t\tbuf.pos(x2, y2, zLevel).color(Color.getRed(colorB), Color.getGreen(colorB), Color.getBlue(colorB), Color.getAlpha(colorB)).endVertex();\n\t\ttessellator.draw();\n\n\t\tGlStateManager.shadeModel(7424);\n\t\tGlStateManager.disableBlend();\n\t\tGlStateManager.enableAlpha();\n\t\tGlStateManager.enableTexture2D();\n\t}\n\n\t/**\n\t * Draws a textured rectangle.\n\t *\n\t * @param x      the x-coordinate of the rectangle\n\t * @param y      the y-coordinate of the rectangle\n\t * @param u      the u-coordinate of the texture\n\t * @param v      the v-coordinate of the texture\n\t * @param width  the width of the rectangle\n\t * @param height the height of the rectangle\n\t * @param zLevel the z-level of the graphic\n\t * @see net.minecraft.client.gui.Gui#drawTexturedModalRect(int, int, int, int, int, int)\n\t */\n\tpublic static void drawTexturedModalRect(int x, int y, int u, int v, int width, int height, double zLevel) {\n\t\tfloat f = 0.00390625F;\n\t\tfloat f1 = 0.00390625F;\n\n\t\tTessellator tessellator = Tessellator.getInstance();\n\t\tBufferBuilder buf = tessellator.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);\n\t\tbuf.pos(x, y + height, zLevel).tex(u * f, (v + height) * f1);\n\t\tbuf.pos(x + width, y + height, zLevel).tex((u + width) * f, (v + height) * f1);\n\t\tbuf.pos(x + width, y, zLevel).tex((u + width) * f, v * f1);\n\t\tbuf.pos(x, y, zLevel).tex(u * f, v * f1);\n\t\ttessellator.draw();\n\t}\n\n\t/**\n\t * Draws the specified string with a z-translated drop shadow.\n\t *\n\t * @param fontRenderer the font renderer to render the string with\n\t * @param s            the string to render\n\t * @param x            the x-coordinate of the string\n\t * @param y            the y-coordinate of the string\n\t * @param color        the color of the string\n\t * @return the stop x-coordinate of the drawn string\n\t */\n\tpublic static int drawStringWithTranslatedShadow(FontRenderer fontRenderer, String s, int x, int y, int color) {\n\t\tint endX;\n\n\t\t// make color gray-ish and draw shadow\n\t\tint grayColor = (color & 16579836) >> 2 | color & -16777216;\n\t\tendX = fontRenderer.drawString(s, x + 1, y + 1, grayColor);\n\n\t\t// move to foreground and draw actual string\n\t\tGL11.glTranslated(0.0, 0.0, 1.0);\n\t\tendX = Math.max(endX, fontRenderer.drawString(s, x, y, color));\n\t\tGL11.glTranslated(0.0, 0.0, -1.0);\n\n\t\treturn endX;\n\t}\n\n\t/**\n\t * Takes colors as enum values from {@link logisticspipes.utils.Color}.\n\t *\n\t * @see #drawQuad(Tessellator, int, int, int, int, int, double)\n\t */\n\tpublic static void drawQuad(Tessellator tessellator, int x, int y, int width, int height, Color color, double zLevel) {\n\t\tSimpleGraphics.drawQuad(tessellator, x, y, width, height, Color.getValue(color), zLevel);\n\t}\n\n\t/**\n\t * Adds a quad to the tesselator at the specified position with the set\n\t * width and height and color.\n\t *\n\t * @param tessellator the tesselator\n\t * @param x           the x-coordinate of the quad\n\t * @param y           the y-coordinate of the quad\n\t * @param width       the width of the quad\n\t * @param height      the height of the quad\n\t * @param color       the color of the quad\n\t * @param zLevel      the z-level of the quad\n\t */\n\tpublic static void drawQuad(Tessellator tessellator, int x, int y, int width, int height, int color, double zLevel) {\n\t\tBufferBuilder buf = tessellator.getBuffer();\n\t\tbuf.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);\n\t\tfloat a = Color.getAlpha(color);\n\t\tfloat r = Color.getRed(color);\n\t\tfloat g = Color.getGreen(color);\n\t\tfloat b = Color.getBlue(color);\n\t\tbuf.pos(x, y, zLevel)\n\t\t\t\t.color(r, g, b, a)\n\t\t\t\t.endVertex();\n\t\tbuf.pos(x, y + height, zLevel)\n\t\t\t\t.color(r, g, b, a)\n\t\t\t\t.endVertex();\n\t\tbuf.pos(x + width, y + height, zLevel)\n\t\t\t\t.color(r, g, b, a)\n\t\t\t\t.endVertex();\n\t\tbuf.pos(x + width, y, zLevel)\n\t\t\t\t.color(r, g, b, a)\n\t\t\t\t.endVertex();\n\t\ttessellator.draw();\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/SmallGuiButton.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.gui;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.gui.GuiButton;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.utils.Color;\n\npublic class SmallGuiButton extends GuiButton {\n\n\tprivate final int stringOffset;\n\n\tpublic SmallGuiButton(int buttonId, int x, int y, int width, int height, String label) {\n\t\tthis(buttonId, x, y, width, height, label, 0);\n\t}\n\n\tpublic SmallGuiButton(int buttonId, int x, int y, int width, int height, String label, int offset) {\n\t\tsuper(buttonId, x, y, width, height, label);\n\t\tstringOffset = offset;\n\t}\n\n\tpublic SmallGuiButton(int i, int j, int k, String s) {\n\t\tsuper(i, j, k, s);\n\t\tstringOffset = 0;\n\t\t// TODO Auto-generated constructor stub\n\t}\n\n\t@Override\n\tpublic void drawButton(@Nonnull Minecraft minecraft, int mouseX, int mouseY, float partialTicks) {\n\t\tif (!visible) {\n\t\t\treturn;\n\t\t}\n\t\tFontRenderer fontrenderer = minecraft.fontRenderer;\n\t\tminecraft.renderEngine.bindTexture(GuiButton.BUTTON_TEXTURES);\n\t\t// GL11.glBindTexture(3553 /*GL_TEXTURE_2D*/, minecraft.renderEngine.getTexture(\"/gui/gui.png\"));\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tboolean flag = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height;\n\t\tint k = getHoverState(flag);\n\n\t\tdrawTexturedModalRect(x, y, 0, 46 + k * 20, width / 2, height / 2);\n\t\tdrawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + k * 20, width / 2, height / 2);\n\n\t\tdrawTexturedModalRect(x, y + height / 2, 0, 46 + 25 - height + k * 20, width / 2, height / 2);\n\t\tdrawTexturedModalRect(x + width / 2, y + height / 2, 200 - width / 2, 46 + 25 - height + k * 20, width / 2, height / 2);\n\n\t\tmouseDragged(minecraft, mouseX, mouseY);\n\n\t\tint color = Color.getValue(Color.LIGHTER_GREY);\n\t\tif (!enabled) {\n\t\t\tcolor = Color.getValue(Color.GREY);\n\t\t} else if (flag) {\n\t\t\tcolor = Color.getValue(Color.LIGHT_YELLOW);\n\t\t}\n\t\tdrawCenteredString(fontrenderer, displayString, x + width / 2, y + (height - 8) / 2 + stringOffset, color);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/SneakyUpgradeSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport logisticspipes.interfaces.ISlotCheck;\nimport logisticspipes.pipes.upgrades.UpgradeManager;\n\npublic class SneakyUpgradeSlot extends UpgradeSlot {\n\n\tprotected SneakyUpgradeSlot(UpgradeManager manager, int upgradeSlotId, int i, int j, int k, ISlotCheck slotCheck) {\n\t\tsuper(manager.sneakyInv, manager, upgradeSlotId, i, j, k, slotCheck);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/StaticRestrictedSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.Item;\n\nimport logisticspipes.interfaces.ISlotCheck;\n\npublic class StaticRestrictedSlot extends RestrictedSlot {\n\n\tint limit;\n\n\tpublic StaticRestrictedSlot(IInventory iinventory, int i, int j, int k, Item item, int stackLimit) {\n\t\tsuper(iinventory, i, j, k, item);\n\t\tlimit = stackLimit;\n\t}\n\n\tpublic StaticRestrictedSlot(IInventory iinventory, int i, int j, int k, ISlotCheck slotCheck, int stackLimit) {\n\t\tsuper(iinventory, i, j, k, slotCheck);\n\t\tlimit = stackLimit;\n\t}\n\n\t/**\n\t * Return whether this slot's stack can be taken from this slot.\n\t */\n\t@Override\n\tpublic boolean canTakeStack(EntityPlayer par1EntityPlayer) {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Returns the maximum stack size for a given slot (usually the same as\n\t * getInventoryStackLimit(), but 1 in the case of armor slots)\n\t */\n\t@Override\n\tpublic int getSlotStackLimit() {\n\t\treturn limit;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/SubGuiScreen.java",
    "content": "package logisticspipes.utils.gui;\n\nimport java.io.IOException;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.renderer.RenderHelper;\n\nimport lombok.Getter;\nimport org.lwjgl.opengl.GL11;\n\npublic abstract class SubGuiScreen extends GuiScreen implements ISubGuiControler, IGuiAccess {\n\n\t@Getter\n\tprotected int guiLeft;\n\t@Getter\n\tprotected int guiTop;\n\tprotected int xCenter;\n\tprotected int yCenter;\n\t@Getter\n\tprotected int right;\n\t@Getter\n\tprotected int bottom;\n\t@Getter\n\tprotected int xSize;\n\t@Getter\n\tprotected int ySize;\n\tprotected int xCenterOffset;\n\tprotected int yCenterOffset;\n\tprotected ISubGuiControler controler;\n\tprivate SubGuiScreen subGui;\n\n\tpublic SubGuiScreen(int xSize, int ySize, int xOffset, int yOffset) {\n\t\tthis.xSize = xSize;\n\t\tthis.ySize = ySize;\n\t\txCenterOffset = xOffset;\n\t\tyCenterOffset = yOffset;\n\t}\n\n\t@Override\n\tpublic void initGui() {\n\t\tsuper.initGui();\n\t\tguiLeft = width / 2 - xSize / 2 + xCenterOffset;\n\t\tguiTop = height / 2 - ySize / 2 + yCenterOffset;\n\n\t\tright = width / 2 + xSize / 2 + xCenterOffset;\n\t\tbottom = height / 2 + ySize / 2 + yCenterOffset;\n\n\t\txCenter = (right + guiLeft) / 2;\n\t\tyCenter = (bottom + guiTop) / 2;\n\t}\n\n\tpublic void register(ISubGuiControler gui) {\n\t\tcontroler = gui;\n\t}\n\n\tpublic void exitGui() {\n\t\tcontroler.resetSubGui();\n\t}\n\n\t@Override\n\tprotected void keyTyped(char par1, int par2) {\n\t\tif (par2 == 1) {\n\t\t\texitGui();\n\t\t}\n\t}\n\n\t@Override\n\tpublic final void drawScreen(int mouseX, int mouseY, float partialTicks) {\n\t\tRenderHelper.disableStandardItemLighting();\n\t\trenderGuiBackground(mouseX, mouseY);\n\t\tGlStateManager.disableRescaleNormal();\n\t\tGlStateManager.disableLighting();\n\t\tGlStateManager.disableDepth();\n\t\tsuper.drawScreen(mouseX, mouseY, partialTicks);\n\t\tRenderHelper.enableGUIStandardItemLighting();\n\n\t\tGlStateManager.pushMatrix();\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tGlStateManager.enableRescaleNormal();\n\t\tshort short1 = 240;\n\t\tshort short2 = 240;\n\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) short1 / 1.0F, (float) short2 / 1.0F);\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\n\t\tthis.drawGuiContainerForegroundLayer(mouseX, mouseY, partialTicks);\n\n\t\tGlStateManager.popMatrix();\n\n\t\tGlStateManager.enableLighting();\n\t\tGlStateManager.enableDepth();\n\t\tif (subGui != null) {\n\t\t\tGL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\tif (!subGui.hasSubGui()) {\n\t\t\t\tGL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\t\tsuper.drawDefaultBackground();\n\t\t\t}\n\t\t\tGL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);\n\t\t\tsubGui.drawScreen(mouseX, mouseY, partialTicks);\n\t\t\tGL11.glPopAttrib();\n\t\t}\n\t\trenderToolTips(mouseX, mouseY, partialTicks);\n\t}\n\n\tprotected void renderToolTips(int mouseX, int mouseY, float par3) {}\n\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY, float partialTick) {\n\t\tdrawGuiContainerForegroundLayer(mouseX, mouseY);\n\t}\n\n\tprotected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {}\n\n\tprotected abstract void renderGuiBackground(int mouseX, int mouseY);\n\n\t@Override\n\tpublic final void handleMouseInput() throws IOException {\n\t\tif (subGui != null) {\n\t\t\tsubGui.handleMouseInput();\n\t\t} else {\n\t\t\thandleMouseInputSub();\n\t\t}\n\t}\n\n\tpublic void handleMouseInputSub() throws IOException {\n\t\tsuper.handleMouseInput();\n\t}\n\n\t@Override\n\tpublic final void handleKeyboardInput() throws IOException {\n\t\tif (subGui != null) {\n\t\t\tsubGui.handleKeyboardInput();\n\t\t} else {\n\t\t\tsuper.handleKeyboardInput();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setWorldAndResolution(Minecraft mc, int width, int height) {\n\t\tsuper.setWorldAndResolution(mc, width, height);\n\t\tif (subGui != null) {\n\t\t\tsubGui.setWorldAndResolution(mc, width, height);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void resetSubGui() {\n\t\tsubGui = null;\n\t}\n\n\t@Override\n\tpublic boolean hasSubGui() {\n\t\treturn subGui != null;\n\t}\n\n\t@Override\n\tpublic SubGuiScreen getSubGui() {\n\t\treturn subGui;\n\t}\n\n\t@Override\n\tpublic void setSubGui(SubGuiScreen gui) {\n\t\tif (subGui == null) {\n\t\t\tsubGui = gui;\n\t\t\tsubGui.register(this);\n\t\t\tsubGui.setWorldAndResolution(mc, width, height);\n\t\t\tsubGui.initGui();\n\t\t}\n\t}\n\n\t@Override\n\tpublic LogisticsBaseGuiScreen getBaseScreen() {\n\t\treturn controler.getBaseScreen();\n\t}\n\n\t@Override\n\tpublic Minecraft getMC() {\n\t\treturn mc;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/TextListDisplay.java",
    "content": "package logisticspipes.utils.gui;\n\nimport java.util.Collections;\n\nimport net.minecraft.client.gui.Gui;\nimport net.minecraft.util.text.TextFormatting;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport logisticspipes.utils.Color;\nimport network.rs485.logisticspipes.util.TextUtil;\n\npublic class TextListDisplay {\n\n\tpublic interface List {\n\n\t\tint getSize();\n\n\t\tString getTextAt(int index);\n\n\t\tint getTextColor(int index);\n\t}\n\n\tprivate final List list;\n\tprivate final IGuiAccess gui;\n\n\tprivate final int borderTop;\n\tprivate final int borderRight;\n\tprivate final int borderBottom;\n\tprivate final int borderLeft;\n\tprivate final int elementPerPage;\n\n\tprivate int mouseClickX = 0;\n\tprivate int mouseClickY = 0;\n\tprivate int mousePosX = 0;\n\tprivate int mousePosY = 0;\n\tprivate int scroll = 0;\n\t@Getter\n\t@Setter\n\tprivate int selected = -1;\n\tprivate int hover = -1;\n\n\tpublic TextListDisplay(IGuiAccess gui, int borderLeft, int borderTop, int borderRight, int borderBottom, int elementPerPage, List list) {\n\t\tthis.list = list;\n\t\tthis.gui = gui;\n\t\tthis.borderTop = borderTop;\n\t\tthis.borderRight = borderRight;\n\t\tthis.borderBottom = borderBottom;\n\t\tthis.borderLeft = borderLeft;\n\t\tthis.elementPerPage = elementPerPage;\n\t}\n\n\tpublic void mouseClicked(int i, int j, int k) {\n\t\tmouseClickX = i;\n\t\tmouseClickY = j;\n\t}\n\n\tpublic void renderGuiBackground(int mouseX, int mouseY) {\n\t\tmousePosX = mouseX;\n\t\tmousePosY = mouseY;\n\n\t\tGui.drawRect(gui.getGuiLeft() + borderLeft, gui.getGuiTop() + borderTop, gui.getRight() - borderRight, gui.getBottom() - borderBottom, Color.getValue(Color.GREY));\n\n\t\tif (scroll + elementPerPage > list.getSize()) {\n\t\t\tscroll = list.getSize() - elementPerPage;\n\t\t}\n\t\tif (scroll < 0) {\n\t\t\tscroll = 0;\n\t\t}\n\n\t\tboolean flag = false;\n\n\t\thover = -1;\n\t\tif (gui.getGuiLeft() + borderLeft + 2 < this.mousePosX\n\t\t\t\t&& this.mousePosX < gui.getRight() - borderRight - 2 && gui.getGuiTop() + borderTop + 2 < this.mousePosY\n\t\t\t\t&& this.mousePosY < gui.getGuiTop() + borderTop + 3 + (elementPerPage * 10)) {\n\t\t\thover = scroll + (this.mousePosY - gui.getGuiTop() - borderTop - 3) / 10;\n\t\t}\n\t\tif (list.getSize() == 0 || hover >= list.getSize()) {\n\t\t\thover = -1;\n\t\t}\n\n\t\tif (gui.getGuiLeft() + borderLeft + 2 < this.mouseClickX\n\t\t\t\t&& this.mouseClickX < gui.getRight() - borderRight - 2 && gui.getGuiTop() + borderTop + 2 < this.mouseClickY\n\t\t\t\t&& this.mouseClickY < gui.getGuiTop() + borderTop + 3 + (elementPerPage * 10)) {\n\t\t\tselected = scroll + (this.mouseClickY - gui.getGuiTop() - borderTop - 3) / 10;\n\t\t\tmouseClickX = -1;\n\t\t\tmouseClickY = -1;\n\t\t}\n\n\t\tfor (int i = scroll; i < list.getSize() && (i - scroll) < elementPerPage; i++) {\n\t\t\tif (i == selected) {\n\t\t\t\tGui.drawRect(gui.getGuiLeft() + borderLeft + 2, gui.getGuiTop() + borderTop + 2 + ((i - scroll) * 10), gui.getRight() - borderRight - 2, gui.getGuiTop() + borderTop + 13 + ((i - scroll) * 10), Color.getValue(Color.DARKER_GREY));\n\t\t\t\tflag = true;\n\t\t\t}\n\t\t\tString name = list.getTextAt(i);\n\t\t\tname = TextUtil.getTrimmedString(name, gui.getXSize() - borderRight - borderLeft - 6, gui.getMC().fontRenderer, \"...\");\n\t\t\tgui.getMC().fontRenderer.drawString(name, gui.getGuiLeft() + borderLeft + 4, gui.getGuiTop() + borderTop + 4 + ((i - scroll) * 10), list.getTextColor(i));\n\t\t}\n\n\t\tif (!flag) {\n\t\t\tselected = -1;\n\t\t}\n\t}\n\n\tpublic void renderGuiForeground() {\n\t\tif (hover != -1) {\n\t\t\tGuiGraphics.drawToolTip(mousePosX - gui.getGuiLeft(), mousePosY - gui.getGuiTop(), Collections.singletonList(list.getTextAt(hover)), TextFormatting.WHITE);\n\t\t}\n\t}\n\n\tpublic void scrollUp() {\n\t\tscroll++;\n\t}\n\n\tpublic void scrollDown() {\n\t\tif (scroll > 0) {\n\t\t\tscroll--;\n\t\t}\n\t}\n\n\tpublic void mouseScrollUp() {\n\t\tif (gui.getGuiLeft() + borderLeft < mousePosX\n\t\t\t\t&& mousePosX < gui.getRight() - borderRight && gui.getGuiTop() + borderTop < mousePosY && mousePosY < gui.getBottom() + borderBottom) {\n\t\t\tscrollUp();\n\t\t}\n\t}\n\n\tpublic void mouseScrollDown() {\n\t\tif (gui.getGuiLeft() + borderLeft < mousePosX\n\t\t\t\t&& mousePosX < gui.getRight() - borderRight && gui.getGuiTop() + borderTop < mousePosY && mousePosY < gui.getBottom() + borderBottom) {\n\t\t\tscrollDown();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/UnmodifiableSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.Slot;\n\npublic class UnmodifiableSlot extends Slot {\n\n\tpublic UnmodifiableSlot(IInventory par1iInventory, int par2, int par3, int par4) {\n\t\tsuper(par1iInventory, par2, par3, par4);\n\t}\n\n\tpublic UnmodifiableSlot(Slot slot) {\n\t\tsuper(slot.inventory, slot.getSlotIndex(), slot.xPos, slot.yPos);\n\t}\n\n\t@Override\n\tpublic boolean canTakeStack(EntityPlayer par1EntityPlayer) {\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/UpgradeSlot.java",
    "content": "package logisticspipes.utils.gui;\n\nimport net.minecraft.inventory.IInventory;\n\nimport lombok.Getter;\n\nimport logisticspipes.interfaces.ISlotCheck;\nimport logisticspipes.interfaces.ISlotUpgradeManager;\nimport logisticspipes.pipes.upgrades.IPipeUpgrade;\n\npublic class UpgradeSlot extends RestrictedSlot {\n\n\t@Getter\n\tprotected final ISlotUpgradeManager manager;\n\tprotected final int upgradeSlotId;\n\n\tprotected UpgradeSlot(IInventory iinventory, ISlotUpgradeManager manager, int upgradeSlotId, int i, int j, int k, ISlotCheck slotCheck) {\n\t\tsuper(iinventory, i, j, k, slotCheck);\n\t\tthis.manager = manager;\n\t\tthis.upgradeSlotId = upgradeSlotId;\n\t}\n\n\tpublic UpgradeSlot(ISlotUpgradeManager manager, int upgradeSlotId, int i, int j, int k, ISlotCheck check) {\n\t\tsuper(manager.getInv(), i, j, k, check);\n\t\tthis.manager = manager;\n\t\tthis.upgradeSlotId = upgradeSlotId;\n\t}\n\n\tpublic IPipeUpgrade getUpgrade() {\n\t\treturn manager.getUpgrade(upgradeSlotId);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/extension/GuiExtension.java",
    "content": "package logisticspipes.utils.gui.extension;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport lombok.AccessLevel;\nimport lombok.Getter;\nimport lombok.Setter;\n\npublic abstract class GuiExtension {\n\n\t@Getter\n\t@Setter(value = AccessLevel.PACKAGE)\n\tprivate boolean extending;\n\tprivate int currentW = getMinimumWidth();\n\tprivate int currentH = getMinimumHeight();\n\t@Getter\n\tprivate int currentXPos = 0;\n\t@Getter\n\tprivate int currentYPos = 0;\n\tprivate int targetYPos = 0;\n\tprivate boolean init = true;\n\tprivate long lastTime;\n\tprivate List<Integer> slotList = new ArrayList<>();\n\tprivate List<Integer> buttonList = new ArrayList<>();\n\n\tpublic abstract int getFinalWidth();\n\n\tpublic abstract int getFinalHeight();\n\n\tpublic abstract void renderForeground(int left, int top);\n\n\tpublic final void update(int xPos, int yPos) {\n\t\tdouble d = 0;\n\t\tif(lastTime > 0) {\n\t\t\tlong time = System.currentTimeMillis();\n\t\t\td = (time - lastTime) * 1.0 / 5;\n\t\t\tif (d < 1) {\n\t\t\t\td = 0;\n\t\t\t} else {\n\t\t\t\tlastTime = time;\n\t\t\t}\n\t\t\td = Math.min(d, 20.0);\n\t\t} else {\n\t\t\tlastTime = System.currentTimeMillis();\n\t\t}\n\t\tcurrentXPos = xPos;\n\t\tif (yPos > currentYPos + 1 * d && !init) {\n\t\t\tcurrentYPos += 2 * d;\n\t\t} else if (yPos < currentYPos - 1 * d && !init) {\n\t\t\tcurrentYPos -= 2 * d;\n\t\t} else {\n\t\t\tcurrentYPos = yPos;\n\t\t}\n\t\ttargetYPos = yPos;\n\t\tinit = false;\n\t\tif (extending) {\n\t\t\tif (currentH < getFinalHeight()) {\n\t\t\t\tcurrentH += 4 * d;\n\t\t\t} else {\n\t\t\t\tcurrentH = getFinalHeight();\n\t\t\t}\n\t\t\tif (currentW < getFinalWidth()) {\n\t\t\t\tcurrentW += 2 * d;\n\t\t\t} else {\n\t\t\t\tcurrentW = getFinalWidth();\n\t\t\t}\n\t\t} else {\n\t\t\tif (currentH > getMinimumHeight()) {\n\t\t\t\tcurrentH -= 4 * d;\n\t\t\t} else {\n\t\t\t\tcurrentH = getMinimumHeight();\n\t\t\t}\n\t\t\tif (currentW > getMinimumWidth()) {\n\t\t\t\tcurrentW -= 2 * d;\n\t\t\t} else {\n\t\t\t\tcurrentW = getMinimumWidth();\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int getMinimumWidth() {\n\t\treturn 23;\n\t}\n\n\tpublic int getMinimumHeight() {\n\t\treturn 26;\n\t}\n\n\tpublic int getCurrentWidth() {\n\t\treturn currentW;\n\t}\n\n\tpublic int getCurrentHeight() {\n\t\treturn currentH;\n\t}\n\n\tpublic boolean isFullyExtended() {\n\t\treturn currentW == getFinalWidth() && currentH == getFinalHeight() && targetYPos == currentYPos;\n\t}\n\n\tpublic boolean isFullyRetracted() {\n\t\treturn currentW == getMinimumWidth() && currentH == getMinimumHeight() && targetYPos == currentYPos;\n\t}\n\n\tpublic void handleMouseOverAt(int xPos, int yPos) {}\n\n\tpublic void registerSlot(int id) {\n\t\tslotList.add(id);\n\t}\n\n\tpublic boolean renderSlot(int id) {\n\t\treturn slotList.contains(id);\n\t}\n\n\tpublic boolean renderSelectSlot(int id) {\n\t\treturn slotList.contains(id);\n\t}\n\n\tpublic void registerButton(int id) {\n\t\tbuttonList.add(id);\n\t}\n\n\tpublic boolean renderButton(int id) {\n\t\treturn buttonList.contains(id);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/extension/GuiExtensionController.java",
    "content": "package logisticspipes.utils.gui.extension;\n\nimport java.awt.Rectangle;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.GuiButton;\nimport net.minecraft.inventory.Slot;\n\nimport lombok.Setter;\n\nimport logisticspipes.utils.gui.GuiGraphics;\n\npublic class GuiExtensionController {\n\n\tpublic enum GuiSide {\n\t\tLEFT,\n\t\tRIGHT\n\t}\n\n\tprivate final List<GuiExtension> extensions = new ArrayList<>();\n\tprivate final List<GuiExtension> extensionsToRemove = new ArrayList<>();\n\t@Setter\n\tprivate int maxBottom;\n\tprivate GuiExtension currentlyExtended = null;\n\tprivate Map<Slot, Integer> slotMap = new HashMap<>();\n\tprivate Map<GuiButton, Integer> buttonMap = new HashMap<>();\n\n\tprivate final GuiSide side;\n\n\tpublic GuiExtensionController(GuiSide side) {\n\t\tthis.side = side;\n\t}\n\n\tpublic void render(int xPos, int yPos) {\n\t\tyPos += 4;\n\t\tif (currentlyExtended == null) {\n\t\t\tfor (GuiExtension extension : extensions) {\n\t\t\t\textension.setExtending(false);\n\t\t\t\tint left;\n\t\t\t\tint right;\n\t\t\t\tif (side == GuiSide.LEFT) {\n\t\t\t\t\tleft = xPos - extension.getCurrentWidth();\n\t\t\t\t\tright = xPos + 15;\n\t\t\t\t} else {\n\t\t\t\t\tleft = xPos - 15;\n\t\t\t\t\tright = xPos + extension.getCurrentWidth();\n\t\t\t\t}\n\t\t\t\tint bottom = yPos + extension.getCurrentHeight();\n\t\t\t\textension.update(left, yPos);\n\t\t\t\tGuiGraphics.drawGuiBackGround(Minecraft.getMinecraft(), left, yPos, right, bottom, 0, true, true, side != GuiSide.RIGHT, true, side != GuiSide.LEFT);\n\t\t\t\textension.renderForeground(left + (side == GuiSide.RIGHT ? 20 : 0), yPos);\n\t\t\t\tyPos = bottom;\n\t\t\t}\n\t\t} else {\n\t\t\tif (currentlyExtended.isExtending()) {\n\t\t\t\tint left;\n\t\t\t\tint right;\n\t\t\t\tif (side == GuiSide.LEFT) {\n\t\t\t\t\tleft = xPos - currentlyExtended.getCurrentWidth();\n\t\t\t\t\tright = xPos + 15;\n\t\t\t\t} else {\n\t\t\t\t\tleft = xPos - 15;\n\t\t\t\t\tright = xPos + currentlyExtended.getCurrentWidth();\n\t\t\t\t}\n\t\t\t\tint bottom = currentlyExtended.getCurrentYPos() + currentlyExtended.getCurrentHeight();\n\t\t\t\tcurrentlyExtended.update(left, yPos);\n\t\t\t\tGuiGraphics.drawGuiBackGround(Minecraft.getMinecraft(), left, currentlyExtended.getCurrentYPos(), right, bottom, 0, true, true, side != GuiSide.RIGHT, true, side != GuiSide.LEFT);\n\t\t\t\tcurrentlyExtended.renderForeground(left + (side == GuiSide.RIGHT ? 20 : 0), currentlyExtended.getCurrentYPos());\n\t\t\t} else {\n\t\t\t\tfor (GuiExtension extension : extensions) {\n\t\t\t\t\tif (extension == currentlyExtended) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\textension.setExtending(false);\n\t\t\t\t\tint bottom = yPos + extension.getCurrentHeight();\n\t\t\t\t\tyPos = bottom;\n\t\t\t\t}\n\t\t\t\tint left;\n\t\t\t\tint right;\n\t\t\t\tif (side == GuiSide.LEFT) {\n\t\t\t\t\tleft = xPos - currentlyExtended.getCurrentWidth();\n\t\t\t\t\tright = xPos + 15;\n\t\t\t\t} else {\n\t\t\t\t\tleft = xPos - 15;\n\t\t\t\t\tright = xPos + currentlyExtended.getCurrentWidth();\n\t\t\t\t}\n\t\t\t\tint bottom = currentlyExtended.getCurrentYPos() + currentlyExtended.getCurrentHeight();\n\t\t\t\tcurrentlyExtended.update(left, yPos);\n\t\t\t\tGuiGraphics.drawGuiBackGround(Minecraft.getMinecraft(), left, currentlyExtended.getCurrentYPos(), right, bottom, 0, true, true, side != GuiSide.RIGHT, true, side != GuiSide.LEFT);\n\t\t\t\tcurrentlyExtended.renderForeground(left + (side == GuiSide.RIGHT ? 20 : 0), currentlyExtended.getCurrentYPos());\n\t\t\t\tif (currentlyExtended.isFullyRetracted()) {\n\t\t\t\t\tcurrentlyExtended = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (currentlyExtended != null && extensionsToRemove.contains(currentlyExtended)) {\n\t\t\tcurrentlyExtended = null;\n\t\t}\n\t\textensions.removeAll(extensionsToRemove);\n\t\textensionsToRemove.clear();\n\t}\n\n\tpublic void addExtension(GuiExtension extension) {\n\t\textensions.add(extension);\n\t}\n\n\tpublic void removeExtension(GuiExtension extension) {\n\t\textensionsToRemove.add(extension);\n\t}\n\n\tpublic void mouseClicked(int x, int y, int k) {\n\t\tif (currentlyExtended == null) {\n\t\t\textensions.stream()\n\t\t\t\t\t.filter(extension -> x > extension.getCurrentXPos() && x < extension.getCurrentXPos() + extension.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0) && y > extension.getCurrentYPos() && y < extension.getCurrentYPos() + extension.getCurrentHeight())\n\t\t\t\t\t.forEach(extension -> {\n\t\t\t\t\t\tcurrentlyExtended = extension;\n\t\t\t\t\t\tcurrentlyExtended.setExtending(true);\n\t\t\t\t\t});\n\t\t} else {\n\t\t\tif (x > currentlyExtended.getCurrentXPos() && x < currentlyExtended.getCurrentXPos() + currentlyExtended.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0) && y > currentlyExtended.getCurrentYPos() && y < currentlyExtended.getCurrentYPos() + currentlyExtended.getCurrentHeight()) {\n\t\t\t\tcurrentlyExtended.setExtending(false);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void mouseOver(int i, int j) {\n\t\tint x = i;\n\t\tint y = j;\n\t\tif (currentlyExtended == null) {\n\t\t\tfor (GuiExtension extension : extensions) {\n\t\t\t\tif (x > extension.getCurrentXPos() && x < extension.getCurrentXPos() + extension.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0) && y > extension.getCurrentYPos() && y < extension.getCurrentYPos() + extension.getCurrentHeight()) {\n\t\t\t\t\textension.handleMouseOverAt(x, y);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (x > currentlyExtended.getCurrentXPos() && x < currentlyExtended.getCurrentXPos() + currentlyExtended.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0) && y > currentlyExtended.getCurrentYPos() && y < currentlyExtended.getCurrentYPos() + currentlyExtended.getCurrentHeight()) {\n\t\t\t\tcurrentlyExtended.handleMouseOverAt(x, y);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic int registerControlledSlot(Slot slot) {\n\t\tint size = slotMap.size();\n\t\tslotMap.put(slot, size);\n\t\treturn size;\n\t}\n\n\tpublic boolean renderSlot(Slot slot) {\n\t\tif (!slotMap.containsKey(slot)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (currentlyExtended == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!currentlyExtended.isFullyExtended()) {\n\t\t\treturn false;\n\t\t}\n\t\tint id = slotMap.get(slot);\n\t\treturn currentlyExtended.renderSlot(id);\n\t}\n\n\tpublic boolean renderSelectSlot(Slot slot) {\n\t\tif (!slotMap.containsKey(slot)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (currentlyExtended == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!currentlyExtended.isFullyExtended()) {\n\t\t\treturn false;\n\t\t}\n\t\tint id = slotMap.get(slot);\n\t\treturn currentlyExtended.renderSelectSlot(id);\n\t}\n\n\tpublic int registerControlledButton(GuiButton button) {\n\t\tint size = buttonMap.size();\n\t\tbuttonMap.put(button, size);\n\t\treturn size;\n\t}\n\n\tpublic boolean renderButtonControlled(GuiButton button) {\n\t\treturn buttonMap.containsKey(button);\n\t}\n\n\tpublic boolean renderButton(GuiButton button) {\n\t\tif (!buttonMap.containsKey(button)) {\n\t\t\treturn true;\n\t\t}\n\t\tif (currentlyExtended == null) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!currentlyExtended.isFullyExtended()) {\n\t\t\treturn false;\n\t\t}\n\t\tint id = buttonMap.get(button);\n\t\treturn currentlyExtended.renderButton(id);\n\t}\n\n\tpublic void clear() {\n\t\textensions.clear();\n\t\textensionsToRemove.clear();\n\t\tcurrentlyExtended = null;\n\t}\n\n\tpublic void retract() {\n\t\tif (currentlyExtended != null) {\n\t\t\tcurrentlyExtended.setExtending(false);\n\t\t}\n\t}\n\n\tpublic List<Rectangle> getGuiExtraAreas() {\n\t\tList<Rectangle> list = new ArrayList<>();\n\t\tif (currentlyExtended == null) {\n\t\t\tfor (GuiExtension extension : extensions) {\n\t\t\t\tlist.add(new Rectangle(extension.getCurrentXPos(), extension.getCurrentYPos(), extension.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0), extension.getCurrentHeight()));\n\t\t\t}\n\t\t} else {\n\t\t\tlist.add(new Rectangle(currentlyExtended.getCurrentXPos(), currentlyExtended.getCurrentYPos(), currentlyExtended.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0), currentlyExtended.getCurrentHeight()));\n\t\t}\n\t\treturn list;\n\t}\n\n\tpublic boolean isOverPanel(int x, int y, int w, int h) {\n\t\tif (currentlyExtended == null) {\n\t\t\tfor (GuiExtension extension : extensions) {\n\t\t\t\tif (x + w > extension.getCurrentXPos() && x < extension.getCurrentXPos() + extension.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0) && y + h > extension.getCurrentYPos() && y < extension.getCurrentYPos() + extension.getCurrentHeight()) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (x + w > currentlyExtended.getCurrentXPos() && x < currentlyExtended.getCurrentXPos() + currentlyExtended.getCurrentWidth() + (side == GuiSide.RIGHT ? 15 : 0) && y + h > currentlyExtended.getCurrentYPos() && y < currentlyExtended.getCurrentYPos() + currentlyExtended.getCurrentHeight()) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/hud/BasicHUDButton.java",
    "content": "package logisticspipes.utils.gui.hud;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.texture.TextureMap;\n\nimport net.minecraftforge.fml.client.FMLClientHandler;\n\nimport org.lwjgl.opengl.GL11;\n\nimport logisticspipes.interfaces.IHUDButton;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.SimpleGraphics;\n\npublic abstract class BasicHUDButton implements IHUDButton {\n\n\tprotected final int posX;\n\tprotected final int posY;\n\tprotected final int sizeX;\n\tprotected final int sizeY;\n\tprotected long focusedTimeStart = 0;\n\tprotected final String label;\n\n\tpublic BasicHUDButton(String name, int x, int y, int width, int heigth) {\n\t\tlabel = name;\n\t\tposX = x;\n\t\tposY = y;\n\t\tsizeX = width;\n\t\tsizeY = heigth;\n\t}\n\n\t@Override\n\tpublic int getX() {\n\t\treturn posX;\n\t}\n\n\t@Override\n\tpublic int getY() {\n\t\treturn posY;\n\t}\n\n\t@Override\n\tpublic int sizeX() {\n\t\treturn sizeX;\n\t}\n\n\t@Override\n\tpublic int sizeY() {\n\t\treturn sizeY;\n\t}\n\n\t@Override\n\tpublic void blockFocused() {\n\t\tfocusedTimeStart = -1;\n\t}\n\n\t@Override\n\tpublic boolean isblockFocused() {\n\t\treturn focusedTimeStart == -1;\n\t}\n\n\t@Override\n\tpublic void setFocused() {\n\t\tfocusedTimeStart = System.currentTimeMillis();\n\t}\n\n\t@Override\n\tpublic boolean isFocused() {\n\t\treturn focusedTimeStart != 0;\n\t}\n\n\t@Override\n\tpublic void clearFocused() {\n\t\tfocusedTimeStart = 0;\n\t}\n\n\t@Override\n\tpublic int focusedTime() {\n\t\treturn (int) (System.currentTimeMillis() - focusedTimeStart);\n\t}\n\n\t@Override\n\tpublic void renderButton(boolean hover, boolean clicked, boolean shifted) {\n\t\tMinecraft minecraft = FMLClientHandler.instance().getClient();\n\t\t//GL11.glBindTexture(3553 /*GL_TEXTURE_2D*/,\n\t\tminecraft.renderEngine.bindTexture(GuiGraphics.WIDGETS_TEXTURE);\n\t\tGL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tint k = !buttonEnabled() ? 0 : hover ? 2 : 1;\n\n\t\tSimpleGraphics.drawTexturedModalRect(posX, posY, 0, 46 + k * 20, sizeX / 2, sizeY / 2, 0.0);\n\t\tSimpleGraphics.drawTexturedModalRect(posX + sizeX / 2, posY, 200 - sizeX / 2, 46 + k * 20, sizeX / 2, sizeY / 2, 0.0);\n\n\t\tSimpleGraphics.drawTexturedModalRect(posX, posY + sizeY / 2, 0, 46 + 24 - sizeY + k * 20, sizeX / 2, sizeY / 2, 0.0);\n\t\tSimpleGraphics.drawTexturedModalRect(posX + sizeX / 2, posY + sizeY / 2, 200 - sizeX / 2, 46 + 24 - sizeY + k * 20, sizeX / 2, sizeY / 2, 0.0);\n\n\t\tGL11.glTranslatef(0.0F, 0.0F, -0.001F);\n\t\tint color = Color.getValue(Color.LIGHTER_GREY);\n\t\tif (!clicked) {\n\t\t\tcolor = Color.getValue(Color.LIGHT_YELLOW);\n\t\t\tif (hover) {\n\t\t\t\tGL11.glTranslatef(0.0F, 0.0F, -0.02F);\n\t\t\t}\n\t\t}\n\t\tminecraft.fontRenderer.drawString(label, -(minecraft.fontRenderer.getStringWidth(label) / 2) + posX + sizeX / 2, posY + (sizeY - 8) / 2, color);\n\t\tif (!clicked && hover) {\n\t\t\tGL11.glTranslatef(0.0F, 0.0F, 0.02F);\n\t\t}\n\t\tGL11.glTranslatef(0.0F, 0.0F, 0.001F);\n\t\tminecraft.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t}\n\n\t@Override\n\tpublic void renderAlways(boolean shifted) {\n\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/gui/sideconfig/SideConfigDisplay.java",
    "content": "package logisticspipes.utils.gui.sideconfig;\n\nimport java.awt.Rectangle;\nimport java.nio.FloatBuffer;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.ScaledResolution;\nimport net.minecraft.client.renderer.BlockRendererDispatcher;\nimport net.minecraft.client.renderer.BufferBuilder;\nimport net.minecraft.client.renderer.GLAllocation;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.client.renderer.Tessellator;\nimport net.minecraft.client.renderer.block.model.IBakedModel;\nimport net.minecraft.client.renderer.texture.TextureAtlasSprite;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats;\nimport net.minecraft.client.renderer.vertex.VertexFormat;\nimport net.minecraft.client.renderer.vertex.VertexFormatElement;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.tileentity.TileEntityChest;\nimport net.minecraft.util.BlockRenderLayer;\nimport net.minecraft.util.EnumBlockRenderType;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.ForgeHooksClient;\nimport net.minecraftforge.client.MinecraftForgeClient;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport org.lwjgl.input.Keyboard;\nimport org.lwjgl.input.Mouse;\nimport org.lwjgl.opengl.GL11;\nimport org.lwjgl.opengl.GL14;\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe;\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe;\nimport logisticspipes.textures.Textures;\nimport logisticspipes.utils.LPPositionSet;\nimport logisticspipes.utils.math.BoundingBox;\nimport logisticspipes.utils.math.Camera;\nimport logisticspipes.utils.math.Matrix4d;\nimport logisticspipes.utils.math.VecmathUtil;\nimport logisticspipes.utils.math.Vector2d;\nimport logisticspipes.utils.math.Vector3d;\nimport logisticspipes.utils.math.Vertex;\nimport network.rs485.logisticspipes.world.CoordinateUtils;\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\n//Based on: https://github.com/SleepyTrousers/EnderIO/blob/master/src/main/java/crazypants/enderio/machine/gui/GuiOverlayIoConfig.java\n@SideOnly(Side.CLIENT)\npublic abstract class SideConfigDisplay {\n\n\tprivate boolean draggingRotate = false;\n\tprivate boolean draggingMove = false;\n\tprivate float pitch;\n\tprivate float yaw;\n\tprivate double distance;\n\tprivate long initTime;\n\n\tprivate Minecraft mc = Minecraft.getMinecraft();\n\tprivate World world;\n\n\tprivate final Vector3d origin = new Vector3d();\n\tprivate final Vector3d eye = new Vector3d();\n\tprivate final Camera camera = new Camera();\n\tprivate final Matrix4d pitchRot = new Matrix4d();\n\tprivate final Matrix4d yawRot = new Matrix4d();\n\n\tpublic DoubleCoordinates originBC;\n\n\tprivate List<DoubleCoordinates> configurables = new ArrayList<>();\n\tprivate List<DoubleCoordinates> neighbours = new ArrayList<>();\n\n\tprivate SelectedFace selection;\n\n\tpublic boolean renderNeighbours = true;\n\n\tpublic SideConfigDisplay(CoreRoutedPipe configurables) {\n\t\tthis(Collections.singletonList(configurables.getLPPosition()));\n\t}\n\n\tpublic SideConfigDisplay(LPPositionSet<DoubleCoordinates> configurables) {\n\t\tthis(Arrays.asList(configurables.toArray(new DoubleCoordinates[0])));\n\t}\n\n\tpublic SideConfigDisplay(List<DoubleCoordinates> configurables) {\n\t\tthis.configurables.addAll(configurables);\n\n\t\tVector3d c;\n\t\tVector3d size;\n\t\tif (configurables.size() == 1) {\n\t\t\tDoubleCoordinates bc = this.configurables.get(0);\n\t\t\tc = new Vector3d(bc.getXDouble() + 0.5, bc.getYDouble() + 0.5, bc.getZDouble() + 0.5);\n\t\t\tsize = new Vector3d(1, 1, 1);\n\t\t} else {\n\t\t\tVector3d min = new Vector3d(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);\n\t\t\tVector3d max = new Vector3d(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);\n\t\t\tfor (DoubleCoordinates bc : configurables) {\n\t\t\t\tmin.set(Math.min(bc.getXDouble(), min.x), Math.min(bc.getYDouble(), min.y), Math\n\t\t\t\t\t\t.min(bc.getZDouble(), min.z));\n\t\t\t\tmax.set(Math.max(bc.getXDouble(), max.x), Math.max(bc.getYDouble(), max.y), Math\n\t\t\t\t\t\t.max(bc.getZDouble(), max.z));\n\t\t\t}\n\t\t\tsize = new Vector3d(max);\n\t\t\tsize.sub(min);\n\t\t\tsize.multiply(0.5);\n\t\t\tc = new Vector3d(min.x + size.x, min.y + size.y, min.z + size.z);\n\t\t\tsize.multiply(2);\n\t\t}\n\n\t\toriginBC = new DoubleCoordinates((int) c.x, (int) c.y, (int) c.z);\n\t\torigin.set(c);\n\t\tpitchRot.setIdentity();\n\t\tyawRot.setIdentity();\n\n\t\tpitch = -mc.player.rotationPitch;\n\t\tyaw = 180 - mc.player.rotationYaw;\n\n\t\tdistance = Math.max(Math.max(size.x, size.y), size.z) + 4;\n\n\t\tfor (DoubleCoordinates bc : configurables) {\n\t\t\tfor (EnumFacing dir : EnumFacing.VALUES) {\n\t\t\t\tDoubleCoordinates loc = CoordinateUtils.add(new DoubleCoordinates(bc), dir);\n\t\t\t\tif (!configurables.contains(loc)) {\n\t\t\t\t\tneighbours.add(loc);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tworld = mc.player.world;\n\t}\n\n\tpublic abstract void handleSelection(SelectedFace selection);\n\n\tpublic void init() {\n\t\tinitTime = System.currentTimeMillis();\n\t}\n\n\tpublic SelectedFace getSelection() {\n\t\treturn selection;\n\t}\n\n\tpublic void handleMouseInput() {\n\n\t\tif (Mouse.getEventButton() == 0) {\n\t\t\tdraggingRotate = Mouse.getEventButtonState();\n\t\t}\n\t\tif (Mouse.getEventButton() == 2) {\n\t\t\tdraggingMove = Mouse.getEventButtonState();\n\t\t}\n\n\t\tif (draggingRotate) {\n\t\t\tdouble dx = (Mouse.getEventDX() / (double) mc.displayWidth);\n\t\t\tdouble dy = (Mouse.getEventDY() / (double) mc.displayHeight);\n\t\t\tif (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {\n\t\t\t\tdistance -= dy * 15;\n\t\t\t} else {\n\t\t\t\tyaw -= 4 * dx * 180;\n\t\t\t\tpitch += 2 * dy * 180;\n\t\t\t\tpitch = (float) VecmathUtil.clamp(pitch, -80, 80);\n\t\t\t}\n\t\t}\n\n\t\tif (draggingMove) {\n\t\t\tdouble dx = Mouse.getEventDX();\n\t\t\tdouble dy = -Mouse.getEventDY();\n\t\t\tVector3d orivec = camera.getWorldPoint(new Vector2d(0, 0));\n\t\t\tVector3d newvec = camera.getWorldPoint(new Vector2d(dx * distance, dy * distance)).negate();\n\t\t\torigin.add(orivec).add(newvec);\n\t\t}\n\n\t\tdistance -= Mouse.getEventDWheel() * 0.01;\n\t\tdistance = VecmathUtil.clamp(distance, 0.01, 200);\n\n\t\tlong elapsed = System.currentTimeMillis() - initTime;\n\n\t\tint x = Mouse.getEventX();\n\t\tint y = Mouse.getEventY();\n\t\tVector3d start = new Vector3d();\n\t\tVector3d end = new Vector3d();\n\t\tif (camera.getRayForPixel(x, y, start, end)) {\n\t\t\tend.multiply(distance * 2);\n\t\t\tend.add(start);\n\t\t\tupdateSelection(start, end);\n\t\t}\n\n\t\tif (!Mouse.getEventButtonState() && camera.isValid() && elapsed > 500) {\n\t\t\tboolean inNeigButBounds = false;\n\t\t\tif (Mouse.getEventButton() == 1) {\n\t\t\t\tif (selection != null) {\n\t\t\t\t\thandleSelection(selection);\n\t\t\t\t}\n\t\t\t} else if (Mouse.getEventButton() == 0 && inNeigButBounds) {\n\t\t\t\trenderNeighbours = !renderNeighbours;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void updateSelection(Vector3d start, Vector3d end) {\n\t\tstart.add(origin);\n\t\tend.add(origin);\n\t\tList<RayTraceResult> hits = new ArrayList<>();\n\n\t\tLogisticsBlockGenericPipe.ignoreSideRayTrace = true;\n\t\tfor (DoubleCoordinates bc : configurables) {\n\t\t\tIBlockState blockState = bc.getBlockState(world);\n\t\t\tif (!blockState.getBlock().isAir(blockState, world, bc.getBlockPos())) {\n\t\t\t\tRayTraceResult hit = blockState.collisionRayTrace(world, bc.getBlockPos(), start.toVec3d(), end.toVec3d());\n\t\t\t\tif (hit != null && hit.typeOfHit != RayTraceResult.Type.MISS) {\n\t\t\t\t\thits.add(hit);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tLogisticsBlockGenericPipe.ignoreSideRayTrace = false;\n\t\tselection = null;\n\t\tRayTraceResult hit = getClosestHit(start.toVec3d(), hits);\n\t\tif (hit != null) {\n\t\t\tTileEntity te = world.getTileEntity(hit.getBlockPos());\n\t\t\tif (te != null) {\n\t\t\t\tselection = new SelectedFace(te, hit.sideHit, hit);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static RayTraceResult getClosestHit(Vec3d origin, Collection<RayTraceResult> candidates) {\n\t\tdouble minLengthSquared = Double.POSITIVE_INFINITY;\n\t\tRayTraceResult closest = null;\n\n\t\tfor (RayTraceResult hit : candidates) {\n\t\t\tif (hit != null) {\n\t\t\t\tdouble lengthSquared = hit.hitVec.squareDistanceTo(origin);\n\t\t\t\tif (lengthSquared < minLengthSquared) {\n\t\t\t\t\tminLengthSquared = lengthSquared;\n\t\t\t\t\tclosest = hit;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn closest;\n\t}\n\n\tpublic void drawScreen(int par1, int par2, float partialTick, Rectangle vp, Rectangle parentBounds) {\n\n\t\tif (!updateCamera(partialTick, vp.x, vp.y, vp.width, vp.height)) {\n\t\t\treturn;\n\t\t}\n\t\tapplyCamera(partialTick);\n\t\trenderScene();\n\t\trenderSelection();\n\n\t\trenderOverlay(par1, par2);\n\t}\n\n\tprivate void renderSelection() {\n\t\tif (selection == null) {\n\t\t\treturn;\n\t\t}\n\t\tBoundingBox bb = new BoundingBox(new DoubleCoordinates(selection.config));\n\n\t\tTextureAtlasSprite icon = (TextureAtlasSprite) Textures.LOGISTICS_SIDE_SELECTION;\n\t\tList<Vertex> corners = bb.getCornersWithUvForFace(selection.face, icon.getMinU(), icon.getMaxU(), icon.getMinV(), icon.getMaxV());\n\n\t\tGlStateManager.disableDepth();\n\t\tGlStateManager.disableLighting();\n\n\t\tRenderUtil.bindBlockTexture();\n\t\tBufferBuilder tes = Tessellator.getInstance().getBuffer();\n\t\tGlStateManager.color(1, 1, 1);\n\t\tVector3d trans = new Vector3d((-origin.x) + eye.x, (-origin.y) + eye.y, (-origin.z) + eye.z);\n\t\ttes.setTranslation(trans.x, trans.y, trans.z);\n\t\tRenderUtil.addVerticesToTessellator(corners, DefaultVertexFormats.POSITION_TEX, true);\n\t\tTessellator.getInstance().draw();\n\t\ttes.setTranslation(0, 0, 0);\n\t}\n\n\tprivate void renderOverlay(int mx, int my) {\n\t\tRectangle vp = camera.getViewport();\n\t\tScaledResolution scaledresolution = new ScaledResolution(mc);\n\n\t\tint vpx = vp.x / scaledresolution.getScaleFactor();\n\t\tint vph = vp.height / scaledresolution.getScaleFactor();\n\t\tint vpw = vp.width / scaledresolution.getScaleFactor();\n\t\tint vpy = (int) ((float) (vp.y + vp.height - 4) / (float) scaledresolution.getScaleFactor());\n\n\t\tGL11.glViewport(0, 0, mc.displayWidth, mc.displayHeight);\n\t\tGL11.glMatrixMode(GL11.GL_PROJECTION);\n\t\tGL11.glLoadIdentity();\n\t\tGL11.glOrtho(0.0D, scaledresolution.getScaledWidth_double(), scaledresolution\n\t\t\t\t.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D);\n\t\tGL11.glMatrixMode(GL11.GL_MODELVIEW);\n\t\tGL11.glLoadIdentity();\n\t\tGL11.glTranslatef(vpx, vpy, -2000.0F);\n\n\t\tGlStateManager.disableLighting();\n\t}\n\n\tprivate void renderScene() {\n\t\tGlStateManager.enableCull();\n\t\tGlStateManager.enableRescaleNormal();\n\n\t\tRenderHelper.disableStandardItemLighting();\n\t\tmc.entityRenderer.disableLightmap();\n\t\tRenderUtil.bindBlockTexture();\n\n\t\tGlStateManager.disableLighting();\n\t\tGlStateManager.enableTexture2D();\n\t\tGlStateManager.enableAlpha();\n\n\t\tVector3d trans = new Vector3d((-origin.x) + eye.x, (-origin.y) + eye.y, (-origin.z) + eye.z);\n\n\t\tBlockRenderLayer renderLayer = MinecraftForgeClient.getRenderLayer();\n\t\ttry {\n\t\t\tfor (BlockRenderLayer layer : BlockRenderLayer.values()) {\n\t\t\t\tForgeHooksClient.setRenderLayer(layer);\n\t\t\t\tsetGlStateForPass(layer, false);\n\t\t\t\tdoWorldRenderPass(trans, configurables, layer);\n\t\t\t}\n\n\t\t\tif (renderNeighbours) {\n\t\t\t\tfor (BlockRenderLayer layer : BlockRenderLayer.values()) {\n\t\t\t\t\tForgeHooksClient.setRenderLayer(layer);\n\t\t\t\t\tsetGlStateForPass(layer, true);\n\t\t\t\t\tdoWorldRenderPass(trans, neighbours, layer);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tForgeHooksClient.setRenderLayer(renderLayer);\n\t\t}\n\n\t\tRenderHelper.enableStandardItemLighting();\n\t\tGlStateManager.enableLighting();\n\t\tTileEntityRendererDispatcher.instance.entityX = origin.x - eye.x;\n\t\tTileEntityRendererDispatcher.instance.entityY = origin.y - eye.y;\n\t\tTileEntityRendererDispatcher.instance.entityZ = origin.z - eye.z;\n\t\tTileEntityRendererDispatcher.staticPlayerX = origin.x - eye.x;\n\t\tTileEntityRendererDispatcher.staticPlayerY = origin.y - eye.y;\n\t\tTileEntityRendererDispatcher.staticPlayerZ = origin.z - eye.z;\n\n\t\tfor (int pass = 0; pass < 2; pass++) {\n\t\t\tForgeHooksClient.setRenderPass(pass);\n\t\t\tsetGlStateForPass(pass, false);\n\t\t\tdoTileEntityRenderPass(configurables, pass);\n\t\t\tif (renderNeighbours) {\n\t\t\t\tsetGlStateForPass(pass, true);\n\t\t\t\tdoTileEntityRenderPass(neighbours, pass);\n\t\t\t}\n\t\t}\n\t\tForgeHooksClient.setRenderPass(-1);\n\t\tsetGlStateForPass(0, false);\n\t}\n\n\tprivate void doTileEntityRenderPass(List<DoubleCoordinates> blocks, int pass) {\n\t\tfor (DoubleCoordinates bc : blocks) {\n\t\t\tTileEntity tile = world.getTileEntity(bc.getBlockPos());\n\t\t\tif (tile != null) {\n\t\t\t\tif (tile.shouldRenderInPass(pass)) {\n\t\t\t\t\tVector3d at = new Vector3d(eye.x, eye.y, eye.z);\n\t\t\t\t\tat.x += bc.getXCoord() - origin.x;\n\t\t\t\t\tat.y += bc.getYCoord() - origin.y;\n\t\t\t\t\tat.z += bc.getZCoord() - origin.z;\n\t\t\t\t\tif (tile.getClass() == TileEntityChest.class) {\n\t\t\t\t\t\tTileEntityChest chest = (TileEntityChest) tile;\n\t\t\t\t\t\tif (chest.adjacentChestXNeg != null) {\n\t\t\t\t\t\t\ttile = chest.adjacentChestXNeg;\n\t\t\t\t\t\t\tat.x--;\n\t\t\t\t\t\t} else if (chest.adjacentChestZNeg != null) {\n\t\t\t\t\t\t\ttile = chest.adjacentChestZNeg;\n\t\t\t\t\t\t\tat.z--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tTileEntityRendererDispatcher.instance.render(tile, at.x, at.y, at.z, 0, -1, 0);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void doWorldRenderPass(Vector3d trans, List<DoubleCoordinates> blocks, BlockRenderLayer layer) {\n\n\t\tBufferBuilder wr = Tessellator.getInstance().getBuffer();\n\t\twr.begin(7, DefaultVertexFormats.BLOCK);\n\n\t\tTessellator.getInstance().getBuffer().setTranslation(trans.x, trans.y, trans.z);\n\n\t\tfor (DoubleCoordinates bc : blocks) {\n\t\t\tIBlockState blockState = world.getBlockState(bc.getBlockPos()).getActualState(world, bc.getBlockPos());\n\t\t\tif (blockState.getBlock().canRenderInLayer(blockState, layer)) {\n\t\t\t\trenderBlock(blockState, bc.getBlockPos(), world, Tessellator.getInstance().getBuffer());\n\t\t\t}\n\t\t}\n\n\t\tTessellator.getInstance().draw();\n\t\tTessellator.getInstance().getBuffer().setTranslation(0, 0, 0);\n\t}\n\n\tpublic void renderBlock(IBlockState state, BlockPos pos, IBlockAccess blockAccess, BufferBuilder worldRendererIn) {\n\n\t\ttry {\n\t\t\tBlockRendererDispatcher blockrendererdispatcher = mc.getBlockRendererDispatcher();\n\t\t\tEnumBlockRenderType type = state.getRenderType();\n\t\t\tif (type != EnumBlockRenderType.MODEL) {\n\t\t\t\tblockrendererdispatcher.renderBlock(state, pos, blockAccess, worldRendererIn);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tIBakedModel ibakedmodel = blockrendererdispatcher.getModelForState(state);\n\t\t\tstate = state.getBlock().getExtendedState(state, world, pos);\n\t\t\tblockrendererdispatcher.getBlockModelRenderer().renderModel(blockAccess, ibakedmodel, state, pos, worldRendererIn, false);\n\n\t\t} catch (Throwable ignored) {\n\t\t}\n\t}\n\n\tprivate void setGlStateForPass(BlockRenderLayer layer, boolean isNeighbour) {\n\t\tint pass = layer == BlockRenderLayer.TRANSLUCENT ? 1 : 0;\n\t\tsetGlStateForPass(pass, isNeighbour);\n\t}\n\n\tprivate void setGlStateForPass(int layer, boolean isNeighbour) {\n\n\t\tGlStateManager.color(1, 1, 1);\n\t\tif (isNeighbour) {\n\n\t\t\tGlStateManager.enableDepth();\n\t\t\tGlStateManager.enableBlend();\n\t\t\tfloat alpha = 1f;\n\t\t\tfloat col = 1f;\n\n\t\t\tGlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_CONSTANT_COLOR);\n\t\t\tGL14.glBlendColor(col, col, col, alpha);\n\t\t\treturn;\n\t\t}\n\n\t\tif (layer == 0) {\n\t\t\tGlStateManager.enableDepth();\n\t\t\tGlStateManager.disableBlend();\n\t\t\tGlStateManager.depthMask(true);\n\t\t} else {\n\t\t\tGlStateManager.enableBlend();\n\t\t\tGlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);\n\t\t\tGlStateManager.depthMask(false);\n\n\t\t}\n\n\t}\n\n\tprivate boolean updateCamera(float partialTick, int vpx, int vpy, int vpw, int vph) {\n\t\tif (vpw <= 0 || vph <= 0) {\n\t\t\treturn false;\n\t\t}\n\t\tcamera.setViewport(vpx, vpy, vpw, vph);\n\t\tcamera.setProjectionMatrixAsPerspective(30, 0.05, 50, vpw, vph);\n\t\teye.set(0, 0, distance);\n\t\tpitchRot.makeRotationX(Math.toRadians(pitch));\n\t\tyawRot.makeRotationY(Math.toRadians(yaw));\n\t\tpitchRot.transform(eye);\n\t\tyawRot.transform(eye);\n\t\tcamera.setViewMatrixAsLookAt(eye, RenderUtil.ZERO_V, RenderUtil.UP_V);\n\t\treturn camera.isValid();\n\t}\n\n\tprivate void applyCamera(float partialTick) {\n\t\tRectangle vp = camera.getViewport();\n\t\tGL11.glViewport(vp.x, vp.y, vp.width, vp.height);\n\t\tGL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);\n\t\tGL11.glMatrixMode(GL11.GL_PROJECTION);\n\t\tRenderUtil.loadMatrix(camera.getTransposeProjectionMatrix());\n\t\tGL11.glMatrixMode(GL11.GL_MODELVIEW);\n\t\tRenderUtil.loadMatrix(camera.getTransposeViewMatrix());\n\t\tGL11.glTranslatef(-(float) eye.x, -(float) eye.y, -(float) eye.z);\n\n\t}\n\n\tpublic static class SelectedFace {\n\n\t\tpublic TileEntity config;\n\t\tpublic EnumFacing face;\n\t\tpublic RayTraceResult hit;\n\n\t\tpublic SelectedFace(TileEntity config, EnumFacing face, RayTraceResult hit) {\n\t\t\tsuper();\n\t\t\tthis.config = config;\n\t\t\tthis.face = face;\n\t\t\tthis.hit = hit;\n\t\t}\n\t}\n\n\t/*\n\tprivate static class RenderPassHelper {\n\t\tprivate static Field worldRenderPass = null;\n\t\tprivate static int savedWorldRenderPass = -1;\n\t\tprivate static int savedEntityRenderPass = -1;\n\n\t\tstatic {\n\t\t\ttry {\n\t\t\t\tworldRenderPass = ForgeHooksClient.class.getDeclaredField(\"worldRenderPass\");\n\t\t\t\tworldRenderPass.setAccessible(true);\n\t\t\t} catch (Exception e) {\n\t\t\t\tLogisticsPipes.log.warn(\"Failed to access ForgeHooksClient.worldRenderPass because of: \" + e);\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\n\t\tpublic static void setBlockRenderPass(int pass) {\n\t\t\tsavedWorldRenderPass = ForgeHooksClient.getWorldRenderPass();\n\t\t\tsavedEntityRenderPass = MinecraftForgeClient.getRenderPass();\n\t\t\tsetBlockRenderPassImpl(pass);\n\t\t\tsetEntityRenderPass(pass);\n\t\t}\n\n\t\tprivate static void setBlockRenderPassImpl(int pass) {\n\t\t\tif (worldRenderPass != null) {\n\t\t\t\ttry {\n\t\t\t\t\tworldRenderPass.setInt(null, pass);\n\t\t\t\t} catch (Exception e) {\n\t\t\t\t\tLogisticsPipes.log.warn(\"Failed to access ForgeHooksClient.worldRenderPass because of: \" + e);\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t\tworldRenderPass = null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate static void clearBlockRenderPass() {\n\t\t\tsetBlockRenderPassImpl(savedWorldRenderPass);\n\t\t\tsetEntityRenderPass(savedEntityRenderPass);\n\t\t}\n\n\t\tprivate static void clearEntityRenderPass() {\n\t\t\tForgeHooksClient.setRenderPass(-1);\n\t\t}\n\n\t\tprivate static void setEntityRenderPass(int pass) {\n\t\t\tForgeHooksClient.setRenderPass(pass);\n\t\t}\n\t}\n*/\n\tprivate static class RenderUtil {\n\n\t\tpublic static final Vector3d UP_V = new Vector3d(0, 1, 0);\n\t\tpublic static final Vector3d ZERO_V = new Vector3d(0, 0, 0);\n\t\tprivate static final FloatBuffer MATRIX_BUFFER = GLAllocation.createDirectFloatBuffer(16);\n\t\tpublic static final ResourceLocation BLOCK_TEX = TextureMap.LOCATION_BLOCKS_TEXTURE;\n\n\t\tpublic static void loadMatrix(Matrix4d mat) {\n\t\t\tMATRIX_BUFFER.rewind();\n\t\t\tMATRIX_BUFFER.put((float) mat.m00);\n\t\t\tMATRIX_BUFFER.put((float) mat.m01);\n\t\t\tMATRIX_BUFFER.put((float) mat.m02);\n\t\t\tMATRIX_BUFFER.put((float) mat.m03);\n\t\t\tMATRIX_BUFFER.put((float) mat.m10);\n\t\t\tMATRIX_BUFFER.put((float) mat.m11);\n\t\t\tMATRIX_BUFFER.put((float) mat.m12);\n\t\t\tMATRIX_BUFFER.put((float) mat.m13);\n\t\t\tMATRIX_BUFFER.put((float) mat.m20);\n\t\t\tMATRIX_BUFFER.put((float) mat.m21);\n\t\t\tMATRIX_BUFFER.put((float) mat.m22);\n\t\t\tMATRIX_BUFFER.put((float) mat.m23);\n\t\t\tMATRIX_BUFFER.put((float) mat.m30);\n\t\t\tMATRIX_BUFFER.put((float) mat.m31);\n\t\t\tMATRIX_BUFFER.put((float) mat.m32);\n\t\t\tMATRIX_BUFFER.put((float) mat.m33);\n\t\t\tMATRIX_BUFFER.rewind();\n\t\t\tGL11.glLoadMatrix(MATRIX_BUFFER);\n\t\t}\n\n\t\tpublic static void bindBlockTexture() {\n\t\t\tMinecraft.getMinecraft().renderEngine.bindTexture(BLOCK_TEX);\n\t\t}\n\n\t\tpublic static void addVerticesToTessellator(List<Vertex> vertices, VertexFormat format, boolean doBegin) {\n\t\t\tif (vertices == null || vertices.isEmpty()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tTessellator tessellator = Tessellator.getInstance();\n\t\t\tBufferBuilder tes = tessellator.getBuffer();\n\t\t\tif (doBegin) {\n\t\t\t\ttes.begin(GL11.GL_QUADS, format);\n\t\t\t}\n\n\t\t\tfor (Vertex v : vertices) {\n\t\t\t\tfor (VertexFormatElement el : format.getElements()) {\n\t\t\t\t\tswitch (el.getUsage()) {\n\t\t\t\t\t\tcase COLOR:\n\t\t\t\t\t\t\tif (el.getType() == VertexFormatElement.EnumType.FLOAT) {\n\t\t\t\t\t\t\t\ttes.color(v.r(), v.g(), v.b(), v.a());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase NORMAL:\n\t\t\t\t\t\t\ttes.normal(v.nx(), v.ny(), v.nz());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase POSITION:\n\t\t\t\t\t\t\ttes.pos(v.x(), v.y(), v.z());\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase UV:\n\t\t\t\t\t\t\tif (el.getType() == VertexFormatElement.EnumType.FLOAT && v.uv != null) {\n\t\t\t\t\t\t\t\ttes.tex(v.u(), v.v());\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase GENERIC:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase PADDING:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttes.endVertex();\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/DictIdentifier.java",
    "content": "package logisticspipes.utils.item;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\npublic class DictIdentifier {\n\n\tprivate static List<DictIdentifier> identifiers = new ArrayList<>();\n\n\tstatic DictIdentifier getForId(int id) {\n\t\tif (DictIdentifier.identifiers.size() <= id) {\n\t\t\tArrayList<DictIdentifier> newidentifiers = new ArrayList<>(id + 1);\n\t\t\twhile (newidentifiers.size() <= id) {\n\t\t\t\tnewidentifiers.add(null);\n\t\t\t}\n\t\t\tfor (int i = 0; i < DictIdentifier.identifiers.size(); i++) {\n\t\t\t\tnewidentifiers.set(i, DictIdentifier.identifiers.get(i));\n\t\t\t}\n\t\t\tDictIdentifier.identifiers = newidentifiers;\n\t\t}\n\t\tDictIdentifier ident = DictIdentifier.identifiers.get(id);\n\t\tif (ident == null) {\n\t\t\tident = new DictIdentifier(id);\n\t\t\tDictIdentifier.identifiers.set(id, ident);\n\t\t}\n\t\treturn ident;\n\t}\n\n\tprivate final int id;\n\tprivate String name;\n\tprivate String category;\n\n\tprivate DictIdentifier(int id) {\n\t\tthis.id = id;\n\t}\n\n\tpublic String getName() {\n\t\tif (name == null) {\n\t\t\tname = OreDictionary.getOreName(id);\n\t\t}\n\t\treturn name;\n\t}\n\n\tpublic String getCategory() {\n\t\tif (category == null) {\n\t\t\tcategory = Pattern.compile(\"[A-Z].*\").matcher(getName()).replaceFirst(\"\");\n\t\t}\n\t\treturn category;\n\t}\n\n\tpublic boolean canNameMatch(DictIdentifier ident) {\n\t\treturn getName().equals(ident.getName());\n\t}\n\n\tpublic boolean canCategoryMatch(DictIdentifier ident) {\n\t\treturn getCategory().equals(ident.getCategory());\n\t}\n\n\tpublic void debugDumpData(boolean isClient, StringBuilder builder) {\n\t\tbuilder.append(id);\n\t\tbuilder.append(\"{\");\n\t\tbuilder.append(getName());\n\t\tbuilder.append(\"}\");\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/DictItemIdentifier.java",
    "content": "package logisticspipes.utils.item;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.List;\nimport java.util.concurrent.ConcurrentHashMap;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.oredict.OreDictionary;\n\nimport logisticspipes.LogisticsPipes;\n\npublic class DictItemIdentifier {\n\n\tprivate static ConcurrentHashMap<BitSet, DictItemIdentifier> identifiers = new ConcurrentHashMap<>();\n\n\t@Nullable\n\tpublic static DictItemIdentifier getDictItemIdentifier(@Nonnull ItemIdentifier itemIdent) {\n\t\tBitSet ids = new BitSet();\n\t\tboolean hasDict = false;\n\t\tfinal ItemStack stack = itemIdent.unsafeMakeNormalStack(1);\n\t\tif (stack.isEmpty()) {\n\t\t\tLogisticsPipes.log.error(\"Cannot make stack from item \" + itemIdent.toString() + \" -- item creates and empty stack!\");\n\t\t\treturn null;\n\t\t}\n\t\tfor (int oreId : OreDictionary.getOreIDs(stack)) {\n\t\t\tids.set(oreId);\n\t\t\thasDict = true;\n\t\t}\n\t\tif (!hasDict) {\n\t\t\treturn null;\n\t\t}\n\t\tDictItemIdentifier dictIdent = DictItemIdentifier.identifiers.get(ids);\n\t\tif (dictIdent == null) {\n\t\t\tdictIdent = new DictItemIdentifier(ids);\n\t\t\tDictItemIdentifier.identifiers.put(ids, dictIdent);\n\t\t}\n\t\treturn dictIdent;\n\t}\n\n\tprivate final List<DictIdentifier> parts = new ArrayList<>();\n\n\tprivate DictItemIdentifier(BitSet set) {\n\t\tint id = -1;\n\t\twhile ((id = set.nextSetBit(id + 1)) != -1) {\n\t\t\tparts.add(DictIdentifier.getForId(id));\n\t\t}\n\t}\n\n\tpublic boolean canMatch(DictItemIdentifier ident, boolean byName, boolean byCategory) {\n\t\tfor (DictIdentifier ident1 : parts) {\n\t\t\tfor (DictIdentifier ident2 : ident.parts) {\n\t\t\t\tif (ident1 == ident2) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (byName && ident1.canNameMatch(ident2)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (byCategory && ident1.canCategoryMatch(ident2)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic void debugDumpData(boolean isClient) {\n\t\tStringBuilder builder = new StringBuilder(\"DictIdentifiers: [\");\n\t\tboolean first = true;\n\t\tfor (DictIdentifier ident : parts) {\n\t\t\tif (!first) {\n\t\t\t\tbuilder.append(\", \");\n\t\t\t}\n\t\t\tident.debugDumpData(isClient, builder);\n\t\t\tfirst = false;\n\t\t}\n\t\tbuilder.append(\"]\");\n\t\tSystem.out.println(builder.toString());\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/ItemIdentifier.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * <p>\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.item;\n\nimport java.lang.ref.ReferenceQueue;\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicReferenceArray;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReadWriteLock;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.creativetab.CreativeTabs;\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.init.Blocks;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemBlock;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTBase;\nimport net.minecraft.nbt.NBTTagByte;\nimport net.minecraft.nbt.NBTTagByteArray;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagDouble;\nimport net.minecraft.nbt.NBTTagFloat;\nimport net.minecraft.nbt.NBTTagInt;\nimport net.minecraft.nbt.NBTTagIntArray;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.nbt.NBTTagLong;\nimport net.minecraft.nbt.NBTTagShort;\nimport net.minecraft.nbt.NBTTagString;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.fml.common.Loader;\nimport net.minecraftforge.fml.common.ModContainer;\nimport net.minecraftforge.fml.common.registry.ForgeRegistries;\nimport net.minecraftforge.registries.ForgeRegistry;\n\nimport lombok.AllArgsConstructor;\n\nimport logisticspipes.asm.addinfo.IAddInfo;\nimport logisticspipes.asm.addinfo.IAddInfoProvider;\nimport logisticspipes.items.LogisticsFluidContainer;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.utils.FinalNBTTagCompound;\nimport logisticspipes.utils.ReflectionHelper;\n\n/**\n * @author Krapht I have no bloody clue what different mods use to differate\n * between items except for itemID, there is metadata, damage, and\n * whatnot. so..... to avoid having to change all my bloody code every\n * time I need to support a new item targeted that would make it a\n * \"different\" item, I made this cache here A ItemIdentifier is\n * immutable, singleton and most importantly UNIQUE!\n */\npublic final class ItemIdentifier implements Comparable<ItemIdentifier>, ILPCCTypeHolder {\n\n\t//a key to look up a ItemIdentifier by Item:damage:tag\n\tprivate static class ItemKey {\n\n\t\tpublic final Item item;\n\t\tpublic final int itemDamage;\n\t\tpublic final FinalNBTTagCompound tag;\n\n\t\tpublic ItemKey(Item i, int d, FinalNBTTagCompound t) {\n\t\t\titem = i;\n\t\t\titemDamage = d;\n\t\t\ttag = t;\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean equals(Object that) {\n\t\t\tif (!(that instanceof ItemKey)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tItemKey i = (ItemKey) that;\n\t\t\treturn item == i.item && itemDamage == i.itemDamage && tag.equals(i.tag);\n\t\t}\n\n\t\t@Override\n\t\tpublic int hashCode() {\n\t\t\treturn item.hashCode() ^ itemDamage ^ tag.hashCode();\n\t\t}\n\t}\n\n\t//remember itemId/damage/tag so we can find GCed ItemIdentifiers\n\tprivate static class IDReference extends WeakReference<ItemIdentifier> {\n\n\t\tprivate final ItemKey key;\n\t\tprivate final int uniqueID;\n\n\t\tIDReference(ItemKey k, int u, ItemIdentifier id) {\n\t\t\tsuper(id, ItemIdentifier.keyRefQueue);\n\t\t\tkey = k;\n\t\t\tuniqueID = u;\n\t\t}\n\t}\n\n\tprivate interface IDamagedIdentifierHolder {\n\n\t\tItemIdentifier get(int damage);\n\n\t\tvoid set(int damage, ItemIdentifier ret);\n\n\t\tvoid ensureCapacity(int damage);\n\t}\n\n\tprivate static class MapDamagedItentifierHolder implements IDamagedIdentifierHolder {\n\n\t\tprivate final ConcurrentHashMap<Integer, ItemIdentifier> holder;\n\n\t\tpublic MapDamagedItentifierHolder() {\n\t\t\tholder = new ConcurrentHashMap<>(4096, 0.5f, 1);\n\t\t}\n\n\t\t@Override\n\t\tpublic ItemIdentifier get(int damage) {\n\t\t\treturn holder.get(damage);\n\t\t}\n\n\t\t@Override\n\t\tpublic void set(int damage, ItemIdentifier item) {\n\t\t\tholder.put(damage, item);\n\t\t}\n\n\t\t@Override\n\t\tpublic void ensureCapacity(int damage) {}\n\t}\n\n\tprivate static class ArrayDamagedItentifierHolder implements IDamagedIdentifierHolder {\n\n\t\tprivate AtomicReferenceArray<ItemIdentifier> holder;\n\n\t\tpublic ArrayDamagedItentifierHolder(int damage) {\n\t\t\t//round to nearest superior power of 2\n\t\t\tint newlen = 1 << (32 - Integer.numberOfLeadingZeros(damage));\n\t\t\tholder = new AtomicReferenceArray<>(newlen);\n\t\t}\n\n\t\t@Override\n\t\tpublic ItemIdentifier get(int damage) {\n\t\t\treturn holder.get(damage);\n\t\t}\n\n\t\t@Override\n\t\tpublic void set(int damage, ItemIdentifier ident) {\n\t\t\tholder.set(damage, ident);\n\t\t}\n\n\t\t@Override\n\t\tpublic void ensureCapacity(int damage) {\n\t\t\tif (holder.length() <= damage) {\n\t\t\t\tint newlen = 1 << (32 - Integer.numberOfLeadingZeros(damage));\n\t\t\t\tAtomicReferenceArray<ItemIdentifier> newdamages = new AtomicReferenceArray<>(newlen);\n\t\t\t\tfor (int i = 0; i < holder.length(); i++) {\n\t\t\t\t\tnewdamages.set(i, holder.get(i));\n\t\t\t\t}\n\t\t\t\tholder = newdamages;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\n\t//array of ItemIdentifiers for damage=0,tag=null items\n\tprivate final static ConcurrentHashMap<Item, ItemIdentifier> simpleIdentifiers = new ConcurrentHashMap<>(4096, 0.5f, 1);\n\n\t//array of arrays for items with damage>0 and tag==null\n\tprivate final static ConcurrentHashMap<Item, IDamagedIdentifierHolder> damageIdentifiers = new ConcurrentHashMap<>(4096, 0.5f, 1);\n\n\t//map for id+damage+tag -> ItemIdentifier lookup\n\tprivate final static HashMap<ItemKey, IDReference> keyRefMap = new HashMap<>(1024, 0.5f);\n\t//for tracking the tagUniqueIDs in use for a given Item\n\tprivate final static HashMap<Item, BitSet> tagIDsets = new HashMap<>(1024, 0.5f);\n\t//a referenceQueue to collect GCed identifier refs\n\tprivate final static ReferenceQueue<ItemIdentifier> keyRefQueue = new ReferenceQueue<>();\n\t//and locks to protect these\n\tprivate final static ReadWriteLock keyRefLock = new ReentrantReadWriteLock();\n\tprivate final static Lock keyRefRlock = ItemIdentifier.keyRefLock.readLock();\n\tprivate final static Lock keyRefWlock = ItemIdentifier.keyRefLock.writeLock();\n\n\t//helper thread to clean up references to GCed ItemIdentifiers\n\tprivate static final class ItemIdentifierCleanupThread extends Thread {\n\n\t\tpublic ItemIdentifierCleanupThread() {\n\t\t\tsetName(\"LogisticsPipes ItemIdentifier Cleanup Thread\");\n\t\t\tsetDaemon(true);\n\t\t\tstart();\n\t\t}\n\n\t\t@Override\n\t\tpublic void run() {\n\t\t\twhile (true) {\n\t\t\t\tIDReference r;\n\t\t\t\ttry {\n\t\t\t\t\tr = (IDReference) (ItemIdentifier.keyRefQueue.remove());\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tItemIdentifier.keyRefWlock.lock();\n\t\t\t\tdo {\n\t\t\t\t\t//value in the map might have been replaced in the meantime\n\t\t\t\t\tIDReference current = ItemIdentifier.keyRefMap.get(r.key);\n\t\t\t\t\tif (r == current) {\n\t\t\t\t\t\tItemIdentifier.keyRefMap.remove(r.key);\n\t\t\t\t\t\tItemIdentifier.tagIDsets.get(r.key.item).clear(r.uniqueID);\n\t\t\t\t\t}\n\t\t\t\t\tr = (IDReference) (ItemIdentifier.keyRefQueue.poll());\n\t\t\t\t} while (r != null);\n\t\t\t\tItemIdentifier.keyRefWlock.unlock();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static final ItemIdentifierCleanupThread cleanupThread = new ItemIdentifierCleanupThread();\n\n\t//Hide default constructor\n\tprivate ItemIdentifier(Item item, int itemDamage, FinalNBTTagCompound tag, int uniqueID) {\n\t\tthis.item = item;\n\t\tthis.itemDamage = itemDamage;\n\t\tthis.tag = tag;\n\t\tthis.uniqueID = uniqueID;\n\t}\n\n\tpublic final Item item;\n\tpublic final int itemDamage;\n\tpublic final FinalNBTTagCompound tag;\n\tpublic final int uniqueID;\n\n\tprivate int maxStackSize = 0;\n\n\tprivate ItemIdentifier _IDIgnoringNBT = null;\n\tprivate ItemIdentifier _IDIgnoringDamage = null;\n\tprivate ItemIdentifier _IDIgnoringData = null;\n\tprivate DictItemIdentifier _dict;\n\tprivate boolean canHaveDict = true;\n\tprivate String modName;\n\tprivate String creativeTabName;\n\n\tprivate static ItemIdentifier getOrCreateSimple(Item item, ItemIdentifier proposal) {\n\t\tif (proposal != null) {\n\t\t\tif (proposal.item == item && proposal.itemDamage == 0 && proposal.tag == null) {\n\t\t\t\treturn proposal;\n\t\t\t}\n\t\t}\n\t\t//no locking here. if 2 threads race and create the same ItemIdentifier, they end up .equal() and one of them ends up in the map\n\t\tItemIdentifier ret = ItemIdentifier.simpleIdentifiers.get(item);\n\t\tif (ret != null) {\n\t\t\treturn ret;\n\t\t}\n\t\tret = new ItemIdentifier(item, 0, null, 0);\n\t\tItemIdentifier.simpleIdentifiers.put(item, ret);\n\t\treturn ret;\n\t}\n\n\tprivate static ItemIdentifier getOrCreateDamage(Item item, int damage, ItemIdentifier proposal) {\n\t\tif (proposal != null) {\n\t\t\tif (proposal.item == item && proposal.itemDamage == damage && proposal.tag == null) {\n\t\t\t\treturn proposal;\n\t\t\t}\n\t\t}\n\t\t//again no locking, we can end up removing or overwriting ItemIdentifiers concurrently added by another thread, but that doesn't affect anything.\n\t\tIDamagedIdentifierHolder damages = ItemIdentifier.damageIdentifiers.get(item);\n\t\tif (damages == null) {\n\t\t\tif (item.getMaxDamage() < 32767) {\n\t\t\t\tdamages = new ArrayDamagedItentifierHolder(damage);\n\t\t\t} else {\n\t\t\t\tdamages = new MapDamagedItentifierHolder();\n\t\t\t}\n\t\t\tItemIdentifier.damageIdentifiers.put(item, damages);\n\t\t} else {\n\t\t\tdamages.ensureCapacity(damage);\n\t\t}\n\t\tItemIdentifier ret = damages.get(damage);\n\t\tif (ret != null) {\n\t\t\treturn ret;\n\t\t}\n\t\tret = new ItemIdentifier(item, damage, null, 0);\n\t\tdamages.set(damage, ret);\n\t\treturn ret;\n\t}\n\n\tprivate static ItemIdentifier getOrCreateTag(Item item, int damage, FinalNBTTagCompound tag) {\n\t\tItemKey k = new ItemKey(item, damage, tag);\n\t\tItemIdentifier.keyRefRlock.lock();\n\t\tIDReference r = ItemIdentifier.keyRefMap.get(k);\n\t\tif (r != null) {\n\t\t\tItemIdentifier ret = r.get();\n\t\t\tif (ret != null) {\n\t\t\t\tItemIdentifier.keyRefRlock.unlock();\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\t\tItemIdentifier.keyRefRlock.unlock();\n\t\tItemIdentifier.keyRefWlock.lock();\n\t\tr = ItemIdentifier.keyRefMap.get(k);\n\t\tif (r != null) {\n\t\t\tItemIdentifier ret = r.get();\n\t\t\tif (ret != null) {\n\t\t\t\tItemIdentifier.keyRefWlock.unlock();\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t}\n\t\tif (ItemIdentifier.tagIDsets.get(item) == null) {\n\t\t\tItemIdentifier.tagIDsets.put(item, new BitSet(16));\n\t\t}\n\t\tint nextUniqueID;\n\t\tif (r == null) {\n\t\t\tnextUniqueID = ItemIdentifier.tagIDsets.get(item).nextClearBit(1);\n\t\t\tItemIdentifier.tagIDsets.get(item).set(nextUniqueID);\n\t\t} else {\n\t\t\tnextUniqueID = r.uniqueID;\n\t\t}\n\t\tFinalNBTTagCompound finaltag = new FinalNBTTagCompound(tag);\n\t\tItemKey realKey = new ItemKey(item, damage, finaltag);\n\t\tItemIdentifier ret = new ItemIdentifier(item, damage, finaltag, nextUniqueID);\n\t\tItemIdentifier.keyRefMap.put(realKey, new IDReference(realKey, nextUniqueID, ret));\n\t\tItemIdentifier.keyRefWlock.unlock();\n\t\treturn ret;\n\t}\n\n\tpublic static ItemIdentifier get(Item item, int itemUndamagableDamage, NBTTagCompound tag) {\n\t\treturn get(item, itemUndamagableDamage, tag, null);\n\t}\n\n\tprivate static ItemIdentifier get(Item item, int itemUndamagableDamage, NBTTagCompound tag, ItemIdentifier proposal) {\n\t\tif (itemUndamagableDamage < 0) {\n\t\t\tthrow new IllegalArgumentException(\"Item Damage out of range\");\n\t\t}\n\t\tif (tag == null && itemUndamagableDamage == 0) {\n\t\t\t//no tag, no damage\n\t\t\treturn ItemIdentifier.getOrCreateSimple(item, proposal);\n\t\t} else if (tag == null) {\n\t\t\t//no tag, damage\n\t\t\treturn ItemIdentifier.getOrCreateDamage(item, itemUndamagableDamage, proposal);\n\t\t} else {\n\t\t\t//tag\n\t\t\treturn ItemIdentifier.getOrCreateTag(item, itemUndamagableDamage, new FinalNBTTagCompound(tag));\n\t\t}\n\t}\n\n\t@AllArgsConstructor\n\tpublic static class ItemStackAddInfo implements IAddInfo {\n\n\t\tprivate final ItemIdentifier ident;\n\t}\n\n\t@SuppressWarnings(\"ConstantConditions\")\n\t@Nonnull\n\tpublic static ItemIdentifier get(@Nonnull ItemStack itemStack) {\n\t\tItemIdentifier proposal = null;\n\t\tIAddInfoProvider prov = null;\n\t\tif (((Object) itemStack) instanceof IAddInfoProvider && !itemStack.hasTagCompound()) {\n\t\t\tprov = (IAddInfoProvider) (Object) itemStack;\n\t\t\tItemStackAddInfo info = prov.getLogisticsPipesAddInfo(ItemStackAddInfo.class);\n\t\t\tif (info != null) {\n\t\t\t\tproposal = info.ident;\n\t\t\t}\n\t\t}\n\t\tItemIdentifier ident = ItemIdentifier.get(itemStack.getItem(), itemStack.getItemDamage(), itemStack.getTagCompound(), proposal);\n\t\tif (ident != proposal && prov != null && !itemStack.hasTagCompound()) {\n\t\t\tprov.setLogisticsPipesAddInfo(new ItemStackAddInfo(ident));\n\t\t}\n\t\treturn ident;\n\t}\n\n\tpublic static List<ItemIdentifier> getMatchingNBTIdentifier(Item item, int itemData) {\n\t\t//inefficient, we'll have to add another map if this becomes a bottleneck\n\t\tArrayList<ItemIdentifier> resultlist = new ArrayList<>(16);\n\t\tItemIdentifier.keyRefRlock.lock();\n\t\tfor (IDReference r : ItemIdentifier.keyRefMap.values()) {\n\t\t\tItemIdentifier t = r.get();\n\t\t\tif (t != null && t.item == item && t.itemDamage == itemData) {\n\t\t\t\tresultlist.add(t);\n\t\t\t}\n\t\t}\n\t\tItemIdentifier.keyRefRlock.unlock();\n\t\treturn resultlist;\n\t}\n\n\t/* Instance Methods */\n\n\tpublic ItemIdentifier getUndamaged() {\n\t\tif (_IDIgnoringDamage == null) {\n\t\t\tif (!unsafeMakeNormalStack(1).isItemStackDamageable()) {\n\t\t\t\t_IDIgnoringDamage = this;\n\t\t\t} else {\n\t\t\t\tItemStack tstack = makeNormalStack(1);\n\t\t\t\ttstack.setItemDamage(0);\n\t\t\t\t_IDIgnoringDamage = ItemIdentifier.get(tstack);\n\t\t\t}\n\t\t}\n\t\treturn _IDIgnoringDamage;\n\t}\n\n\tpublic ItemIdentifier getIgnoringNBT() {\n\t\tif (_IDIgnoringNBT == null) {\n\t\t\tif (tag == null) {\n\t\t\t\t_IDIgnoringNBT = this;\n\t\t\t} else {\n\t\t\t\t_IDIgnoringNBT = ItemIdentifier.get(item, itemDamage, null, null);\n\t\t\t}\n\t\t}\n\t\treturn _IDIgnoringNBT;\n\t}\n\n\tpublic ItemIdentifier getIgnoringData() {\n\t\tif (_IDIgnoringData == null) {\n\t\t\tif (itemDamage == 0) {\n\t\t\t\t_IDIgnoringData = this;\n\t\t\t} else {\n\t\t\t\t_IDIgnoringData = ItemIdentifier.get(item, 0, tag, null);\n\t\t\t}\n\t\t}\n\t\treturn _IDIgnoringData;\n\t}\n\n\tpublic String getDebugName() {\n\t\treturn item.getTranslationKey() + \"(ID: \" + Item.getIdFromItem(item) + \", Damage: \" + itemDamage + \")\";\n\t}\n\n\t@Nonnull\n\tprivate String getName(@Nonnull ItemStack stack) {\n\t\treturn item.getItemStackDisplayName(stack);\n\t}\n\n\t@Nonnull\n\tpublic String getFriendlyName() {\n\t\treturn getName(unsafeMakeNormalStack(1));\n\t}\n\n\tpublic String getFriendlyNameCC() {\n\t\treturn MainProxy.proxy.getName(this);\n\t}\n\n\tpublic String getModName() {\n\t\tif (modName == null) {\n\t\t\tResourceLocation rl = item.getRegistryName();\n\t\t\tassert rl != null;\n\t\t\tMap<String, ModContainer> modList = Loader.instance().getIndexedModList();\n\t\t\tModContainer mc = modList.get(rl.getNamespace());\n\t\t\tif (mc == null) {\n\t\t\t\t// get mod that really registered this item\n\t\t\t\tMap<ResourceLocation, String> map = ReflectionHelper.invokePrivateMethod(ForgeRegistry.class, ForgeRegistries.ITEMS, \"getOverrideOwners\", \"getOverrideOwners\", new Class[0], new Object[0]);\n\n\t\t\t\tfinal String key = map.get(rl);\n\t\t\t\tif (key != null)\n\t\t\t\t\tmc = modList.get(key);\n\t\t\t}\n\n\t\t\tmodName = mc != null ? mc.getName() : \"UNKNOWN\";\n\t\t}\n\t\treturn modName;\n\t}\n\n\tpublic String getCreativeTabName() {\n\t\tif (creativeTabName == null) {\n\t\t\tCreativeTabs tab = item.getCreativeTab();\n\n\t\t\tif (tab == null && item instanceof ItemBlock) {\n\t\t\t\tBlock block = Block.getBlockFromItem(item);\n\t\t\t\tif (block != Blocks.AIR) {\n\t\t\t\t\ttab = block.getCreativeTab();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (tab != null) {\n\t\t\t\tcreativeTabName = tab.tabLabel;\n\t\t\t}\n\t\t}\n\t\treturn creativeTabName;\n\t}\n\n\t@Nonnull\n\tpublic ItemIdentifierStack makeStack(int stackSize) {\n\t\treturn new ItemIdentifierStack(this, stackSize);\n\t}\n\n\t@Nonnull\n\tpublic ItemStack unsafeMakeNormalStack(int stackSize) {\n\t\tItemStack stack = new ItemStack(item, stackSize, itemDamage);\n\t\tstack.setTagCompound(tag);\n\t\treturn stack;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack makeNormalStack(int stackSize) {\n\t\tItemStack stack = new ItemStack(item, stackSize, itemDamage);\n\t\tif (tag != null) {\n\t\t\tstack.setTagCompound(tag.copy());\n\t\t}\n\t\treturn stack;\n\t}\n\n\t@Nonnull\n\tpublic EntityItem makeEntityItem(int stackSize, World world, double x, double y, double z) {\n\t\treturn new EntityItem(world, x, y, z, makeNormalStack(stackSize));\n\t}\n\n\tpublic int getMaxStackSize() {\n\t\tif (maxStackSize == 0) {\n\t\t\tItemStack tstack = unsafeMakeNormalStack(1);\n\t\t\tint tstacksize = tstack.getMaxStackSize();\n\t\t\tif (tstack.isItemStackDamageable() && tstack.isItemDamaged()) {\n\t\t\t\ttstacksize = 1;\n\t\t\t}\n\t\t\ttstacksize = Math.max(1, Math.min(64, tstacksize));\n\t\t\tmaxStackSize = tstacksize;\n\t\t}\n\t\treturn maxStackSize;\n\t}\n\n\tprivate static Map<Integer, Object> getArrayAsMap(int[] array) {\n\t\tHashMap<Integer, Object> map = new HashMap<>();\n\t\tint i = 0;\n\t\tfor (int object : array) {\n\t\t\tmap.put(i, object);\n\t\t\ti++;\n\t\t}\n\t\treturn map;\n\t}\n\n\tprivate static Map<Integer, Object> getArrayAsMap(byte[] array) {\n\t\tHashMap<Integer, Object> map = new HashMap<>();\n\t\tint i = 1;\n\t\tfor (byte object : array) {\n\t\t\tmap.put(i, object);\n\t\t\ti++;\n\t\t}\n\t\treturn map;\n\t}\n\n\tpublic static Map<Object, Object> getNBTBaseAsMap(NBTBase nbt) throws SecurityException, IllegalArgumentException {\n\t\tif (nbt == null) return null;\n\n\t\tif (nbt instanceof NBTTagByte) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagByte\");\n\t\t\tmap.put(\"value\", ((NBTTagByte) nbt).getByte());\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagByteArray) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagByteArray\");\n\t\t\tmap.put(\"value\", ItemIdentifier.getArrayAsMap(((NBTTagByteArray) nbt).getByteArray()));\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagDouble) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagDouble\");\n\t\t\tmap.put(\"value\", ((NBTTagDouble) nbt).getDouble());\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagFloat) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagFloat\");\n\t\t\tmap.put(\"value\", ((NBTTagFloat) nbt).getFloat());\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagInt) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagInt\");\n\t\t\tmap.put(\"value\", ((NBTTagInt) nbt).getInt());\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagIntArray) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagIntArray\");\n\t\t\tmap.put(\"value\", ItemIdentifier.getArrayAsMap(((NBTTagIntArray) nbt).getIntArray()));\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagList) {\n\t\t\tHashMap<Integer, Object> content = new HashMap<>();\n\t\t\tint i = 1;\n\t\t\tfor (Object object : ((NBTTagList) nbt)) {\n\t\t\t\tif (object instanceof NBTBase) {\n\t\t\t\t\tcontent.put(i, ItemIdentifier.getNBTBaseAsMap((NBTBase) object));\n\t\t\t\t}\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagList\");\n\t\t\tmap.put(\"value\", content);\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagCompound) {\n\t\t\tHashMap<Object, Object> content = new HashMap<>();\n\t\t\tHashMap<Integer, Object> keys = new HashMap<>();\n\t\t\tint i = 1;\n\t\t\tfor (String key : ((NBTTagCompound) nbt).getKeySet()) {\n\t\t\t\tNBTBase value = ((NBTTagCompound) nbt).getTag(key);\n\t\t\t\tcontent.put(key, ItemIdentifier.getNBTBaseAsMap(value));\n\t\t\t\tkeys.put(i, key);\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagCompound\");\n\t\t\tmap.put(\"value\", content);\n\t\t\tmap.put(\"keys\", keys);\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagLong) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagLong\");\n\t\t\tmap.put(\"value\", ((NBTTagLong) nbt).getLong());\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagShort) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagShort\");\n\t\t\tmap.put(\"value\", ((NBTTagShort) nbt).getShort());\n\t\t\treturn map;\n\t\t} else if (nbt instanceof NBTTagString) {\n\t\t\tHashMap<Object, Object> map = new HashMap<>();\n\t\t\tmap.put(\"type\", \"NBTTagString\");\n\t\t\tmap.put(\"value\", ((NBTTagString) nbt).getString());\n\t\t\treturn map;\n\t\t} else {\n\t\t\tthrow new UnsupportedOperationException(\"Unsupported NBTBase of type:\" + nbt.getClass().getName());\n\t\t}\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn getModName() + \":\" + getFriendlyName() + \", \" + Item.getIdFromItem(item) + \":\" + itemDamage;\n\t}\n\n\t@Override\n\tpublic int compareTo(ItemIdentifier o) {\n\t\tint c = Item.getIdFromItem(item) - Item.getIdFromItem(o.item);\n\t\tif (c != 0) {\n\t\t\treturn c;\n\t\t}\n\t\tc = itemDamage - o.itemDamage;\n\t\tif (c != 0) {\n\t\t\treturn c;\n\t\t}\n\t\tc = uniqueID - o.uniqueID;\n\t\treturn c;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object that) {\n\t\tif (that instanceof ItemIdentifierStack) {\n\t\t\tthrow new IllegalStateException(\"Comparison between ItemIdentifierStack and ItemIdentifier -- did you forget a .getItem() in your code?\");\n\t\t}\n\t\tif (!(that instanceof ItemIdentifier)) {\n\t\t\treturn false;\n\t\t}\n\t\tItemIdentifier i = (ItemIdentifier) that;\n\t\treturn this.equals(i);\n\n\t}\n\n\tpublic boolean equals(ItemIdentifier that) {\n\t\tif (that == null) return false;\n\t\treturn item == that.item && itemDamage == that.itemDamage && uniqueID == that.uniqueID;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\tif (tag == null) {\n\t\t\treturn item.hashCode() + itemDamage;\n\t\t} else {\n\t\t\treturn (item.hashCode() + itemDamage) ^ tag.hashCode();\n\t\t}\n\t}\n\n\tpublic boolean equalsForCrafting(ItemIdentifier item) {\n\t\treturn this.item == item.item && (item.isDamageable() || (itemDamage == item.itemDamage));\n\t}\n\n\tpublic boolean equalsWithoutNBT(@Nonnull ItemStack stack) {\n\t\treturn item == stack.getItem() && itemDamage == stack.getItemDamage();\n\t}\n\n\tpublic boolean equalsWithoutNBT(ItemIdentifier item) {\n\t\treturn this.item == item.item && itemDamage == item.itemDamage;\n\t}\n\n\tpublic boolean isDamageable() {\n\t\treturn unsafeMakeNormalStack(1).isItemStackDamageable();\n\t}\n\n\tpublic boolean isFluidContainer() {\n\t\treturn item instanceof LogisticsFluidContainer;\n\t}\n\n\t@Nullable\n\tpublic DictItemIdentifier getDictIdentifiers() {\n\t\tif (_dict == null && canHaveDict) {\n\t\t\t_dict = DictItemIdentifier.getDictItemIdentifier(this);\n\t\t\tcanHaveDict = false;\n\t\t}\n\t\treturn _dict;\n\t}\n\n\tpublic void debugDumpData(boolean isClient) {\n\t\tSystem.out.println((isClient ? \"Client\" : \"Server\") + \" Item: \" + Item.getIdFromItem(item) + \":\" + itemDamage + \" uniqueID \" + uniqueID);\n\t\tStringBuilder sb = new StringBuilder();\n\t\tsb.append(\"Tag: \");\n\t\tdebugDumpTag(tag, sb);\n\t\tSystem.out.println(sb.toString());\n\t\tSystem.out.println(\"Damageable: \" + isDamageable());\n\t\tSystem.out.println(\"MaxStackSize: \" + getMaxStackSize());\n\t\tif (getUndamaged() == this) {\n\t\t\tSystem.out.println(\"Undamaged: this\");\n\t\t} else {\n\t\t\tSystem.out.println(\"Undamaged:\");\n\t\t\tgetUndamaged().debugDumpData(isClient);\n\t\t}\n\t\tSystem.out.println(\"Mod: \" + getModName());\n\t\tSystem.out.println(\"CreativeTab: \" + getCreativeTabName());\n\t\tif (getDictIdentifiers() != null) {\n\t\t\tgetDictIdentifiers().debugDumpData(isClient);\n\t\t}\n\t}\n\n\tprivate void debugDumpTag(NBTBase nbt, StringBuilder sb) {\n\t\tif (nbt == null) {\n\t\t\tsb.append(\"null\");\n\t\t\treturn;\n\t\t}\n\t\tif (nbt instanceof NBTTagByte) {\n\t\t\tsb.append(\"TagByte(data=\").append(((NBTTagByte) nbt).getByte()).append(\")\");\n\t\t} else if (nbt instanceof NBTTagShort) {\n\t\t\tsb.append(\"TagShort(data=\").append(((NBTTagShort) nbt).getShort()).append(\")\");\n\t\t} else if (nbt instanceof NBTTagInt) {\n\t\t\tsb.append(\"TagInt(data=\").append(((NBTTagInt) nbt).getInt()).append(\")\");\n\t\t} else if (nbt instanceof NBTTagLong) {\n\t\t\tsb.append(\"TagLong(data=\").append(((NBTTagLong) nbt).getLong()).append(\")\");\n\t\t} else if (nbt instanceof NBTTagFloat) {\n\t\t\tsb.append(\"TagFloat(data=\").append(((NBTTagFloat) nbt).getFloat()).append(\")\");\n\t\t} else if (nbt instanceof NBTTagDouble) {\n\t\t\tsb.append(\"TagDouble(data=\").append(((NBTTagDouble) nbt).getDouble()).append(\")\");\n\t\t} else if (nbt instanceof NBTTagString) {\n\t\t\tsb.append(\"TagString(data=\\\"\").append(((NBTTagString) nbt).getString()).append(\"\\\")\");\n\t\t} else if (nbt instanceof NBTTagByteArray) {\n\t\t\tsb.append(\"TagByteArray(data=\");\n\t\t\tfor (int i = 0; i < ((NBTTagByteArray) nbt).getByteArray().length; i++) {\n\t\t\t\tsb.append(((NBTTagByteArray) nbt).getByteArray()[i]);\n\t\t\t\tif (i < ((NBTTagByteArray) nbt).getByteArray().length - 1) {\n\t\t\t\t\tsb.append(\",\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb.append(\")\");\n\t\t} else if (nbt instanceof NBTTagIntArray) {\n\t\t\tsb.append(\"TagIntArray(data=\");\n\t\t\tfor (int i = 0; i < ((NBTTagIntArray) nbt).getIntArray().length; i++) {\n\t\t\t\tsb.append(((NBTTagIntArray) nbt).getIntArray()[i]);\n\t\t\t\tif (i < ((NBTTagIntArray) nbt).getIntArray().length - 1) {\n\t\t\t\t\tsb.append(\",\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb.append(\")\");\n\t\t} else if (nbt instanceof NBTTagList) {\n\t\t\tsb.append(\"TagList(data=\");\n\t\t\tfor (int i = 0; i < ((NBTTagList) nbt).tagCount(); i++) {\n\t\t\t\tdebugDumpTag((((NBTTagList) nbt).get(i)), sb);\n\t\t\t\tif (i < ((NBTTagList) nbt).tagCount() - 1) {\n\t\t\t\t\tsb.append(\",\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb.append(\")\");\n\t\t} else if (nbt instanceof NBTTagCompound) {\n\t\t\tsb.append(\"TagCompound(data=\");\n\t\t\tfor (Iterator<String> iter = ((NBTTagCompound) nbt).getKeySet().iterator(); iter.hasNext(); ) {\n\t\t\t\tString key = iter.next();\n\t\t\t\tNBTBase value = ((NBTTagCompound) nbt).getTag(key);\n\t\t\t\tsb.append(\"\\\"\").append(key).append(\"\\\"=\");\n\t\t\t\tdebugDumpTag((value), sb);\n\t\t\t\tif (iter.hasNext()) {\n\t\t\t\t\tsb.append(\",\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsb.append(\")\");\n\t\t} else {\n\t\t\tsb.append(nbt.getClass().getName()).append(\"(?)\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/ItemIdentifierInventory.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * <p>\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.item;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.ITextComponent;\nimport net.minecraft.util.text.TextComponentString;\nimport net.minecraft.world.World;\n\nimport logisticspipes.LogisticsPipes;\nimport network.rs485.logisticspipes.IStore;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.FluidIdentifier;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory;\nimport network.rs485.logisticspipes.inventory.SlotAccess;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\n\npublic class ItemIdentifierInventory\n\t\timplements IStore, Iterable<Pair<ItemIdentifierStack, Integer>>, IItemIdentifierInventory {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate final ItemIdentifierStack[] _contents;\n\tprivate final String _name;\n\tprivate final int _stackLimit;\n\t@Nonnull\n\tprivate final HashMap<ItemIdentifier, Integer> _contentsMap;\n\tprivate final HashSet<ItemIdentifier> _contentsUndamagedSet;\n\tprivate final HashSet<ItemIdentifier> _contentsNoNBTSet;\n\tprivate final HashSet<ItemIdentifier> _contentsUndamagedNoNBTSet;\n\tprivate final boolean isLiquidInventory;\n\n\tprivate final LinkedList<ISimpleInventoryEventHandler> _listener = new LinkedList<>();\n\n\tpublic final SlotAccess slotAccess = new SlotAccess() {\n\n\t\t@Override\n\t\tpublic void mergeSlots(int intoSlot, int fromSlot) {\n\t\t\tif (_contents[intoSlot] == null) {\n\t\t\t\t_contents[intoSlot] = _contents[fromSlot];\n\t\t\t} else {\n\t\t\t\t_contents[intoSlot].setStackSize(_contents[intoSlot].getStackSize() + _contents[fromSlot].getStackSize());\n\t\t\t}\n\t\t\t_contents[fromSlot] = null;\n\t\t\tupdateContents();\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canMerge(int intoSlot, int fromSlot) {\n\t\t\treturn _contents[intoSlot].getItem().equals(_contents[fromSlot].getItem());\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean isSlotEmpty(int idx) {\n\t\t\treturn _contents[idx] == null;\n\t\t}\n\n\t};\n\n\tpublic ItemIdentifierInventory(int size, String name, int stackLimit, boolean liquidInv) {\n\t\t_contents = new ItemIdentifierStack[size];\n\t\t_name = name;\n\t\t_stackLimit = stackLimit;\n\t\t_contentsMap = new HashMap<>((int) (size * 1.5));\n\t\t_contentsUndamagedSet = new HashSet<>((int) (size * 1.5));\n\t\t_contentsNoNBTSet = new HashSet<>((int) (size * 1.5));\n\t\t_contentsUndamagedNoNBTSet = new HashSet<>((int) (size * 1.5));\n\t\tisLiquidInventory = liquidInv;\n\t}\n\n\tpublic ItemIdentifierInventory(int size, String name, int stackLimit) {\n\t\tthis(size, name, stackLimit, false);\n\t}\n\n\tpublic ItemIdentifierInventory(@Nonnull ItemIdentifierInventory copy) {\n\t\t_contents = Arrays.copyOf(copy._contents, copy._contents.length);\n\t\tfor (int i = 0; i < _contents.length; i++) {\n\t\t\tif (copy._contents[i] != null) _contents[i] = new ItemIdentifierStack(copy._contents[i]);\n\t\t}\n\t\t_name = copy._name;\n\t\t_stackLimit = copy._stackLimit;\n\t\t_contentsMap = new HashMap<>(copy._contentsMap);\n\t\t_contentsUndamagedSet = new HashSet<>(copy._contentsUndamagedSet);\n\t\t_contentsNoNBTSet = new HashSet<>(copy._contentsNoNBTSet);\n\t\t_contentsUndamagedNoNBTSet = new HashSet<>(copy._contentsUndamagedNoNBTSet);\n\t\tisLiquidInventory = copy.isLiquidInventory;\n\t}\n\n\tpublic static void dropItems(World world, @Nonnull ItemStack stack, BlockPos pos) {\n\t\tdropItems(world, stack, pos.getX(), pos.getY(), pos.getZ());\n\t}\n\n\tpublic static void dropItems(World world, @Nonnull ItemStack stack, int i, int j, int k) {\n\t\tif (stack.isEmpty()) return;\n\t\tfloat f1 = 0.7F;\n\t\tdouble d = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;\n\t\tdouble d1 = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;\n\t\tdouble d2 = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;\n\t\tEntityItem entityitem = new EntityItem(world, i + d, j + d1, k + d2, stack);\n\t\tentityitem.setPickupDelay(10);\n\t\tworld.spawnEntity(entityitem);\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn _contents.length;\n\t}\n\n\t@Override\n\t@Deprecated\n\t@Nonnull\n\tpublic ItemStack getStackInSlot(int i) {\n\t\tif (_contents[i] == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\treturn _contents[i].makeNormalStack();\n\t}\n\n\t@Override\n\tpublic ItemIdentifierStack getIDStackInSlot(int i) {\n\t\treturn _contents[i];\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack decrStackSize(int slot, int count) {\n\t\tif (_contents[slot] == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tItemStack ret = _contents[slot].makeNormalStack();\n\t\tif (_contents[slot].getStackSize() > count) {\n\t\t\tret.setCount(count);\n\t\t\t_contents[slot].setStackSize(_contents[slot].getStackSize() - count);\n\t\t} else {\n\t\t\t_contents[slot] = null;\n\t\t}\n\t\tupdateContents();\n\t\treturn ret;\n\t}\n\n\t@Override\n\tpublic void setInventorySlotContents(int i, @Nonnull ItemStack itemstack) {\n\t\tif (itemstack.isEmpty()) {\n\t\t\t_contents[i] = null;\n\t\t} else {\n\t\t\tif (isInvalidStack(itemstack)) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tnew UnsupportedOperationException(\"Not valid for this Inventory: (\" + itemstack + \")\")\n\t\t\t\t\t\t\t.printStackTrace();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_contents[i] = ItemIdentifierStack.getFromStack(itemstack);\n\t\t}\n\t\tupdateContents();\n\t}\n\n\t@Override\n\tpublic void setInventorySlotContents(int i, ItemIdentifierStack itemstack) {\n\t\tif (itemstack == null) {\n\t\t\t_contents[i] = null;\n\t\t} else {\n\t\t\tif (!isValidStack(itemstack)) {\n\t\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\t\tnew UnsupportedOperationException(\"Not valid for this Inventory: (\" + itemstack + \")\")\n\t\t\t\t\t\t\t.printStackTrace();\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_contents[i] = itemstack;\n\t\t}\n\t\tupdateContents();\n\t}\n\n\t@Override\n\tpublic int getInventoryStackLimit() {\n\t\treturn _stackLimit;\n\t}\n\n\t@Override\n\tpublic void markDirty() {\n\t\tupdateContents();\n\t\tfor (ISimpleInventoryEventHandler handler : _listener) {\n\t\t\thandler.InventoryChanged(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isUsableByPlayer(@Nonnull EntityPlayer entityplayer) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void openInventory(@Nonnull EntityPlayer player) {}\n\n\t@Override\n\tpublic void closeInventory(@Nonnull EntityPlayer player) {}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\treadFromNBT(nbttagcompound, \"\");\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound, String prefix) {\n\t\t// FIXME: after 1.12 remove this items appending crap\n\t\tNBTTagList nbttaglist = nbttagcompound.getTagList(prefix + \"items\", nbttagcompound.getId());\n\n\t\tArrays.fill(_contents, null);\n\t\tfor (int j = 0; j < nbttaglist.tagCount(); ++j) {\n\t\t\tNBTTagCompound nbttagcompound2 = nbttaglist.getCompoundTagAt(j);\n\t\t\tint index = nbttagcompound2.getInteger(\"index\");\n\t\t\tif (index < _contents.length) {\n\t\t\t\tItemStack stack = ItemStackLoader.loadAndFixItemStackFromNBT(nbttagcompound2);\n\t\t\t\tItemIdentifierStack itemstack = ItemIdentifierStack.getFromStack(stack);\n\t\t\t\tif (isValidStack(itemstack)) {\n\t\t\t\t\t_contents[index] = itemstack;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tLogisticsPipes.log.fatal(\"SimpleInventory: java.lang.ArrayIndexOutOfBoundsException: \" + index + \" of \"\n\t\t\t\t\t\t+ _contents.length);\n\t\t\t}\n\t\t}\n\t\tupdateContents();\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\twriteToNBT(nbttagcompound, \"\");\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound, String prefix) {\n\t\tNBTTagList nbttaglist = new NBTTagList();\n\t\tfor (int j = 0; j < _contents.length; ++j) {\n\t\t\tif (_contents[j] != null && _contents[j].getStackSize() > 0) {\n\t\t\t\tNBTTagCompound nbttagcompound2 = new NBTTagCompound();\n\t\t\t\tnbttaglist.appendTag(nbttagcompound2);\n\t\t\t\tnbttagcompound2.setInteger(\"index\", j);\n\t\t\t\t_contents[j].unsafeMakeNormalStack().writeToNBT(nbttagcompound2);\n\t\t\t}\n\t\t}\n\t\tnbttagcompound.setTag(prefix + \"items\", nbttaglist);\n\t\tnbttagcompound.setInteger(prefix + \"itemsCount\", _contents.length);\n\t}\n\n\tpublic void dropContents(World world, BlockPos pos) {\n\t\tdropContents(world, pos.getX(), pos.getY(), pos.getZ());\n\t}\n\n\tpublic void dropContents(World world, int posX, int posY, int posZ) {\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tfor (int i = 0; i < _contents.length; i++) {\n\t\t\t\twhile (_contents[i] != null) {\n\t\t\t\t\tItemStack todrop = decrStackSize(i, _contents[i].getItem().getMaxStackSize());\n\t\t\t\t\tItemIdentifierInventory.dropItems(world, todrop, posX, posY, posZ);\n\t\t\t\t}\n\t\t\t}\n\t\t\tupdateContents();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addListener(@Nonnull ISimpleInventoryEventHandler listener) {\n\t\tif (!_listener.contains(listener)) {\n\t\t\t_listener.add(listener);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void removeListener(@Nonnull ISimpleInventoryEventHandler listener) {\n\t\t_listener.remove(listener);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack removeStackFromSlot(int i) {\n\t\tif (_contents[i] == null) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\n\t\tItemStack stackToTake = _contents[i].makeNormalStack();\n\t\t_contents[i] = null;\n\t\tupdateContents();\n\t\treturn stackToTake;\n\t}\n\n\t@Override\n\tpublic void handleItemIdentifierList(Collection<ItemIdentifierStack> _allItems) {\n\t\tint i = 0;\n\t\tfor (ItemIdentifierStack stack : _allItems) {\n\t\t\tif (_contents.length <= i) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t_contents[i] = stack;\n\t\t\ti++;\n\t\t}\n\t\tmarkDirty();\n\t}\n\n\tprivate int tryAddToSlot(int i, @Nonnull ItemStack stack, int realstacklimit) {\n\t\tif (isInvalidStack(stack)) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tnew UnsupportedOperationException(\"Not valid for this Inventory: (\" + stack + \")\").printStackTrace();\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t\tItemIdentifierStack slot = _contents[i];\n\n\t\tif (slot == null) {\n\t\t\t_contents[i] = ItemIdentifierStack.getFromStack(stack);\n\t\t\t_contents[i].setStackSize(Math.min(_contents[i].getStackSize(), realstacklimit));\n\t\t\treturn _contents[i].getStackSize();\n\t\t}\n\n\t\tItemIdentifier stackIdent = ItemIdentifier.get(stack);\n\t\tItemIdentifier slotIdent = slot.getItem();\n\n\t\tif (slotIdent.equals(stackIdent)) {\n\t\t\tslot.setStackSize(slot.getStackSize() + stack.getCount());\n\n\t\t\tif (slot.getStackSize() > realstacklimit) {\n\t\t\t\tint ans = stack.getCount() - (slot.getStackSize() - realstacklimit);\n\t\t\t\tslot.setStackSize(realstacklimit);\n\t\t\t\treturn ans;\n\t\t\t} else {\n\t\t\t\treturn stack.getCount();\n\t\t\t}\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tpublic int addCompressed(@Nonnull ItemStack stack, boolean ignoreMaxStackSize) {\n\t\tif (stack.isEmpty()) return 0;\n\n\t\tif (isInvalidStack(stack)) {\n\t\t\tif (LogisticsPipes.isDEBUG()) {\n\t\t\t\tnew UnsupportedOperationException(\"Not valid for this Inventory: (\" + stack + \")\").printStackTrace();\n\t\t\t}\n\t\t\treturn stack.getCount();\n\t\t}\n\n\t\tstack = stack.copy();\n\n\t\tItemIdentifier stackIdent = ItemIdentifier.get(stack);\n\t\tint stacklimit = _stackLimit;\n\n\t\tif (!ignoreMaxStackSize) {\n\t\t\tstacklimit = Math.min(stacklimit, stackIdent.getMaxStackSize());\n\t\t}\n\n\t\tfor (int i = 0; i < _contents.length; i++) {\n\t\t\tif (stack.getCount() <= 0) break;\n\t\t\tif (_contents[i] == null) continue; //Skip Empty Slots on first attempt.\n\n\t\t\tint added = tryAddToSlot(i, stack, stacklimit);\n\t\t\tstack.setCount(stack.getCount() - added);\n\t\t}\n\n\t\tfor (int i = 0; i < _contents.length; i++) {\n\t\t\tif (stack.getCount() <= 0) break;\n\n\t\t\tint added = tryAddToSlot(i, stack, stacklimit);\n\t\t\tstack.setCount(stack.getCount() - added);\n\t\t}\n\n\t\tmarkDirty();\n\t\treturn stack.getCount();\n\t}\n\n\t/* InventoryUtil-like functions */\n\n\tprivate void updateContents() {\n\t\t_contentsMap.clear();\n\t\t_contentsUndamagedSet.clear();\n\t\t_contentsNoNBTSet.clear();\n\t\t_contentsUndamagedNoNBTSet.clear();\n\t\tfor (ItemIdentifierStack _content : _contents) {\n\t\t\tif (_content == null) continue;\n\n\t\t\tItemIdentifier itemId = _content.getItem();\n\t\t\t_contentsMap.merge(itemId, _content.getStackSize(), Integer::sum);\n\t\t\t_contentsUndamagedSet.add(itemId\n\t\t\t\t\t.getUndamaged()); // add is cheaper than check then add; it just returns false if it is already there\n\t\t\t_contentsNoNBTSet.add(itemId\n\t\t\t\t\t.getIgnoringNBT()); // add is cheaper than check then add; it just returns false if it is already there\n\t\t\t_contentsUndamagedNoNBTSet.add(itemId.getIgnoringNBT()\n\t\t\t\t\t.getUndamaged()); // add is cheaper than check then add; it just returns false if it is already there\n\t\t}\n\t}\n\n\t@Override\n\tpublic int itemCount(@Nonnull final ItemIdentifier item) {\n\t\treturn _contentsMap.getOrDefault(item, 0);\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Map<ItemIdentifier, Integer> getItemsAndCount() {\n\t\treturn _contentsMap;\n\t}\n\n\t@Override\n\tpublic boolean containsItem(final ItemIdentifier item) {\n\t\treturn _contentsMap.containsKey(item);\n\t}\n\n\t@Override\n\tpublic boolean containsUndamagedItem(@Nonnull final ItemIdentifier item) {\n\t\treturn _contentsUndamagedSet.contains(item);\n\t}\n\n\t@Override\n\tpublic boolean containsExcludeNBTItem(@Nonnull final ItemIdentifier item) {\n\t\treturn _contentsNoNBTSet.contains(item);\n\t}\n\n\t@Override\n\tpublic boolean containsUndamagedExcludeNBTItem(@Nonnull final ItemIdentifier item) {\n\t\treturn _contentsUndamagedNoNBTSet.contains(item);\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn _contentsMap.isEmpty();\n\t}\n\n\t@Override\n\tpublic boolean isItemValidForSlot(int i, @Nonnull ItemStack itemstack) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic int getField(int id) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void setField(int id, int value) {}\n\n\t@Override\n\tpublic int getFieldCount() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void clear() {\n\t\tArrays.fill(_contents, null);\n\t\tupdateContents();\n\t}\n\n\t@Override\n\tpublic void clearInventorySlotContents(int i) {\n\t\t_contents[i] = null;\n\t\tupdateContents();\n\t}\n\n\t@Override\n\tpublic void recheckStackLimit() {\n\t\tfor (ItemIdentifierStack _content : _contents) {\n\t\t\tif (_content != null) {\n\t\t\t\t_content.setStackSize(Math.min(_content.getStackSize(), _stackLimit));\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate boolean isInvalidStack(@Nonnull ItemStack stack) {\n\t\tif (isLiquidInventory && !stack.isEmpty()) {\n\t\t\treturn FluidIdentifier.get(stack) == null;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate boolean isValidStack(ItemIdentifierStack stack) {\n\t\tif (stack == null) return true;\n\t\tif (isLiquidInventory) {\n\t\t\treturn FluidIdentifier.get(stack.getItem()) != null;\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Iterator<Pair<ItemIdentifierStack, Integer>> iterator() {\n\t\tfinal Iterator<ItemIdentifierStack> iter = Arrays.asList(_contents).iterator();\n\t\treturn new Iterator<Pair<ItemIdentifierStack, Integer>>() {\n\n\t\t\tint pos = -1;\n\n\t\t\t@Override\n\t\t\tpublic boolean hasNext() {\n\t\t\t\treturn iter.hasNext();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic Pair<ItemIdentifierStack, Integer> next() {\n\t\t\t\tpos++;\n\t\t\t\treturn new Pair<>(iter.next(), pos);\n\t\t\t}\n\t\t};\n\t}\n\n\tpublic void clearGrid() {\n\t\tfor (int i = 0; i < getSizeInventory(); i++) {\n\t\t\t_contents[i] = null;\n\t\t}\n\t\tupdateContents();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic String getName() {\n\t\treturn _name;\n\t}\n\n\t@Override\n\tpublic boolean hasCustomName() {\n\t\treturn true;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ITextComponent getDisplayName() {\n\t\treturn new TextComponentString(getName());\n\t}\n\n\tpublic NonNullList<ItemStack> toNonNullList() {\n\t\tNonNullList<ItemStack> list = NonNullList.create();\n\t\tlist.addAll(0, Arrays.stream(_contents)\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.map(ItemIdentifierStack::makeNormalStack)\n\t\t\t\t.collect(Collectors.toList()));\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic @Nonnull\n\tList<String> getClientInformation() {\n\t\treturn Arrays.stream(_contents).filter(Objects::nonNull).map(String::valueOf).collect(Collectors.toList());\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterable<Pair<ItemIdentifierStack, Integer>> contents() {\n\t\treturn this;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic SlotAccess getSlotAccess() {\n\t\treturn slotAccess;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/ItemIdentifierStack.java",
    "content": "/*\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.item;\n\nimport java.util.LinkedList;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.world.World;\n\nimport logisticspipes.logisticspipes.IRoutedItem;\nimport logisticspipes.pipes.basic.CoreRoutedPipe.ItemSendMode;\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\nimport logisticspipes.utils.tuples.Triplet;\n\npublic final class ItemIdentifierStack implements Comparable<ItemIdentifierStack>, ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprivate final ItemIdentifier _item;\n\tprivate int stackSize;\n\n\tpublic static ItemIdentifierStack getFromStack(@Nonnull ItemStack stack) {\n\t\treturn new ItemIdentifierStack(ItemIdentifier.get(stack), stack.getCount());\n\t}\n\n\tpublic ItemIdentifierStack(ItemIdentifier item, int stackSize) {\n\t\t_item = item;\n\t\tsetStackSize(stackSize);\n\t}\n\n\tpublic ItemIdentifierStack(ItemIdentifierStack copy) {\n\t\tthis(copy._item, copy.stackSize);\n\t}\n\n\tpublic ItemIdentifier getItem() {\n\t\treturn _item;\n\t}\n\n\t/**\n\t * @return the stackSize\n\t */\n\tpublic int getStackSize() {\n\t\treturn stackSize;\n\t}\n\n\t/**\n\t * @param stackSize\n\t *            the stackSize to set\n\t */\n\tpublic void setStackSize(int stackSize) {\n\t\tthis.stackSize = stackSize;\n\t}\n\n\tpublic void lowerStackSize(int stackSize) {\n\t\tthis.stackSize -= stackSize;\n\t}\n\n\t@Nonnull\n\tpublic ItemStack unsafeMakeNormalStack() {\n\t\treturn _item.unsafeMakeNormalStack(stackSize);\n\t}\n\n\t@Nonnull\n\tpublic ItemStack makeNormalStack() {\n\t\treturn _item.makeNormalStack(stackSize);\n\t}\n\n\t@Nonnull\n\tpublic EntityItem makeEntityItem(World world, double x, double y, double z) {\n\t\treturn _item.makeEntityItem(stackSize, world, x, y, z);\n\t}\n\n\t@Override\n\tpublic boolean equals(Object that) {\n\t\tif (that instanceof ItemIdentifierStack) {\n\t\t\tItemIdentifierStack stack = (ItemIdentifierStack) that;\n\t\t\treturn stack._item.equals(_item) && stack.getStackSize() == getStackSize();\n\t\t}\n\t\tif ((that instanceof ItemIdentifier)) {\n\t\t\tthrow new IllegalStateException(\"Comparison between ItemIdentifierStack and ItemIdentifier -- did you forget a .getItem() in your code?\");\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn _item.hashCode() ^ (1023 * getStackSize());\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"%dx %s\", getStackSize(), _item.toString());\n\t}\n\n\tpublic String getFriendlyName() {\n\t\treturn getStackSize() + \" \" + _item.getFriendlyName();\n\t}\n\n\tpublic static LinkedList<ItemIdentifierStack> getListFromInventory(IInventory inv) {\n\t\treturn ItemIdentifierStack.getListFromInventory(inv, false);\n\t}\n\n\tpublic static LinkedList<ItemIdentifierStack> getListFromInventory(IInventory inv, boolean removeNull) {\n\t\tLinkedList<ItemIdentifierStack> list = new LinkedList<>();\n\t\tfor (int i = 0; i < inv.getSizeInventory(); i++) {\n\t\t\tif (inv.getStackInSlot(i).isEmpty()) {\n\t\t\t\tif (!removeNull) {\n\t\t\t\t\tlist.add(null);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlist.add(ItemIdentifierStack.getFromStack(inv.getStackInSlot(i)));\n\t\t\t}\n\t\t}\n\t\treturn list;\n\t}\n\n\tpublic static LinkedList<ItemIdentifierStack> getListSendQueue(LinkedList<Triplet<IRoutedItem, EnumFacing, ItemSendMode>> _sendQueue) {\n\t\tLinkedList<ItemIdentifierStack> list = new LinkedList<>();\n\t\tfor (Triplet<IRoutedItem, EnumFacing, ItemSendMode> part : _sendQueue) {\n\t\t\tif (part == null) {\n\t\t\t\tlist.add(null);\n\t\t\t} else {\n\t\t\t\tboolean added = false;\n\t\t\t\tfor (ItemIdentifierStack stack : list) {\n\t\t\t\t\tif (stack.getItem().equals(part.getValue1().getItemIdentifierStack().getItem())) {\n\t\t\t\t\t\tstack.setStackSize(stack.getStackSize() + part.getValue1().getItemIdentifierStack().stackSize);\n\t\t\t\t\t\tadded = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!added) {\n\t\t\t\t\tlist.add(new ItemIdentifierStack(part.getValue1().getItemIdentifierStack()));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic int compareTo(ItemIdentifierStack o) {\n\t\tint c = _item.compareTo(o._item);\n\t\tif (c == 0) {\n\t\t\treturn getStackSize() - o.getStackSize();\n\t\t}\n\t\treturn c;\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/ItemStackRenderer.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/mc16/LICENSE.md\n */\n\npackage logisticspipes.utils.item;\n\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.BlockPane;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.gui.FontRenderer;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.OpenGlHelper;\nimport net.minecraft.client.renderer.RenderHelper;\nimport net.minecraft.client.renderer.RenderItem;\nimport net.minecraft.client.renderer.block.model.IBakedModel;\nimport net.minecraft.client.renderer.block.model.ItemCameraTransforms;\nimport net.minecraft.client.renderer.entity.RenderEntityItem;\nimport net.minecraft.client.renderer.entity.RenderManager;\nimport net.minecraft.client.renderer.texture.TextureManager;\nimport net.minecraft.client.renderer.texture.TextureMap;\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemBlock;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.ForgeHooksClient;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport lombok.Data;\nimport lombok.experimental.Accessors;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.utils.Color;\nimport logisticspipes.utils.gui.GuiGraphics;\nimport logisticspipes.utils.gui.IItemSearch;\nimport logisticspipes.utils.gui.SimpleGraphics;\nimport network.rs485.logisticspipes.util.TextUtil;\n\n@Data\n@Accessors(chain = true)\n@SideOnly(Side.CLIENT)\npublic class ItemStackRenderer {\n\n\tprivate RenderManager renderManager;\n\tprivate RenderItem renderItem;\n\tprivate TextureManager texManager;\n\tprivate FontRenderer fontRenderer;\n\tprivate RenderEntityItem itemEntityRenderer;\n\n\t@Nonnull\n\tprivate ItemStack itemstack = ItemStack.EMPTY;\n\tprivate ItemIdentifierStack itemIdentStack;\n\tprivate int posX;\n\tprivate int posY;\n\tprivate float zLevel;\n\tprivate float scaleX;\n\tprivate float scaleY;\n\tprivate float scaleZ;\n\tprivate DisplayAmount displayAmount;\n\tprivate boolean renderEffects;\n\tprivate boolean ignoreDepth;\n\tprivate boolean renderInColor;\n\tprivate EntityItem entityitem;\n\tprivate World world;\n\tprivate float partialTickTime;\n\n\tpublic ItemStackRenderer(int posX, int posY, float zLevel, boolean renderEffects, boolean ignoreDepth) {\n\t\tthis.posX = posX;\n\t\tthis.posY = posY;\n\t\tthis.zLevel = zLevel;\n\t\tthis.renderEffects = renderEffects;\n\t\tthis.ignoreDepth = ignoreDepth;\n\t\trenderManager = Minecraft.getMinecraft().getRenderManager();\n\t\tfontRenderer = renderManager.getFontRenderer();\n\t\tworld = renderManager.world;\n\t\ttexManager = renderManager.renderEngine;\n\t\tif (texManager == null) texManager = Minecraft.getMinecraft().getTextureManager();\n\t\trenderItem = Minecraft.getMinecraft().getRenderItem();\n\t\titemEntityRenderer = new RenderEntityItem(renderManager, renderItem);\n\t\tscaleX = 1.0F;\n\t\tscaleY = 1.0F;\n\t\tscaleZ = 1.0F;\n\t}\n\n\tpublic static void renderItemIdentifierStackListIntoGui(List<ItemIdentifierStack> _allItems, IItemSearch IItemSearch, int page, int left, int top, int columns, int items, int xSize, int ySize, float zLevel, DisplayAmount displayAmount) {\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(_allItems, IItemSearch, page, left, top, columns, items, xSize, ySize, zLevel, displayAmount, true, false);\n\t}\n\n\tpublic static void renderItemIdentifierStackListIntoGui(List<ItemIdentifierStack> _allItems, IItemSearch IItemSearch, int page, int left, int top, int columns, int items, int xSize, int ySize, float zLevel, DisplayAmount displayAmount, boolean renderEffect, boolean ignoreDepth) {\n\t\tItemStackRenderer itemStackRenderer = new ItemStackRenderer(0, 0, zLevel, renderEffect, ignoreDepth);\n\t\titemStackRenderer.setDisplayAmount(displayAmount);\n\t\tItemStackRenderer.renderItemIdentifierStackListIntoGui(_allItems, IItemSearch, page, left, top, columns, items, xSize, ySize, itemStackRenderer);\n\t}\n\n\tpublic static void renderItemIdentifierStackListIntoGui(List<ItemIdentifierStack> _allItems, IItemSearch IItemSearch, int page, int left, int top, int columns, int items, int xSize, int ySize, ItemStackRenderer itemStackRenderer) {\n\t\tint ppi = 0;\n\t\tint column = 0;\n\t\tint row = 0;\n\n\t\tfor (ItemIdentifierStack identifierStack : _allItems) {\n\t\t\tif (identifierStack == null) {\n\t\t\t\tcolumn++;\n\t\t\t\tif (column >= columns) {\n\t\t\t\t\trow++;\n\t\t\t\t\tcolumn = 0;\n\t\t\t\t}\n\t\t\t\tppi++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemIdentifier item = identifierStack.getItem();\n\t\t\tif (IItemSearch != null && !IItemSearch.itemSearched(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tppi++;\n\n\t\t\tif (ppi <= items * page) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (ppi > items * (page + 1)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tItemStack itemstack = identifierStack.unsafeMakeNormalStack();\n\t\t\tint x = left + xSize * column;\n\t\t\tint y = top + ySize * row + 1;\n\n\t\t\tif (!itemstack.isEmpty()) {\n\t\t\t\titemStackRenderer.setItemstack(itemstack).setPosX(x).setPosY(y);\n\t\t\t\titemStackRenderer.renderInGui();\n\t\t\t}\n\n\t\t\tcolumn++;\n\t\t\tif (column >= columns) {\n\t\t\t\trow++;\n\t\t\t\tcolumn = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void renderInGui() {\n\t\tassert displayAmount != null;\n\t\tassert renderItem != null;\n\t\tassert texManager != null;\n\t\tassert fontRenderer != null;\n\t\tassert scaleX != 0.0F;\n\t\tassert scaleY != 0.0F;\n\t\tassert scaleZ != 0.0F;\n\n\t\tGlStateManager.pushMatrix();\n\n\t\t// The only thing that ever sets NORMALIZE are slimes. It never gets disabled and it interferes with our lightning in the HUD.\n\t\tGlStateManager.disableNormalize();\n\n\t\t// set up lightning\n\t\tGlStateManager.scale(1.0F / scaleX, 1.0F / scaleY, 1.0F / scaleZ);\n\t\tRenderHelper.enableGUIStandardItemLighting();\n\t\tOpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240.0F, 240.0F);\n\t\tGlStateManager.scale(scaleX, scaleY, scaleZ);\n\n\t\tif (ignoreDepth) {\n\t\t\tGlStateManager.disableDepth();\n\t\t} else {\n\t\t\tGlStateManager.enableDepth();\n\t\t}\n\n\t\trenderItem.zLevel += zLevel;\n\n\t\tif (itemIdentStack != null) {\n\t\t\tif (itemIdentStack.getStackSize() < 1) {\n\t\t\t\titemstack = itemIdentStack.getItem().unsafeMakeNormalStack(1);\n\t\t\t} else {\n\t\t\t\titemstack = itemIdentStack.unsafeMakeNormalStack();\n\t\t\t}\n\t\t}\n\n\t\tIBakedModel bakedmodel = renderItem.getItemModelWithOverrides(itemstack, null, (renderEffects ? Minecraft.getMinecraft().player : null));\n\n\t\tGlStateManager.pushMatrix();\n\t\tthis.texManager.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\tthis.texManager.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).setBlurMipmap(false, false);\n\t\tGlStateManager.enableRescaleNormal();\n\t\tGlStateManager.enableAlpha();\n\t\tGlStateManager.alphaFunc(516, 0.1F);\n\t\tGlStateManager.enableBlend();\n\t\tGlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);\n\t\tGlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);\n\t\tthis.setupGuiTransform(posX, posY, bakedmodel.isGui3d());\n\t\tbakedmodel = ForgeHooksClient.handleCameraTransforms(bakedmodel, ItemCameraTransforms.TransformType.GUI, false);\n\t\trenderItem.renderItem(itemstack, bakedmodel);\n\t\tGlStateManager.disableAlpha();\n\t\tGlStateManager.disableRescaleNormal();\n\t\tGlStateManager.disableLighting();\n\t\tGlStateManager.popMatrix();\n\n\t\tthis.texManager.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);\n\t\tthis.texManager.getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).restoreLastBlurMipmap();\n\n\t\trenderItem.zLevel -= zLevel;\n\n\t\t// disable lightning\n\t\tRenderHelper.disableStandardItemLighting();\n\n\t\tif (ignoreDepth) {\n\t\t\tGlStateManager.disableDepth();\n\t\t} else {\n\t\t\tGlStateManager.enableDepth();\n\t\t}\n\t\t// 20 should be about the size of a block\n\t\tGuiGraphics.drawDurabilityBar(itemstack, posX, posY, zLevel + 20.0F);\n\n\t\t// if we want to render the amount, do that\n\t\tif (displayAmount != DisplayAmount.NEVER) {\n\t\t\tif (ignoreDepth) {\n\t\t\t\tGlStateManager.disableDepth();\n\t\t\t} else {\n\t\t\t\tGlStateManager.enableDepth();\n\t\t\t}\n\n\t\t\tFontRenderer specialFontRenderer = itemstack.getItem().getFontRenderer(itemstack);\n\n\t\t\tif (specialFontRenderer != null) {\n\t\t\t\tfontRenderer = specialFontRenderer;\n\t\t\t}\n\n\t\t\tGlStateManager.disableLighting();\n\t\t\tString amountString = TextUtil.getThreeDigitFormattedNumber(itemIdentStack != null ? itemIdentStack.getStackSize() : itemstack.getCount(), displayAmount == DisplayAmount.ALWAYS);\n\t\t\tGlStateManager.translate(0.0F, 0.0F, zLevel + 130.0F);\n\n\t\t\t// using a translated shadow does not hurt and works with the HUD\n\t\t\tSimpleGraphics.drawStringWithTranslatedShadow(fontRenderer, amountString, posX + 17 - fontRenderer.getStringWidth(amountString), posY + 9, Color.getValue(Color.WHITE));\n\n\t\t\tGlStateManager.translate(0.0F, 0.0F, -(zLevel + 130.0F));\n\t\t}\n\n\t\tGlStateManager.popMatrix();\n\t}\n\n\tprivate void setupGuiTransform(int xPosition, int yPosition, boolean isGui3d) {\n\t\tGlStateManager.translate((float) xPosition, (float) yPosition, 100.0F + renderItem.zLevel);\n\t\tGlStateManager.translate(8.0F, 8.0F, 0.0F);\n\t\tGlStateManager.scale(1.0F, -1.0F, 1.0F);\n\t\tGlStateManager.scale(16.0F, 16.0F, 16.0F);\n\n\t\tif (isGui3d) {\n\t\t\tGlStateManager.enableLighting();\n\t\t} else {\n\t\t\tGlStateManager.disableLighting();\n\t\t}\n\t}\n\n\tpublic void renderInWorld() {\n\t\tassert renderManager != null;\n\t\tassert renderItem != null;\n\t\tassert scaleX != 0.0F;\n\t\tassert scaleY != 0.0F;\n\t\tassert scaleZ != 0.0F;\n\n\t\tif (entityitem == null || !ItemStack.areItemStacksEqual(entityitem.getItem(), itemstack)) {\n\t\t\tObjects.requireNonNull(world, \"World is needed for EntityItem creation\");\n\t\t\tif (itemstack.isEmpty()) {\n\t\t\t\t// :itemcard: 🤷\n\t\t\t\titemstack = new ItemStack(LPItems.itemCard);\n\t\t\t}\n\t\t\tentityitem = new EntityItem(world, 0.0D, 0.0D, 0.0D, itemstack);\n\t\t\tentityitem.getItem().setCount(1);\n\t\t\tentityitem.hoverStart = 0.0F;\n\t\t}\n\n\t\tItem item = itemstack.getItem();\n\t\tif (item instanceof ItemBlock) {\n\t\t\tBlock block = ((ItemBlock) item).getBlock();\n\t\t\tif (block instanceof BlockPane) {\n\t\t\t\tGlStateManager.scale(0.5F, 0.5F, 0.5F);\n\t\t\t}\n\t\t} else if (item == LPItems.requestTable) {\n\t\t\tGlStateManager.scale(0.5F, 0.5F, 0.5F);\n\t\t}\n\n\t\titemEntityRenderer.doRender(entityitem, posX, posY, zLevel, 0.0F, partialTickTime);\n\t}\n\n\tpublic void renderItemInGui(float x, float y, Item item, float zLevel, float scale) {\n\t\t// TODO check if I can set position and the scale here\n\t\tthis.setPosX(0);\n\t\tthis.setPosY(0);\n\t\tthis.setScaleX(1f);\n\t\tthis.setScaleY(1f);\n\t\tthis.setScaleZ(1f);\n\t\tthis.itemstack = new ItemStack(item);\n\t\tthis.displayAmount = DisplayAmount.NEVER;\n\t\tGlStateManager.pushMatrix();\n\t\tGlStateManager.translate(x, y, 0);\n\t\tGlStateManager.scale(scale, scale, 1f);\n\t\tGlStateManager.disableDepth();\n\t\tfloat previousZ = renderItem.zLevel;\n\t\trenderItem.zLevel = zLevel;\n\t\tthis.renderInGui();\n\t\trenderItem.zLevel = previousZ;\n\t\tGlStateManager.enableDepth();\n\t\tGlStateManager.scale(1 / scale, 1 / scale, 1f);\n\t\tGlStateManager.translate(-x, -y, 0);\n\t\tGlStateManager.popMatrix();\n\t}\n\n\tpublic enum DisplayAmount {\n\t\tHIDE_ONE,\n\t\tALWAYS,\n\t\tNEVER,\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/item/SimpleStackInventory.java",
    "content": "/**\n * Copyright (c) Krapht, 2011\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0, or MMPL. Please check the contents of the license located in\n * http://www.mod-buildcraft.com/MMPL-1.0.txt\n */\n\npackage logisticspipes.utils.item;\n\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.stream.IntStream;\nimport java.util.stream.Stream;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.entity.item.EntityItem;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.nbt.NBTTagList;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.text.ITextComponent;\nimport net.minecraft.util.text.TextComponentString;\nimport net.minecraft.world.World;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.proxy.MainProxy;\nimport logisticspipes.utils.ISimpleInventoryEventHandler;\nimport logisticspipes.utils.tuples.Pair;\nimport network.rs485.logisticspipes.IStore;\nimport network.rs485.logisticspipes.util.items.ItemStackLoader;\n\npublic class SimpleStackInventory implements IInventory, IStore, Iterable<Pair<ItemStack, Integer>> {\n\n\tprivate static final TextComponentString TEXT_COMPONENT_EMPTY = new TextComponentString(\"\");\n\n\tprivate final NonNullList<ItemStack> stackList;\n\tprivate final String _name;\n\tprivate final int _stackLimit;\n\n\tprivate final LinkedList<ISimpleInventoryEventHandler> _listener = new LinkedList<>();\n\n\tpublic SimpleStackInventory(SimpleStackInventory copy) {\n\t\tthis(copy.getSizeInventory(), copy._name, copy._stackLimit);\n\t\tfor (int i = 0; i < copy.getSizeInventory(); i++) {\n\t\t\tstackList.set(i, copy.getStackInSlot(i).copy());\n\t\t}\n\t}\n\n\tpublic SimpleStackInventory(int size, String name, int stackLimit) {\n\t\tstackList = NonNullList.withSize(size, ItemStack.EMPTY);\n\t\t_name = name;\n\t\t_stackLimit = stackLimit;\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn stackList.size();\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn stackList.stream().allMatch(ItemStack::isEmpty);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack getStackInSlot(int i) {\n\t\treturn stackList.get(i);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack decrStackSize(int slot, int count) {\n\t\tfinal ItemStack stack = stackList.get(slot);\n\t\tif (stack.isEmpty()) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\t\tif (stack.getCount() > count) {\n\t\t\tItemStack ret = stack.copy();\n\t\t\tret.setCount(count);\n\t\t\tstack.setCount(stack.getCount() - count);\n\t\t\treturn ret;\n\t\t}\n\t\treturn stackList.set(slot, ItemStack.EMPTY);\n\t}\n\n\t@Override\n\tpublic void setInventorySlotContents(int slot, @Nonnull ItemStack itemstack) {\n\t\tif (itemstack.isEmpty()) {\n\t\t\tstackList.set(slot, ItemStack.EMPTY);\n\t\t} else {\n\t\t\tstackList.set(slot, itemstack.copy());\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic String getName() {\n\t\treturn _name;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ITextComponent getDisplayName() {\n\t\treturn TEXT_COMPONENT_EMPTY;\n\t}\n\n\t@Override\n\tpublic int getInventoryStackLimit() {\n\t\treturn _stackLimit;\n\t}\n\n\t@Override\n\tpublic void markDirty() {\n\t\tfor (ISimpleInventoryEventHandler handler : _listener) {\n\t\t\thandler.InventoryChanged(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean isUsableByPlayer(@Nonnull EntityPlayer entityplayer) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic void openInventory(@Nonnull EntityPlayer player) {}\n\n\t@Override\n\tpublic void closeInventory(@Nonnull EntityPlayer player) {}\n\n\t@Override\n\tpublic void readFromNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\treadFromNBT(nbttagcompound, \"\");\n\t}\n\n\tpublic void readFromNBT(NBTTagCompound nbttagcompound, String prefix) {\n\t\tNBTTagList nbttaglist = nbttagcompound.getTagList(prefix + \"items\", nbttagcompound.getId());\n\n\t\tfor (int j = 0; j < nbttaglist.tagCount(); ++j) {\n\t\t\tNBTTagCompound nbttagcompound2 = nbttaglist.getCompoundTagAt(j);\n\t\t\tint index = nbttagcompound2.getInteger(\"index\");\n\t\t\tif (index < stackList.size()) {\n\t\t\t\tstackList.set(index, ItemStackLoader.loadAndFixItemStackFromNBT(nbttagcompound2));\n\t\t\t} else {\n\t\t\t\tLogisticsPipes.log.fatal(\"SimpleInventory: java.lang.ArrayIndexOutOfBoundsException: \" + index + \" of \" + stackList.size());\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeToNBT(@Nonnull NBTTagCompound nbttagcompound) {\n\t\twriteToNBT(nbttagcompound, \"\");\n\t}\n\n\tpublic void writeToNBT(NBTTagCompound nbttagcompound, String prefix) {\n\t\tNBTTagList nbttaglist = new NBTTagList();\n\t\tfor (int j = 0; j < stackList.size(); ++j) {\n\t\t\tfinal ItemStack stack = stackList.get(j);\n\t\t\tif (!stack.isEmpty()) {\n\t\t\t\tNBTTagCompound nbttagcompound2 = new NBTTagCompound();\n\t\t\t\tnbttaglist.appendTag(nbttagcompound2);\n\t\t\t\tnbttagcompound2.setInteger(\"index\", j);\n\t\t\t\tstack.writeToNBT(nbttagcompound2);\n\t\t\t}\n\t\t}\n\t\tnbttagcompound.setTag(prefix + \"items\", nbttaglist);\n\t\tnbttagcompound.setInteger(prefix + \"itemsCount\", stackList.size());\n\t}\n\n\tpublic void dropContents(World world, BlockPos pos) {\n\t\tif (MainProxy.isServer(world)) {\n\t\t\tfor (int i = 0; i < stackList.size(); i++) {\n\t\t\t\tdropSlot(i, world, pos);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate void dropSlot(int slot, World world, BlockPos pos) {\n\t\tfinal ItemStack slotStack = stackList.get(slot);\n\t\tIntStream.range(0, (slotStack.getCount() / slotStack.getMaxStackSize()) + 1)\n\t\t\t\t.mapToObj(i -> decrStackSize(slot, slotStack.getMaxStackSize()))\n\t\t\t\t.filter(dropStack -> !dropStack.isEmpty())\n\t\t\t\t.forEach(dropStack -> {\n\t\t\t\t\tfloat f1 = 0.7F;\n\t\t\t\t\tdouble d = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;\n\t\t\t\t\tdouble d1 = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;\n\t\t\t\t\tdouble d2 = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;\n\t\t\t\t\tEntityItem entityitem = new EntityItem(world, pos.getX() + d, pos.getY() + d1, pos.getZ() + d2, dropStack);\n\t\t\t\t\tentityitem.setDefaultPickupDelay();\n\t\t\t\t\tworld.spawnEntity(entityitem);\n\t\t\t\t});\n\t}\n\n\tpublic void addListener(ISimpleInventoryEventHandler listner) {\n\t\tif (!_listener.contains(listner)) {\n\t\t\t_listener.add(listner);\n\t\t}\n\t}\n\n\tpublic void removeListener(ISimpleInventoryEventHandler listner) {\n\t\t_listener.remove(listner);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack removeStackFromSlot(int i) {\n\t\treturn stackList.set(i, ItemStack.EMPTY);\n\t}\n\n\tprivate int tryAddToSlot(int i, @Nonnull ItemStack stack, int realstacklimit) {\n\t\tItemStack slotStack = stackList.get(i);\n\t\tif (slotStack.isEmpty()) {\n\t\t\tfinal ItemStack copy = stack.copy();\n\t\t\tstackList.set(i, copy);\n\t\t\tcopy.setCount(Math.min(copy.getCount(), realstacklimit));\n\t\t\treturn copy.getCount();\n\t\t}\n\t\tItemIdentifier stackIdent = ItemIdentifier.get(stack);\n\t\tItemIdentifier slotIdent = ItemIdentifier.get(slotStack);\n\t\tif (slotIdent.equals(stackIdent)) {\n\t\t\tslotStack.setCount(slotStack.getCount() + stack.getCount());\n\t\t\tif (slotStack.getCount() > realstacklimit) {\n\t\t\t\tint ans = stack.getCount() - (slotStack.getCount() - realstacklimit);\n\t\t\t\tslotStack.setCount(realstacklimit);\n\t\t\t\treturn ans;\n\t\t\t} else {\n\t\t\t\treturn stack.getCount();\n\t\t\t}\n\t\t} else {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tpublic int addCompressed(@Nonnull ItemStack stack, boolean ignoreMaxStackSize) {\n\t\tif (stack.isEmpty()) return 0;\n\t\tstack = stack.copy();\n\n\t\tItemIdentifier stackIdent = ItemIdentifier.get(stack);\n\t\tint stacklimit = _stackLimit;\n\t\tif (!ignoreMaxStackSize) {\n\t\t\tstacklimit = Math.min(stacklimit, stackIdent.getMaxStackSize());\n\t\t}\n\n\t\tfor (int i = 0; i < stackList.size(); i++) {\n\t\t\tif (stack.getCount() <= 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (stackList.get(i).isEmpty()) {\n\t\t\t\tcontinue; //Skip Empty Slots on first attempt.\n\t\t\t}\n\t\t\tint added = tryAddToSlot(i, stack, stacklimit);\n\t\t\tstack.setCount(stack.getCount() - added);\n\t\t}\n\t\tfor (int i = 0; i < stackList.size(); i++) {\n\t\t\tif (stack.getCount() <= 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tint added = tryAddToSlot(i, stack, stacklimit);\n\t\t\tstack.setCount(stack.getCount() - added);\n\t\t}\n\t\tmarkDirty();\n\t\treturn stack.getCount();\n\t}\n\n\t@Override\n\tpublic boolean isItemValidForSlot(int i, @Nonnull ItemStack itemstack) {\n\t\treturn true;\n\t}\n\n\t@Override\n\t@kotlin.Deprecated(message = \"not implemented\")\n\tpublic int getField(int id) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\t@kotlin.Deprecated(message = \"not implemented\")\n\tpublic void setField(int id, int value) {}\n\n\t@Override\n\t@kotlin.Deprecated(message = \"not implemented\")\n\tpublic int getFieldCount() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void clear() {\n\t\tCollections.fill(stackList, ItemStack.EMPTY);\n\t}\n\n\tpublic void clearInventorySlotContents(int i) {\n\t\tstackList.set(i, ItemStack.EMPTY);\n\t}\n\n\t@Override\n\tpublic boolean hasCustomName() {\n\t\treturn true;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterator<Pair<ItemStack, Integer>> iterator() {\n\t\tfinal Iterator<ItemStack> iter = stackList.iterator();\n\t\treturn new Iterator<Pair<ItemStack, Integer>>() {\n\n\t\t\tint pos = -1;\n\n\t\t\t@Override\n\t\t\tpublic boolean hasNext() {\n\t\t\t\treturn iter.hasNext();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic Pair<ItemStack, Integer> next() {\n\t\t\t\tpos++;\n\t\t\t\treturn new Pair<>(iter.next(), pos);\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic void remove() {\n\t\t\t\tthrow new UnsupportedOperationException();\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Returns a stream over all non-empty item stacks in this inventory.\n\t */\n\t@Nonnull\n\tpublic Stream<ItemStack> stackStream() {\n\t\treturn stackList.stream().filter(itemStack -> !itemStack.isEmpty());\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/BoundingBox.java",
    "content": "package logisticspipes.utils.math;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.util.EnumFacing;\n\nimport network.rs485.logisticspipes.world.DoubleCoordinates;\n\npublic class BoundingBox {\n\n\tpublic static final BoundingBox UNIT_CUBE = new BoundingBox(0, 0, 0, 1, 1, 1);\n\n\tpublic final float minX;\n\tpublic final float minY;\n\tpublic final float minZ;\n\tpublic final float maxX;\n\tpublic final float maxY;\n\tpublic final float maxZ;\n\n\tpublic BoundingBox(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) {\n\t\tthis.minX = minX;\n\t\tthis.minY = minY;\n\t\tthis.minZ = minZ;\n\t\tthis.maxX = maxX;\n\t\tthis.maxY = maxY;\n\t\tthis.maxZ = maxZ;\n\t}\n\n\tpublic BoundingBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {\n\t\tthis.minX = (float) minX;\n\t\tthis.minY = (float) minY;\n\t\tthis.minZ = (float) minZ;\n\t\tthis.maxX = (float) maxX;\n\t\tthis.maxY = (float) maxY;\n\t\tthis.maxZ = (float) maxZ;\n\t}\n\n\tpublic BoundingBox(DoubleCoordinates bc) {\n\t\tthis(bc.getXDouble(), bc.getYDouble(), bc.getZDouble(), bc.getXDouble() + 1, bc.getYDouble() + 1, bc.getZDouble() + 1);\n\t}\n\n\t@Nonnull\n\tpublic List<Vertex> getCornersWithUvForFace(@Nonnull EnumFacing face, float minU, float maxU, float minV, float maxV) {\n\t\tList<Vertex> result = new ArrayList<>(4);\n\t\tswitch (face) {\n\t\t\tcase NORTH:\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, minY, minZ), new Vector3f(0, 0, -1), new Vector2f(minU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, minY, minZ), new Vector3f(0, 0, -1), new Vector2f(maxU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, maxY, minZ), new Vector3f(0, 0, -1), new Vector2f(maxU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, maxY, minZ), new Vector3f(0, 0, -1), new Vector2f(minU, maxV)));\n\t\t\t\tbreak;\n\t\t\tcase SOUTH:\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, minY, maxZ), new Vector3f(0, 0, 1), new Vector2f(maxU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, minY, maxZ), new Vector3f(0, 0, 1), new Vector2f(minU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, maxY, maxZ), new Vector3f(0, 0, 1), new Vector2f(minU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, maxY, maxZ), new Vector3f(0, 0, 1), new Vector2f(maxU, maxV)));\n\t\t\t\tbreak;\n\t\t\tcase EAST:\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, maxY, minZ), new Vector3f(1, 0, 0), new Vector2f(maxU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, maxY, maxZ), new Vector3f(1, 0, 0), new Vector2f(minU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, minY, maxZ), new Vector3f(1, 0, 0), new Vector2f(minU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, minY, minZ), new Vector3f(1, 0, 0), new Vector2f(maxU, minV)));\n\t\t\t\tbreak;\n\t\t\tcase WEST:\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, minY, minZ), new Vector3f(-1, 0, 0), new Vector2f(maxU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, minY, maxZ), new Vector3f(-1, 0, 0), new Vector2f(minU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, maxY, maxZ), new Vector3f(-1, 0, 0), new Vector2f(minU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, maxY, minZ), new Vector3f(-1, 0, 0), new Vector2f(maxU, maxV)));\n\t\t\t\tbreak;\n\t\t\tcase UP:\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, maxY, maxZ), new Vector3f(0, 1, 0), new Vector2f(minU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, maxY, minZ), new Vector3f(0, 1, 0), new Vector2f(minU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, maxY, minZ), new Vector3f(0, 1, 0), new Vector2f(maxU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, maxY, maxZ), new Vector3f(0, 1, 0), new Vector2f(maxU, minV)));\n\t\t\t\tbreak;\n\t\t\tcase DOWN:\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, minY, minZ), new Vector3f(0, -1, 0), new Vector2f(maxU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, minY, minZ), new Vector3f(0, -1, 0), new Vector2f(minU, maxV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(maxX, minY, maxZ), new Vector3f(0, -1, 0), new Vector2f(minU, minV)));\n\t\t\t\tresult.add(new Vertex(new Vector3d(minX, minY, maxZ), new Vector3f(0, -1, 0), new Vector2f(maxU, minV)));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new IllegalArgumentException(\"Unknown side\");\n\t\t}\n\t\treturn result;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Camera.java",
    "content": "package logisticspipes.utils.math;\n\nimport java.awt.Rectangle;\n\npublic class Camera {\n\n\tprivate Rectangle viewport;\n\n\tprivate Matrix4d projectionTranspose;\n\tprivate Matrix4d projectionMatrix;\n\tprivate Matrix4d projectionInverse;\n\n\tprivate Matrix4d viewTranspose;\n\tprivate Matrix4d viewMatrix;\n\tprivate Matrix4d viewInverse;\n\n\tpublic boolean isValid() {\n\t\treturn viewMatrix != null && projectionMatrix != null && viewport != null;\n\t}\n\n\tpublic void setProjectionMatrixAsPerspective(double fovDegrees, double near, double far, int viewportWidth, int viewportHeight) {\n\t\tsetProjectionMatrix(VecmathUtil.createProjectionMatrixAsPerspective(fovDegrees, near, far, viewportWidth, viewportHeight));\n\t}\n\n\tpublic void setViewMatrixAsLookAt(Vector3d eyePos, Vector3d lookAtPos, Vector3d upVec) {\n\t\tsetViewMatrix(VecmathUtil.createMatrixAsLookAt(eyePos, lookAtPos, upVec));\n\t}\n\n\tpublic Vector3d getEyePoint() {\n\t\tMatrix4d vpm = new Matrix4d();\n\t\tMatrix4d ivm = getInverseViewMatrix();\n\t\tif (ivm == null) {\n\t\t\treturn null;\n\t\t}\n\t\tMatrix4d ipm = getInverseProjectionMatrix();\n\t\tif (ipm == null) {\n\t\t\treturn null;\n\t\t}\n\t\tvpm.mul(ivm, ipm);\n\n\t\tVector3d eye = new Vector3d();\n\t\tivm.getTranslation(eye);\n\t\treturn eye;\n\t}\n\n\tpublic boolean getRayForPixel(int x, int y, Vector3d eyeOut, Vector3d normalOut) {\n\t\tif (isValid()) {\n\t\t\tVecmathUtil.computeRayForPixel(viewport, getInverseProjectionMatrix(), getInverseViewMatrix(), x, y, eyeOut, normalOut);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tpublic Vector2d getScreenPoint(Vector3d point3d) {\n\t\tVector4d transPoint = new Vector4d(point3d.x, point3d.y, point3d.z, 1);\n\n\t\tviewMatrix.transform(transPoint);\n\t\tprojectionMatrix.transform(transPoint);\n\n\t\tint halfWidth = viewport.width / 2;\n\t\tint halfHeight = viewport.height / 2;\n\t\tVector2d screenPos = new Vector2d(transPoint.x, transPoint.y);\n\t\tscreenPos.multiply(1 / transPoint.w);\n\t\tscreenPos.x = screenPos.x * halfWidth + halfWidth;\n\t\tscreenPos.y = -screenPos.y * halfHeight + halfHeight;\n\n\t\treturn screenPos;\n\t}\n\n\tpublic Vector3d getWorldPoint(Vector2d point2d) {\n\t\tint halfWidth = viewport.width / 2;\n\t\tint halfHeight = viewport.height / 2;\n\t\tpoint2d.x = (point2d.x - halfWidth) / halfWidth;\n\t\tpoint2d.y = (-point2d.y + halfHeight) / halfWidth;\n\n\t\tVector4d transPoint = new Vector4d(point2d.x, point2d.y, 0, 1);\n\t\tgetInverseProjectionMatrix().transform(transPoint);\n\t\tgetInverseViewMatrix().transform(transPoint);\n\t\treturn new Vector3d(transPoint.x, transPoint.y, transPoint.z);\n\t}\n\n\tpublic void setViewport(Rectangle viewport) {\n\t\tif (viewport != null) {\n\t\t\tsetViewport(viewport.x, viewport.y, viewport.width, viewport.height);\n\t\t}\n\t}\n\n\tpublic void setViewport(int x, int y, int width, int height) {\n\t\tviewport = new Rectangle(x, y, width, height);\n\t}\n\n\tpublic Rectangle getViewport() {\n\t\treturn viewport;\n\t}\n\n\tpublic Matrix4d getProjectionMatrix() {\n\t\treturn projectionMatrix;\n\t}\n\n\tpublic Matrix4d getTransposeProjectionMatrix() {\n\t\treturn projectionTranspose;\n\t}\n\n\tpublic Matrix4d getInverseProjectionMatrix() {\n\t\tif (projectionMatrix != null) {\n\t\t\tif (projectionInverse == null) {\n\t\t\t\tprojectionInverse = new Matrix4d(projectionMatrix);\n\t\t\t\tprojectionInverse.invert();\n\t\t\t}\n\t\t\treturn projectionInverse;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic void setProjectionMatrix(Matrix4d matrix) {\n\t\tif (projectionMatrix == null) {\n\t\t\tprojectionMatrix = new Matrix4d();\n\t\t\tprojectionTranspose = new Matrix4d();\n\t\t}\n\t\tprojectionMatrix.set(matrix);\n\t\tprojectionTranspose.set(matrix);\n\t\tprojectionTranspose.transpose();\n\t\tprojectionInverse = null;\n\t}\n\n\tpublic Matrix4d getViewMatrix() {\n\t\treturn viewMatrix;\n\t}\n\n\tpublic Matrix4d getTransposeViewMatrix() {\n\t\treturn viewTranspose;\n\t}\n\n\tpublic Matrix4d getInverseViewMatrix() {\n\t\tif (viewMatrix != null) {\n\t\t\tif (viewInverse == null) {\n\t\t\t\tviewInverse = new Matrix4d(viewMatrix);\n\t\t\t\tviewInverse.invert();\n\t\t\t}\n\t\t\treturn viewInverse;\n\t\t} else {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tpublic void setViewMatrix(Matrix4d matrix) {\n\t\tif (viewMatrix == null) {\n\t\t\tviewMatrix = new Matrix4d();\n\t\t\tviewTranspose = new Matrix4d();\n\t\t}\n\t\tviewMatrix.set(matrix);\n\t\tviewTranspose.set(matrix);\n\t\tviewTranspose.transpose();\n\t\tviewInverse = null;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Matrix4d.java",
    "content": "package logisticspipes.utils.math;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Matrix4d {\n\n\tpublic double m00 = 0;\n\tpublic double m01 = 0;\n\tpublic double m02 = 0;\n\tpublic double m03 = 0;\n\tpublic double m10 = 0;\n\tpublic double m11 = 0;\n\tpublic double m12 = 0;\n\tpublic double m13 = 0;\n\tpublic double m20 = 0;\n\tpublic double m21 = 0;\n\tpublic double m22 = 0;\n\tpublic double m23 = 0;\n\tpublic double m30 = 0;\n\tpublic double m31 = 0;\n\tpublic double m32 = 0;\n\tpublic double m33 = 0;\n\n\tpublic Matrix4d(Matrix4d matrix) {\n\t\tthis.set(matrix);\n\t}\n\n\tpublic final void setIdentity() {\n\t\tm00 = 1.0;\n\t\tm01 = 0.0;\n\t\tm02 = 0.0;\n\t\tm03 = 0.0;\n\n\t\tm10 = 0.0;\n\t\tm11 = 1.0;\n\t\tm12 = 0.0;\n\t\tm13 = 0.0;\n\n\t\tm20 = 0.0;\n\t\tm21 = 0.0;\n\t\tm22 = 1.0;\n\t\tm23 = 0.0;\n\n\t\tm30 = 0.0;\n\t\tm31 = 0.0;\n\t\tm32 = 0.0;\n\t\tm33 = 1.0;\n\t}\n\n\tpublic void set(Matrix4d other) {\n\t\tm00 = other.m00;\n\t\tm01 = other.m01;\n\t\tm02 = other.m02;\n\t\tm03 = other.m03;\n\n\t\tm10 = other.m10;\n\t\tm11 = other.m11;\n\t\tm12 = other.m12;\n\t\tm13 = other.m13;\n\n\t\tm20 = other.m20;\n\t\tm21 = other.m21;\n\t\tm22 = other.m22;\n\t\tm23 = other.m23;\n\n\t\tm30 = other.m30;\n\t\tm31 = other.m31;\n\t\tm32 = other.m32;\n\t\tm33 = other.m33;\n\n\t}\n\n\tpublic void makeRotationX(double angle) {\n\t\tsetIdentity();\n\t\tdouble sin = Math.sin(angle);\n\t\tdouble cos = Math.cos(angle);\n\t\tm11 = cos;\n\t\tm12 = -sin;\n\t\tm21 = sin;\n\t\tm22 = cos;\n\t}\n\n\tpublic void makeRotationY(double angle) {\n\t\tsetIdentity();\n\t\tdouble sin = Math.sin(angle);\n\t\tdouble cos = Math.cos(angle);\n\t\tm00 = cos;\n\t\tm02 = sin;\n\t\tm20 = -sin;\n\t\tm22 = cos;\n\t}\n\n\tpublic void makeRotationZ(double angle) {\n\t\tsetIdentity();\n\t\tdouble sin = Math.sin(angle);\n\t\tdouble cos = Math.cos(angle);\n\t\tm00 = cos;\n\t\tm01 = -sin;\n\t\tm10 = sin;\n\t\tm11 = cos;\n\t}\n\n\tpublic void transform(Vector3d vec) {\n\t\tdouble x = m00 * vec.x + m01 * vec.y + m02 * vec.z + m03;\n\t\tdouble y = m10 * vec.x + m11 * vec.y + m12 * vec.z + m13;\n\t\tvec.z = m20 * vec.x + m21 * vec.y + m22 * vec.z + m23;\n\t\tvec.x = x;\n\t\tvec.y = y;\n\t}\n\n\tpublic void transform(Vector4d vec) {\n\t\tdouble x = m00 * vec.x + m01 * vec.y + m02 * vec.z + m03 * vec.w;\n\t\tdouble y = m10 * vec.x + m11 * vec.y + m12 * vec.z + m13 * vec.w;\n\t\tdouble z = m20 * vec.x + m21 * vec.y + m22 * vec.z + m23 * vec.w;\n\t\tvec.w = m30 * vec.x + m31 * vec.y + m32 * vec.z + m33 * vec.w;\n\t\tvec.x = x;\n\t\tvec.y = y;\n\t\tvec.z = z;\n\t}\n\n\tpublic void transformNormal(Vector3d normal) {\n\t\tdouble x = m00 * normal.x + m01 * normal.y + m02 * normal.z;\n\t\tdouble y = m10 * normal.x + m11 * normal.y + m12 * normal.z;\n\t\tnormal.z = m20 * normal.x + m21 * normal.y + m22 * normal.z;\n\t\tnormal.x = x;\n\t\tnormal.y = y;\n\t}\n\n\tpublic void mul(Matrix4d m1, Matrix4d m2) {\n\t\tset(m1);\n\t\tmul(m2);\n\t}\n\n\tpublic void mul(Matrix4d m) {\n\t\tdouble m00Tmp = m00 * m.m00 + m01 * m.m10 + m02 * m.m20 + m03 * m.m30;\n\t\tdouble m01Tmp = m00 * m.m01 + m01 * m.m11 + m02 * m.m21 + m03 * m.m31;\n\t\tdouble m02Tmp = m00 * m.m02 + m01 * m.m12 + m02 * m.m22 + m03 * m.m32;\n\t\tdouble m03Tmp = m00 * m.m03 + m01 * m.m13 + m02 * m.m23 + m03 * m.m33;\n\n\t\tdouble m10Tmp = m10 * m.m00 + m11 * m.m10 + m12 * m.m20 + m13 * m.m30;\n\t\tdouble m11Tmp = m10 * m.m01 + m11 * m.m11 + m12 * m.m21 + m13 * m.m31;\n\t\tdouble m12Tmp = m10 * m.m02 + m11 * m.m12 + m12 * m.m22 + m13 * m.m32;\n\t\tdouble m13Tmp = m10 * m.m03 + m11 * m.m13 + m12 * m.m23 + m13 * m.m33;\n\n\t\tdouble m20Tmp = m20 * m.m00 + m21 * m.m10 + m22 * m.m20 + m23 * m.m30;\n\t\tdouble m21Tmp = m20 * m.m01 + m21 * m.m11 + m22 * m.m21 + m23 * m.m31;\n\t\tdouble m22Tmp = m20 * m.m02 + m21 * m.m12 + m22 * m.m22 + m23 * m.m32;\n\t\tdouble m23Tmp = m20 * m.m03 + m21 * m.m13 + m22 * m.m23 + m23 * m.m33;\n\n\t\tdouble m30Tmp = m30 * m.m00 + m31 * m.m10 + m32 * m.m20 + m33 * m.m30;\n\t\tdouble m31Tmp = m30 * m.m01 + m31 * m.m11 + m32 * m.m21 + m33 * m.m31;\n\t\tdouble m32Tmp = m30 * m.m02 + m31 * m.m12 + m32 * m.m22 + m33 * m.m32;\n\t\tdouble m33Tmp = m30 * m.m03 + m31 * m.m13 + m32 * m.m23 + m33 * m.m33;\n\n\t\tm00 = m00Tmp;\n\t\tm01 = m01Tmp;\n\t\tm02 = m02Tmp;\n\t\tm03 = m03Tmp;\n\t\tm10 = m10Tmp;\n\t\tm11 = m11Tmp;\n\t\tm12 = m12Tmp;\n\t\tm13 = m13Tmp;\n\t\tm20 = m20Tmp;\n\t\tm21 = m21Tmp;\n\t\tm22 = m22Tmp;\n\t\tm23 = m23Tmp;\n\t\tm30 = m30Tmp;\n\t\tm31 = m31Tmp;\n\t\tm32 = m32Tmp;\n\t\tm33 = m33Tmp;\n\t}\n\n\tpublic void getTranslation(Vector3d trans) {\n\t\ttrans.x = m03;\n\t\ttrans.y = m13;\n\t\ttrans.z = m23;\n\t}\n\n\tpublic void setTranslation(Vector3d trans) {\n\t\tm03 = trans.x;\n\t\tm13 = trans.y;\n\t\tm23 = trans.z;\n\t}\n\n\tpublic void transpose() {\n\t\tdouble tmp = m10;\n\t\tm10 = m01;\n\t\tm01 = tmp;\n\n\t\ttmp = m20;\n\t\tm20 = m02;\n\t\tm02 = tmp;\n\n\t\ttmp = m30;\n\t\tm30 = m03;\n\t\tm03 = tmp;\n\n\t\ttmp = m21;\n\t\tm21 = m12;\n\t\tm12 = tmp;\n\n\t\ttmp = m31;\n\t\tm31 = m13;\n\t\tm13 = tmp;\n\n\t\ttmp = m32;\n\t\tm32 = m23;\n\t\tm23 = tmp;\n\t}\n\n\tpublic void invert() {\n\t\tdouble det = determinant();\n\t\tif (det == 0) {\n\t\t\tthrow new RuntimeException(\"Cannot invert matrix with a determinat of 0.\");\n\t\t}\n\t\tdouble detInv = 1f / det;\n\n\t\t// first row\n\t\tdouble t00 = determinant3x3(m11, m21, m31, m12, m22, m32, m13, m23, m33);\n\t\tdouble t01 = -determinant3x3(m01, m21, m31, m02, m22, m32, m03, m23, m33);\n\t\tdouble t02 = determinant3x3(m01, m11, m31, m02, m12, m32, m03, m13, m33);\n\t\tdouble t03 = -determinant3x3(m01, m11, m21, m02, m12, m22, m03, m13, m23);\n\t\t// second row\n\t\tdouble t10 = -determinant3x3(m10, m20, m30, m12, m22, m32, m13, m23, m33);\n\t\tdouble t11 = determinant3x3(m00, m20, m30, m02, m22, m32, m03, m23, m33);\n\t\tdouble t12 = -determinant3x3(m00, m10, m30, m02, m12, m32, m03, m13, m33);\n\t\tdouble t13 = determinant3x3(m00, m10, m20, m02, m12, m22, m03, m13, m23);\n\t\t// third row\n\t\tdouble t20 = determinant3x3(m10, m20, m30, m11, m21, m31, m13, m23, m33);\n\t\tdouble t21 = -determinant3x3(m00, m20, m30, m01, m21, m31, m03, m23, m33);\n\t\tdouble t22 = determinant3x3(m00, m10, m30, m01, m11, m31, m03, m13, m33);\n\t\tdouble t23 = -determinant3x3(m00, m10, m20, m01, m11, m21, m03, m13, m23);\n\t\t// fourth row\n\t\tdouble t30 = -determinant3x3(m10, m20, m30, m11, m21, m31, m12, m22, m32);\n\t\tdouble t31 = determinant3x3(m00, m20, m30, m01, m21, m31, m02, m22, m32);\n\t\tdouble t32 = -determinant3x3(m00, m10, m30, m01, m11, m31, m02, m12, m32);\n\t\tdouble t33 = determinant3x3(m00, m10, m20, m01, m11, m21, m02, m12, m22);\n\n\t\tm00 = t00 * detInv;\n\t\tm11 = t11 * detInv;\n\t\tm22 = t22 * detInv;\n\t\tm33 = t33 * detInv;\n\t\tm10 = t10 * detInv;\n\t\tm01 = t01 * detInv;\n\t\tm02 = t02 * detInv;\n\t\tm20 = t20 * detInv;\n\t\tm21 = t21 * detInv;\n\t\tm12 = t12 * detInv;\n\t\tm30 = t30 * detInv;\n\t\tm03 = t03 * detInv;\n\t\tm31 = t31 * detInv;\n\t\tm13 = t13 * detInv;\n\t\tm23 = t23 * detInv;\n\t\tm32 = t32 * detInv;\n\n\t}\n\n\tpublic double determinant() {\n\t\tdouble result = m00 * ((m11 * m22 * m33 + m21 * m32 * m13 + m31 * m12 * m23) - m31 * m22 * m13 - m11 * m32 * m23 - m21 * m12 * m33);\n\t\tresult -= m10 * ((m01 * m22 * m33 + m21 * m32 * m03 + m31 * m02 * m23) - m31 * m22 * m03 - m01 * m32 * m23 - m21 * m02 * m33);\n\t\tresult += m20 * ((m01 * m12 * m33 + m11 * m32 * m03 + m31 * m02 * m13) - m31 * m12 * m03 - m01 * m32 * m13 - m11 * m02 * m33);\n\t\tresult -= m30 * ((m01 * m12 * m23 + m11 * m22 * m03 + m21 * m02 * m13) - m21 * m12 * m03 - m01 * m22 * m13 - m11 * m02 * m23);\n\t\treturn result;\n\t}\n\n\tprivate double determinant3x3(double e00, double e01, double e02, double e10, double e11, double e12, double e20, double e21, double e22) {\n\t\treturn e00 * (e11 * e22 - e12 * e21) + e01 * (e12 * e20 - e10 * e22) + e02 * (e10 * e21 - e11 * e20);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"Matrix4d(\\n\" + \"  \" + m00 + \", \" + m01 + \", \" + m02 + \", \" + m03 + \"\\n\" + \"  \" + m10 + \", \" + m11 + \", \" + m12 + \", \" + m13 + \"\\n\" + \"  \" + m20\n\t\t\t\t+ \", \" + m21 + \", \" + m22 + \", \" + m23 + \"\\n\" + \"  \" + m30 + \", \" + m31 + \", \" + m32 + \", \" + m33 + \"\\n\" + \")\\n\";\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/MatrixTranformations.java",
    "content": "package logisticspipes.utils.math;\n\nimport net.minecraft.util.EnumFacing;\n\npublic final class MatrixTranformations {\n\n\t/**\n\t * Deactivate constructor\n\t */\n\tprivate MatrixTranformations() {}\n\n\t/**\n\t * Mirrors the array on the Y axis by calculating offsets from 0.5F\n\t *\n\t * @param targetArray\n\t */\n\tpublic static void mirrorY(float[][] targetArray) {\n\t\tfloat temp = targetArray[1][0];\n\t\ttargetArray[1][0] = (targetArray[1][1] - 0.5F) * -1F + 0.5F; // 1 -> 0.5F -> -0.5F -> 0F\n\t\ttargetArray[1][1] = (temp - 0.5F) * -1F + 0.5F; // 0 -> -0.5F -> 0.5F -> 1F\n\t}\n\n\t/**\n\t * Shifts the coordinates around effectively rotating something. Zero state\n\t * is DOWN then -> NORTH -> WEST Note - To obtain Position, do a mirrorY()\n\t * before rotating\n\t *\n\t * @param targetArray the array that should be rotated\n\t */\n\tpublic static void rotate(float[][] targetArray) {\n\t\tfor (int i = 0; i < 2; i++) {\n\t\t\tfloat temp = targetArray[2][i];\n\t\t\ttargetArray[2][i] = targetArray[1][i];\n\t\t\ttargetArray[1][i] = targetArray[0][i];\n\t\t\ttargetArray[0][i] = temp;\n\t\t}\n\t}\n\n\t/**\n\t * @param targetArray the array that should be transformed\n\t * @param direction\n\t */\n\tpublic static void transform(float[][] targetArray, EnumFacing direction) {\n\t\tif ((direction.ordinal() & 0x1) == 1) {\n\t\t\tMatrixTranformations.mirrorY(targetArray);\n\t\t}\n\n\t\tfor (int i = 0; i < (direction.ordinal() >> 1); i++) {\n\t\t\tMatrixTranformations.rotate(targetArray);\n\t\t}\n\t}\n\n\t/**\n\t * Clones both dimensions of a float[][]\n\t *\n\t * @param source the float[][] to deepClone\n\t */\n\tpublic static float[][] deepClone(float[][] source) {\n\t\tfloat[][] target = source.clone();\n\t\tfor (int i = 0; i < target.length; i++) {\n\t\t\ttarget[i] = source[i].clone();\n\t\t}\n\t\treturn target;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vec2.java",
    "content": "package logisticspipes.utils.math;\n\nimport java.util.Objects;\nimport javax.annotation.ParametersAreNonnullByDefault;\n\nimport mcp.MethodsReturnNonnullByDefault;\n\n/**\n * 2-dimensional vector.\n * Imported from qcommon-croco (https://github.com/therealfarfetchd/qcommon)\n *\n * @author therealfarfetchd\n */\n@MethodsReturnNonnullByDefault\n@ParametersAreNonnullByDefault\npublic final class Vec2 {\n\n\tpublic static final Vec2 ORIGIN = new Vec2(0, 0);\n\n\tpublic final float x;\n\tpublic final float y;\n\n\tprivate float length = Float.NaN;\n\tprivate Vec2 normalized;\n\n\tpublic Vec2(float x, float y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t}\n\n\tpublic Vec2 add(Vec2 other) {\n\t\treturn new Vec2(this.x + other.x, this.y + other.y);\n\t}\n\n\tpublic Vec2 sub(Vec2 other) {\n\t\treturn new Vec2(this.x - other.x, this.y - other.y);\n\t}\n\n\tpublic Vec2 mul(Vec2 other) {\n\t\treturn new Vec2(this.x * other.x, this.y * other.y);\n\t}\n\n\tpublic Vec2 mul(float other) {\n\t\treturn new Vec2(this.x * other, this.y * other);\n\t}\n\n\tpublic Vec2 div(Vec2 other) {\n\t\treturn new Vec2(x / other.x, this.y / other.y);\n\t}\n\n\tpublic Vec2 div(float other) {\n\t\treturn new Vec2(this.x / other, this.y / other);\n\t}\n\n\tpublic float dot(Vec2 other) {\n\t\treturn this.x * other.x + this.y * other.y;\n\t}\n\n\tpublic float getLength() {\n\t\tif (Float.isNaN(length)) {\n\t\t\tlength = (float) Math.sqrt(x * x + y * y);\n\t\t}\n\n\t\treturn length;\n\t}\n\n\tpublic Vec2 getNormalized() {\n\t\tif (normalized == null) {\n\t\t\tnormalized = new Vec2(x / getLength(), y / getLength());\n\t\t\tnormalized.length = 1;\n\t\t}\n\n\t\treturn normalized;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (this == o) return true;\n\t\tif (o == null || getClass() != o.getClass()) return false;\n\t\tVec2 vec2 = (Vec2) o;\n\t\treturn Float.compare(vec2.x, x) == 0 &&\n\t\t\t\tFloat.compare(vec2.y, y) == 0;\n\t}\n\n\t@Override\n\tpublic int hashCode() {\n\t\treturn Objects.hash(x, y);\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"(%f, %f)\", x, y);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/VecmathUtil.java",
    "content": "package logisticspipes.utils.math;\n\nimport java.awt.Rectangle;\n\npublic class VecmathUtil {\n\n\tpublic static Vector3d clamp(Vector3d v, double min, double max) {\n\t\tv.x = clamp(v.x, min, max);\n\t\tv.y = clamp(v.y, min, max);\n\t\tv.z = clamp(v.z, min, max);\n\t\treturn v;\n\t}\n\n\tpublic static double clamp(double val, double min, double max) {\n\t\treturn val < min ? min : (Math.min(val, max));\n\t}\n\n\tpublic static int clamp(int val, int min, int max) {\n\t\treturn val < min ? min : (Math.min(val, max));\n\t}\n\n\t/**\n\t * Creates a perspective projection matrix.\n\t *\n\t * @param fovDegrees     The field of view angle in degrees.\n\t * @param near           near plane.\n\t * @param far            far plane.\n\t * @param viewportWidth  viewport width.\n\t * @param viewportHeight viewport height.\n\t * @return the matrix.\n\t */\n\tpublic static Matrix4d createProjectionMatrixAsPerspective(double fovDegrees, double near, double far, int viewportWidth, int viewportHeight) {\n\t\t// for impl details see gluPerspective doco in OpenGL reference manual\n\t\tdouble aspect = (double) viewportWidth / (double) viewportHeight;\n\n\t\tdouble theta = (Math.toRadians(fovDegrees) / 2d);\n\t\tdouble f = Math.cos(theta) / Math.sin(theta);\n\n\t\tdouble a = (far + near) / (near - far);\n\t\tdouble b = (2d * far * near) / (near - far);\n\n\t\treturn new Matrix4d(f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, a, b, 0, 0, -1, 0);\n\t}\n\n\t/**\n\t * Creates a look at matrix.\n\t *\n\t * @param eyePos    the position of the eye.\n\t * @param lookAtPos the point to look at.\n\t * @param upVec     the up vector.\n\t * @return the look at matrix.\n\t */\n\tpublic static Matrix4d createMatrixAsLookAt(Vector3d eyePos, Vector3d lookAtPos, Vector3d upVec) {\n\n\t\tVector3d eye = new Vector3d(eyePos);\n\t\tVector3d lookAt = new Vector3d(lookAtPos);\n\t\tVector3d up = new Vector3d(upVec);\n\n\t\tVector3d forwardVec = new Vector3d(lookAt);\n\t\tforwardVec.sub(eye);\n\t\tforwardVec.makeVectorLength(1);\n\n\t\tVector3d sideVec = new Vector3d();\n\t\tsideVec.cross(forwardVec, up);\n\t\tsideVec.makeVectorLength(1);\n\n\t\tVector3d upVed = new Vector3d();\n\t\tupVed.cross(sideVec, forwardVec);\n\t\tupVed.makeVectorLength(1);\n\n\t\tMatrix4d mat = new Matrix4d(sideVec.x, sideVec.y, sideVec.z, 0, upVed.x, upVed.y, upVed.z, 0, -forwardVec.x, -forwardVec.y, -forwardVec.z, 0, 0, 0, 0, 1);\n\n\t\teye.negate();\n\t\t// mat.transform(eye);\n\t\tmat.transformNormal(eye);\n\t\tmat.setTranslation(eye);\n\n\t\treturn mat;\n\t}\n\n\t/**\n\t * This function computes the ray that goes from the eye, through the\n\t * specified pixel.\n\t *\n\t * @param x         the x pixel location (x = 0 is the left most pixel)\n\t * @param y         the y pixel location (y = 0 is the bottom most pixel)\n\t * @param eyeOut    the eyes position.\n\t * @param normalOut the normal description the directional component of the ray.\n\t */\n\tpublic static void computeRayForPixel(Rectangle vp, Matrix4d ipm, Matrix4d ivm, int x, int y, Vector3d eyeOut, Vector3d normalOut) {\n\n\t\t// grab the eye's position\n\t\tivm.getTranslation(eyeOut);\n\n\t\tMatrix4d vpm = new Matrix4d();\n\t\tvpm.mul(ivm, ipm);\n\n\t\t// Calculate the pixel location in screen clip space (width and height from\n\t\t// -1 to 1)\n\t\tdouble screenX = (x - vp.getX()) / vp.getWidth();\n\t\tdouble screenY = (y - vp.getY()) / vp.getHeight();\n\t\tscreenX = (screenX * 2.0) - 1.0;\n\t\tscreenY = (screenY * 2.0) - 1.0;\n\n\t\t// Now calculate the XYZ location of this point on the near plane\n\t\tVector4d tmp = new Vector4d();\n\t\ttmp.x = screenX;\n\t\ttmp.y = screenY;\n\t\ttmp.z = -1;\n\t\ttmp.w = 1.0;\n\t\tvpm.transform(tmp);\n\n\t\tdouble w = tmp.w;\n\t\tVector3d nearXYZ = new Vector3d(tmp.x / w, tmp.y / w, tmp.z / w);\n\n\t\t// and then on the far plane\n\t\ttmp.x = screenX;\n\t\ttmp.y = screenY;\n\t\ttmp.z = 1;\n\t\ttmp.w = 1.0;\n\t\tvpm.transform(tmp);\n\n\t\tw = tmp.w;\n\t\tVector3d farXYZ = new Vector3d(tmp.x / w, tmp.y / w, tmp.z / w);\n\n\t\tnormalOut.set(farXYZ);\n\t\tnormalOut.sub(nearXYZ);\n\t\tnormalOut.makeVectorLength(1);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vector2d.java",
    "content": "package logisticspipes.utils.math;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Vector2d {\n\n\tpublic double x;\n\tpublic double y;\n\n\tpublic Vector2d(Vector2d vector3d) {\n\t\tthis.x = vector3d.x;\n\t\tthis.y = vector3d.y;\n\t}\n\n\tpublic Vector2d multiply(double i) {\n\t\tx *= i;\n\t\ty *= i;\n\t\treturn this;\n\t}\n\n\tpublic double abs() {\n\t\treturn Math.hypot(x, y);\n\t}\n\n\tpublic Vector2d add(Vector2d vector, double factor) {\n\t\tVector2d lVector = vector.clone().makeVectorLength(factor);\n\t\tx += lVector.x;\n\t\ty += lVector.y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2d add(Vector2d vector) {\n\t\tx += vector.x;\n\t\ty += vector.y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2d sub(Vector2d vector) {\n\t\tx -= vector.x;\n\t\ty -= vector.y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2d reverse() {\n\t\tx = -x;\n\t\ty = -y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2d makeVectorLength(double length) {\n\t\tdouble divide = Math.sqrt(Math.pow(abs(), 2) / Math.pow(length, 2));\n\t\tdouble multiply = 1 / divide;\n\t\tx *= multiply;\n\t\ty *= multiply;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"[%s,%s](%s)\", x, y, abs());\n\t}\n\n\t@Override\n\tpublic Vector2d clone() {\n\t\tVector2d vector = new Vector2d();\n\t\tvector.x = x;\n\t\tvector.y = y;\n\t\treturn vector;\n\t}\n\n\tpublic void set(double x, double y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t}\n\n\tpublic void set(Vector2d vector3d) {\n\t\tthis.set(vector3d.x, vector3d.y);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vector2f.java",
    "content": "package logisticspipes.utils.math;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Vector2f {\n\n\tpublic float x;\n\tpublic float y;\n\n\tpublic Vector2f(Vector2f vector3d) {\n\t\tthis.x = vector3d.x;\n\t\tthis.y = vector3d.y;\n\t}\n\n\tpublic Vector2f multiply(double i) {\n\t\tx *= i;\n\t\ty *= i;\n\t\treturn this;\n\t}\n\n\tpublic double abs() {\n\t\treturn Math.hypot(x, y);\n\t}\n\n\tpublic Vector2f add(Vector2f vector, double factor) {\n\t\tVector2f lVector = vector.clone().makeVectorLength(factor);\n\t\tx += lVector.x;\n\t\ty += lVector.y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2f add(Vector2f vector) {\n\t\tx += vector.x;\n\t\ty += vector.y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2f sub(Vector2f vector) {\n\t\tx -= vector.x;\n\t\ty -= vector.y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2f reverse() {\n\t\tx = -x;\n\t\ty = -y;\n\t\treturn this;\n\t}\n\n\tpublic Vector2f makeVectorLength(double length) {\n\t\tdouble divide = Math.sqrt(Math.pow(abs(), 2) / Math.pow(length, 2));\n\t\tdouble multiply = 1 / divide;\n\t\tx *= multiply;\n\t\ty *= multiply;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"[%s,%s](%s)\", x, y, abs());\n\t}\n\n\t@Override\n\tpublic Vector2f clone() {\n\t\tVector2f vector = new Vector2f();\n\t\tvector.x = x;\n\t\tvector.y = y;\n\t\treturn vector;\n\t}\n\n\tpublic void set(float x, float y) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t}\n\n\tpublic void set(Vector2f vector3d) {\n\t\tthis.set(vector3d.x, vector3d.y);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vector3d.java",
    "content": "package logisticspipes.utils.math;\n\nimport net.minecraft.util.math.Vec3d;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Vector3d {\n\n\tpublic double x;\n\tpublic double y;\n\tpublic double z;\n\n\tpublic Vector3d(Vector3d vector3d) {\n\t\tthis.x = vector3d.x;\n\t\tthis.y = vector3d.y;\n\t\tthis.z = vector3d.z;\n\t}\n\n\tpublic static Vector3d getFromAngles(double Yaw, double Pitch) {\n\t\tVector3d vector = new Vector3d();\n\t\tvector.x = Math.cos(Yaw) * Math.cos(Pitch);\n\t\tvector.y = Math.sin(Pitch);\n\t\tvector.z = Math.sin(Yaw) * Math.cos(Pitch);\n\t\treturn vector;\n\t}\n\n\tpublic Vector3d multiply(double i) {\n\t\tx *= i;\n\t\ty *= i;\n\t\tz *= i;\n\t\treturn this;\n\t}\n\n\tpublic double abs() {\n\t\treturn Math.hypot(x, Math.hypot(y, z));\n\t}\n\n\tpublic Vector3d add(Vector3d vector, double factor) {\n\t\tVector3d lVector = vector.clone().makeVectorLength(factor);\n\t\tx += lVector.x;\n\t\ty += lVector.y;\n\t\tz += lVector.z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3d add(Vector3d vector) {\n\t\tx += vector.x;\n\t\ty += vector.y;\n\t\tz += vector.z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3d sub(Vector3d vector) {\n\t\tx -= vector.x;\n\t\ty -= vector.y;\n\t\tz -= vector.z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3d negate() {\n\t\tx = -x;\n\t\ty = -y;\n\t\tz = -z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3d getOrtogonal(Double pX, Double pY, Double pZ) {\n\t\tif ((pX != null && pY != null && pZ != null) || (pX == null && pY == null) || (pY == null && pZ == null) || (pX == null && pZ == null)) {\n\t\t\tthrow new UnsupportedOperationException(\"One, only one parameter needs to be null\");\n\t\t}\n\t\tVector3d answer = new Vector3d();\n\t\tif (pX == null) {\n\t\t\tanswer.x = (((-pY) * y) - (pZ * z)) / x;\n\t\t\tanswer.y = pY;\n\t\t\tanswer.z = pZ;\n\t\t} else if (pY == null) {\n\t\t\tanswer.x = pX;\n\t\t\tanswer.y = (((-pX) * x) - (pZ * z)) / y;\n\t\t\tanswer.z = pZ;\n\t\t} else if (pZ == null) {\n\t\t\tanswer.x = pX;\n\t\t\tanswer.y = pY;\n\t\t\tanswer.z = (((-pX) * x) - (pY * y)) / z;\n\t\t}\n\t\treturn answer;\n\t}\n\n\tpublic Vector3d makeVectorLength(double length) {\n\t\tdouble divide = Math.sqrt(Math.pow(abs(), 2) / Math.pow(length, 2));\n\t\tdouble multiply = 1 / divide;\n\t\tx *= multiply;\n\t\ty *= multiply;\n\t\tz *= multiply;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"[%s,%s,%s](%s)\", x, y, z, abs());\n\t}\n\n\t@Override\n\tpublic Vector3d clone() {\n\t\tVector3d vector = new Vector3d();\n\t\tvector.x = x;\n\t\tvector.y = y;\n\t\tvector.z = z;\n\t\treturn vector;\n\t}\n\n\tpublic void set(double x, double y, double z) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t}\n\n\tpublic void set(Vector3d vector3d) {\n\t\tthis.set(vector3d.x, vector3d.y, vector3d.z);\n\t}\n\n\tpublic void cross(Vector3d v1, Vector3d v2) {\n\t\tx = v1.y * v2.z - v1.z * v2.y;\n\t\ty = v2.x * v1.z - v2.z * v1.x;\n\t\tz = v1.x * v2.y - v1.y * v2.x;\n\t}\n\n\tpublic Vec3d toVec3d() {\n\t\treturn new Vec3d(x, y, z);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vector3f.java",
    "content": "package logisticspipes.utils.math;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Vector3f {\n\n\tpublic float x;\n\tpublic float y;\n\tpublic float z;\n\n\tpublic Vector3f(Vector3f vector3d) {\n\t\tthis.x = vector3d.x;\n\t\tthis.y = vector3d.y;\n\t\tthis.z = vector3d.z;\n\t}\n\n\tpublic static Vector3f getFromAngles(double Yaw, double Pitch) {\n\t\tVector3f vector = new Vector3f();\n\t\tvector.x = (float) (Math.cos(Yaw) * Math.cos(Pitch));\n\t\tvector.y = (float) Math.sin(Pitch);\n\t\tvector.z = (float) (Math.sin(Yaw) * Math.cos(Pitch));\n\t\treturn vector;\n\t}\n\n\tpublic Vector3f multiply(double i) {\n\t\tx *= i;\n\t\ty *= i;\n\t\tz *= i;\n\t\treturn this;\n\t}\n\n\tpublic double abs() {\n\t\treturn Math.hypot(x, Math.hypot(y, z));\n\t}\n\n\tpublic Vector3f add(Vector3f vector, double factor) {\n\t\tVector3f lVector = vector.clone().makeVectorLength(factor);\n\t\tx += lVector.x;\n\t\ty += lVector.y;\n\t\tz += lVector.z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3f add(Vector3f vector) {\n\t\tx += vector.x;\n\t\ty += vector.y;\n\t\tz += vector.z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3f sub(Vector3f vector) {\n\t\tx -= vector.x;\n\t\ty -= vector.y;\n\t\tz -= vector.z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3f negate() {\n\t\tx = -x;\n\t\ty = -y;\n\t\tz = -z;\n\t\treturn this;\n\t}\n\n\tpublic Vector3f getOrtogonal(Float pX, Float pY, Float pZ) {\n\t\tif ((pX != null && pY != null && pZ != null) || (pX == null && pY == null) || (pY == null && pZ == null) || (pX == null && pZ == null)) {\n\t\t\tthrow new UnsupportedOperationException(\"One, only one parameter needs to be null\");\n\t\t}\n\t\tVector3f answer = new Vector3f();\n\t\tif (pX == null) {\n\t\t\tanswer.x = (((-pY) * y) - (pZ * z)) / x;\n\t\t\tanswer.y = pY;\n\t\t\tanswer.z = pZ;\n\t\t} else if (pY == null) {\n\t\t\tanswer.x = pX;\n\t\t\tanswer.y = (((-pX) * x) - (pZ * z)) / y;\n\t\t\tanswer.z = pZ;\n\t\t} else if (pZ == null) {\n\t\t\tanswer.x = pX;\n\t\t\tanswer.y = pY;\n\t\t\tanswer.z = (((-pX) * x) - (pY * y)) / z;\n\t\t}\n\t\treturn answer;\n\t}\n\n\tpublic Vector3f makeVectorLength(double length) {\n\t\tdouble divide = Math.sqrt(Math.pow(abs(), 2) / Math.pow(length, 2));\n\t\tdouble multiply = 1 / divide;\n\t\tx *= multiply;\n\t\ty *= multiply;\n\t\tz *= multiply;\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn String.format(\"[%s,%s,%s](%s)\", x, y, z, abs());\n\t}\n\n\t@Override\n\tpublic Vector3f clone() {\n\t\tVector3f vector = new Vector3f();\n\t\tvector.x = x;\n\t\tvector.y = y;\n\t\tvector.z = z;\n\t\treturn vector;\n\t}\n\n\tpublic void set(float x, float y, float z) {\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t}\n\n\tpublic void set(Vector3f vector3d) {\n\t\tthis.set(vector3d.x, vector3d.y, vector3d.z);\n\t}\n\n\tpublic void cross(Vector3f v1, Vector3f v2) {\n\t\tx = v1.y * v2.z - v1.z * v2.y;\n\t\ty = v2.x * v1.z - v2.z * v1.x;\n\t\tz = v1.x * v2.y - v1.y * v2.x;\n\t}\n\n\tpublic void normalize() {\n\t\tmakeVectorLength(1);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vector4d.java",
    "content": "package logisticspipes.utils.math;\n\nimport lombok.AllArgsConstructor;\nimport lombok.NoArgsConstructor;\n\n@AllArgsConstructor\n@NoArgsConstructor\npublic class Vector4d {\n\n\tpublic double x;\n\tpublic double y;\n\tpublic double z;\n\tpublic double w;\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/math/Vertex.java",
    "content": "package logisticspipes.utils.math;\n\npublic class Vertex {\n\n\tpublic Vector3d xyz = new Vector3d();\n\tpublic Vector2f uv;\n\tpublic Vector3f normal;\n\n\tpublic Vertex(Vector3d xyz, Vector3f normal, Vector2f uv) {\n\t\tthis.xyz.set(xyz);\n\t\tthis.normal = new Vector3f(normal);\n\t\tthis.uv = new Vector2f(uv);\n\t}\n\n\tpublic double x() {\n\t\treturn xyz.x;\n\t}\n\n\tpublic double y() {\n\t\treturn xyz.y;\n\t}\n\n\tpublic double z() {\n\t\treturn xyz.z;\n\t}\n\n\tpublic float nx() {\n\t\treturn normal.x;\n\t}\n\n\tpublic float ny() {\n\t\treturn normal.y;\n\t}\n\n\tpublic float nz() {\n\t\treturn normal.z;\n\t}\n\n\tpublic float u() {\n\t\treturn uv.x;\n\t}\n\n\tpublic float v() {\n\t\treturn uv.y;\n\t}\n\n\tpublic float r() {\n\t\treturn 1;\n\t}\n\n\tpublic float g() {\n\t\treturn 1;\n\t}\n\n\tpublic float b() {\n\t\treturn 1;\n\t}\n\n\tpublic float a() {\n\t\treturn 0;\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/string/ChatColor.java",
    "content": "package logisticspipes.utils.string;\n\npublic enum ChatColor {\n\t/**\n\t * Represents black\n\t */\n\tBLACK('0'),\n\t/**\n\t * Represents dark blue\n\t */\n\tDARK_BLUE('1'),\n\t/**\n\t * Represents dark green\n\t */\n\tDARK_GREEN('2'),\n\t/**\n\t * Represents dark blue (aqua)\n\t */\n\tDARK_AQUA('3'),\n\t/**\n\t * Represents dark red\n\t */\n\tDARK_RED('4'),\n\t/**\n\t * Represents dark purple\n\t */\n\tDARK_PURPLE('5'),\n\t/**\n\t * Represents gold\n\t */\n\tGOLD('6'),\n\t/**\n\t * Represents gray\n\t */\n\tGRAY('7'),\n\t/**\n\t * Represents dark gray\n\t */\n\tDARK_GRAY('8'),\n\t/**\n\t * Represents blue\n\t */\n\tBLUE('9'),\n\t/**\n\t * Represents green\n\t */\n\tGREEN('a'),\n\t/**\n\t * Represents aqua\n\t */\n\tAQUA('b'),\n\t/**\n\t * Represents red\n\t */\n\tRED('c'),\n\t/**\n\t * Represents light purple\n\t */\n\tLIGHT_PURPLE('d'),\n\t/**\n\t * Represents yellow\n\t */\n\tYELLOW('e'),\n\t/**\n\t * Represents white\n\t */\n\tWHITE('f'),\n\t/**\n\t * Represents magical characters that change around randomly\n\t */\n\tMAGIC('k', true),\n\t/**\n\t * Makes the text bold.\n\t */\n\tBOLD('l', true),\n\t/**\n\t * Makes a line appear through the text.\n\t */\n\tSTRIKETHROUGH('m', true),\n\t/**\n\t * Makes the text appear underlined.\n\t */\n\tUNDERLINE('n', true),\n\t/**\n\t * Makes the text italic.\n\t */\n\tITALIC('o', true),\n\t/**\n\t * Resets all previous chat colors or formats.\n\t */\n\tRESET('r');\n\n\t/**\n\t * The special character which prefixes all chat colour codes. Use this if\n\t * you need to dynamically convert colour codes from your custom format.\n\t */\n\tpublic static final char COLOR_CHAR = '\\u00A7';\n\n\tprivate final char code;\n\tprivate final boolean isFormat;\n\tprivate final String toString;\n\n\tChatColor(char code) {\n\t\tthis(code, false);\n\t}\n\n\tChatColor(char code, boolean isFormat) {\n\t\tthis.code = code;\n\t\tthis.isFormat = isFormat;\n\t\ttoString = new String(new char[] { ChatColor.COLOR_CHAR, code });\n\t}\n\n\t/**\n\t * Gets the char value associated with this color\n\t *\n\t * @return A char value of this color code\n\t */\n\tpublic char getChar() {\n\t\treturn code;\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn toString;\n\t}\n\n\t/**\n\t * Checks if this code is a format code as opposed to a color code.\n\t */\n\tpublic boolean isFormat() {\n\t\treturn isFormat;\n\t}\n\n\t/**\n\t * Checks if this code is a color code as opposed to a format code.\n\t */\n\tpublic boolean isColor() {\n\t\treturn !isFormat && this != RESET;\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/string/StringUtils.java",
    "content": "package logisticspipes.utils.string;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport net.minecraft.client.gui.FontRenderer;\n\npublic final class StringUtils {\n\tpublic static final List<String> UNTRANSLATED_STRINGS = new ArrayList<>();\n\n\tprivate StringUtils() {}\n\n\tpublic static String getWithMaxWidth(String name, int width, FontRenderer fontRenderer) {\n\t\tboolean changed = false;\n\t\twhile (fontRenderer.getStringWidth(name) > width) {\n\t\t\tname = name.substring(0, name.length() - 2);\n\t\t\tchanged = true;\n\t\t}\n\t\tif (changed) {\n\t\t\tname += \"...\";\n\t\t}\n\t\treturn name;\n\t}\n\n\tpublic static String getStringWithSpacesFromInteger(int source) {\n\t\tString data = Integer.toString(source);\n\t\treturn StringUtils.insertThousandsSeparators(data);\n\t}\n\n\tpublic static String getStringWithSpacesFromLong(long source) {\n\t\tString data = Long.toString(source);\n\t\treturn StringUtils.insertThousandsSeparators(data);\n\t}\n\n\tpublic static String insertThousandsSeparators(String source) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tint i;\n\t\tfor (i = source.length(); i > 3; i -= 3) {\n\t\t\tsb.insert(0, source.substring(i - 3, i));\n\t\t\tsb.insert(0, ' ');\n\t\t}\n\t\tsb.insert(0, source.substring(0, i));\n\t\treturn sb.toString();\n\t}\n\n}\n\n"
  },
  {
    "path": "common/logisticspipes/utils/transactor/IInvSlot.java",
    "content": "package logisticspipes.utils.transactor;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\npublic interface IInvSlot {\n\n\tboolean canPutStackInSlot(@Nonnull ItemStack stack);\n\n\t@Nonnull\n\tItemStack getStackInSlot();\n\n\t@Nonnull\n\tItemStack insertItem(@Nonnull ItemStack stack, boolean simulate);\n\n\t@Nonnull\n\tItemStack extractItem(int amount, boolean simulate);\n\n\tint getSlotLimit();\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/transactor/ITransactor.java",
    "content": "package logisticspipes.utils.transactor;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\npublic interface ITransactor {\n\n\t/**\n\t * Adds stack to the transactor\n\t * @param stack to add.\n\t * @param orientation side where transaction is being performed\n\t * @param doAdd whether to commit or simulate transaction\n\t * @return added stack.\n\t */\n\t@Nonnull\n\tItemStack add(@Nonnull ItemStack stack, EnumFacing orientation, boolean doAdd);\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/transactor/InventoryIterator.java",
    "content": "package logisticspipes.utils.transactor;\n\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.items.IItemHandler;\n\npublic final class InventoryIterator {\n\n\t/**\n\t * Deactivate constructor\n\t */\n\tprivate InventoryIterator() {}\n\n\t/**\n\t * Returns an Iterable object for the specified side of the inventory.\n\t *\n\t * @param inv\n\t * @param side\n\t * @return Iterable\n\t */\n\tpublic static Iterable<IInvSlot> getIterable(IItemHandler inv, EnumFacing side) {\n\n\t\treturn new InventoryIteratorSimple(inv);\n\t}\n\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/transactor/InventoryIteratorSimple.java",
    "content": "package logisticspipes.utils.transactor;\n\nimport java.util.Iterator;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\n\nimport net.minecraftforge.items.IItemHandler;\n\nclass InventoryIteratorSimple implements Iterable<IInvSlot> {\n\n\tprivate final IItemHandler inv;\n\n\tInventoryIteratorSimple(IItemHandler inv) {\n\t\tthis.inv = inv;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic Iterator<IInvSlot> iterator() {\n\t\treturn new Iterator<IInvSlot>() {\n\n\t\t\tint slot = 0;\n\n\t\t\t@Override\n\t\t\tpublic boolean hasNext() {\n\t\t\t\treturn slot < inv.getSlots();\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic IInvSlot next() {\n\t\t\t\treturn new InvSlot(slot++);\n\t\t\t}\n\n\t\t};\n\t}\n\n\tprivate class InvSlot implements IInvSlot {\n\n\t\tprivate final int slot;\n\n\t\tpublic InvSlot(int slot) {\n\t\t\tthis.slot = slot;\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic ItemStack getStackInSlot() {\n\t\t\treturn inv.getStackInSlot(slot);\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic ItemStack insertItem(@Nonnull ItemStack stack, boolean simulate) {\n\t\t\treturn inv.insertItem(slot, stack.copy(), simulate);\n\t\t}\n\n\t\t@Nonnull\n\t\t@Override\n\t\tpublic ItemStack extractItem(int amount, boolean simulate) {\n\t\t\treturn inv.extractItem(slot, amount, simulate);\n\t\t}\n\n\t\t@Override\n\t\tpublic int getSlotLimit() {\n\t\t\treturn inv.getSlotLimit(slot);\n\t\t}\n\n\t\t@Override\n\t\tpublic boolean canPutStackInSlot(@Nonnull ItemStack stack) {\n\t\t\tItemStack toTest = stack.copy();\n\t\t\ttoTest.setCount(1);\n\t\t\treturn inv.insertItem(slot, toTest, true).isEmpty();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/transactor/Transactor.java",
    "content": "package logisticspipes.utils.transactor;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\npublic abstract class Transactor implements ITransactor {\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack add(@Nonnull ItemStack stack, EnumFacing orientation, boolean doAdd) {\n\t\tItemStack added = stack.copy();\n\t\tadded.setCount(inject(stack, orientation, doAdd));\n\t\treturn added;\n\t}\n\n\tpublic abstract int inject(@Nonnull ItemStack stack, EnumFacing orientation, boolean doAdd);\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/transactor/TransactorSimple.java",
    "content": "package logisticspipes.utils.transactor;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.items.IItemHandler;\n\npublic class TransactorSimple extends Transactor {\n\n\tprotected IItemHandler inventory;\n\n\tpublic TransactorSimple(IItemHandler inventory) {\n\t\tthis.inventory = inventory;\n\t}\n\n\t@Override\n\tpublic int inject(@Nonnull ItemStack stack, EnumFacing orientation, boolean doAdd) {\n\t\tList<IInvSlot> filledSlots = new ArrayList<>(inventory.getSlots());\n\t\tList<IInvSlot> emptySlots = new ArrayList<>(inventory.getSlots());\n\t\tfor (IInvSlot slot : InventoryIterator.getIterable(inventory, orientation)) {\n\t\t\tif (slot.canPutStackInSlot(stack)) {\n\t\t\t\tif (slot.getStackInSlot().isEmpty()) {\n\t\t\t\t\temptySlots.add(slot);\n\t\t\t\t} else {\n\t\t\t\t\tfilledSlots.add(slot);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tint injected = 0;\n\t\tinjected = tryPut(stack, filledSlots, injected, doAdd);\n\t\tinjected = tryPut(stack, emptySlots, injected, doAdd);\n\n\t\treturn injected;\n\t}\n\n\tprivate int tryPut(@Nonnull ItemStack stack, List<IInvSlot> slots, int injected, boolean doAdd) {\n\t\tint realInjected = injected;\n\n\t\tif (realInjected >= stack.getCount()) {\n\t\t\treturn realInjected;\n\t\t}\n\n\t\tfor (IInvSlot slot : slots) {\n\t\t\tItemStack stackInSlot = slot.getStackInSlot();\n\t\t\tif (stackInSlot.isEmpty() || canStacksMerge(stackInSlot, stack)) {\n\t\t\t\tint used = addToSlot(slot, stack, realInjected, doAdd);\n\t\t\t\tif (used > 0) {\n\t\t\t\t\trealInjected += used;\n\t\t\t\t\tif (realInjected >= stack.getCount()) {\n\t\t\t\t\t\treturn realInjected;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn realInjected;\n\t}\n\n\t/**\n\t * @param slot\n\t * @param stack\n\t * @param injected Amount not to move?\n\t * @param doAdd\n\t * @return Return the number of items moved.\n\t */\n\tprotected int addToSlot(IInvSlot slot, @Nonnull ItemStack stack, int injected, boolean doAdd) {\n\t\tint available = stack.getCount() - injected;\n\n\t\tItemStack newStack = stack.copy();\n\t\tnewStack.setCount(available);\n\n\t\tItemStack rest = slot.insertItem(newStack, !doAdd);\n\t\treturn available - rest.getCount();\n\t}\n\n\tprivate boolean canStacksMerge(@Nonnull ItemStack stack1, @Nonnull ItemStack stack2) {\n\t\tif (stack1.isEmpty() || stack2.isEmpty()) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!stack1.isItemEqual(stack2)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn ItemStack.areItemStackTagsEqual(stack1, stack2);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/tuples/Pair.java",
    "content": "package logisticspipes.utils.tuples;\n\nimport java.util.Map;\nimport java.util.function.BinaryOperator;\nimport java.util.stream.Collector;\nimport java.util.stream.Collectors;\n\nimport lombok.Data;\n\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder;\n\n@Data\npublic class Pair<T1, T2> implements ILPCCTypeHolder {\n\n\tprivate final Object[] ccTypeHolder = new Object[1];\n\tprotected T1 value1;\n\tprotected T2 value2;\n\n\tpublic Pair(kotlin.Pair<T1, T2> kotlinPair) {\n\t\tthis(kotlinPair.component1(), kotlinPair.component2());\n\t}\n\n\tpublic Pair(T1 value1, T2 value2) {\n\t\tthis.value1 = value1;\n\t\tthis.value2 = value2;\n\t}\n\n\tpublic final T1 component1() {\n\t\treturn value1;\n\t}\n\n\tpublic final T2 component2() {\n\t\treturn value2;\n\t}\n\n\tpublic Pair<T1, T2> copy() {\n\t\treturn new Pair<>(value1, value2);\n\t}\n\n\t@Override\n\tpublic Object[] getTypeHolder() {\n\t\treturn ccTypeHolder;\n\t}\n\n\tpublic static <T1, T2> Collector<Pair<T1, T2>, ?, Map<T1, T2>> toMap() {\n\t\treturn Collectors.toMap(Pair::getValue1, Pair::getValue2);\n\t}\n\n\tpublic static <T1, T2> Collector<Pair<T1, T2>, ?, Map<T1, T2>> toMap(BinaryOperator<T2> mergeFunction) {\n\t\treturn Collectors.toMap(Pair::getValue1, Pair::getValue2, mergeFunction);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/tuples/Quartet.java",
    "content": "package logisticspipes.utils.tuples;\n\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.ToString;\n\n@Data\n@EqualsAndHashCode(callSuper = true)\n@ToString(callSuper = true)\npublic class Quartet<T1, T2, T3, T4> extends Triplet<T1, T2, T3> {\n\n\tprotected T4 value4;\n\n\tpublic Quartet(T1 value1, T2 value2, T3 value3, T4 value4) {\n\t\tsuper(value1, value2, value3);\n\t\tthis.value4 = value4;\n\t}\n\n\t@Override\n\tpublic Quartet<T1, T2, T3, T4> copy() {\n\t\treturn new Quartet<>(value1, value2, value3, value4);\n\t}\n}\n"
  },
  {
    "path": "common/logisticspipes/utils/tuples/Triplet.java",
    "content": "package logisticspipes.utils.tuples;\n\nimport lombok.Data;\nimport lombok.EqualsAndHashCode;\nimport lombok.ToString;\n\n@Data\n@EqualsAndHashCode(callSuper = true)\n@ToString(callSuper = true)\npublic class Triplet<T1, T2, T3> extends Pair<T1, T2> {\n\n\tprotected T3 value3;\n\n\tpublic Triplet(T1 value1, T2 value2, T3 value3) {\n\t\tsuper(value1, value2);\n\t\tthis.value3 = value3;\n\t}\n\n\t@Override\n\tpublic Triplet<T1, T2, T3> copy() {\n\t\treturn new Triplet<>(value1, value2, value3);\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/com/enderio/core/api/common/util/IProgressTile.java",
    "content": "package com.enderio.core.api.common.util;\n\npublic interface IProgressTile {\n\n\tfloat getProgress();\n}\n"
  },
  {
    "path": "dummy/src/main/java/com/enderio/core/common/util/BlockCoord.java",
    "content": "package com.enderio.core.common.util;\n\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.world.IBlockAccess;\n\npublic class BlockCoord {\n\n\tpublic TileEntity getTileEntity(IBlockAccess world) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/com/enderio/core/common/util/InventoryWrapper.java",
    "content": "package com.enderio.core.common.util;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.IInventory;\nimport net.minecraft.inventory.ISidedInventory;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.text.ITextComponent;\nimport net.minecraft.util.text.TextComponentString;\n\npublic class InventoryWrapper implements ISidedInventory {\n\n\tpublic static ISidedInventory asSidedInventory(IInventory inv) {\n\t\tif (inv == null) {\n\t\t\treturn null;\n\t\t}\n\t\tif (inv instanceof ISidedInventory) {\n\t\t\treturn (ISidedInventory) inv;\n\t\t}\n\t\treturn new InventoryWrapper(inv);\n\t}\n\n\tpublic InventoryWrapper(IInventory inventory) {\n\t}\n\n\tpublic IInventory getWrappedInv() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic int getSizeInventory() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic boolean isEmpty() {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack getStackInSlot(int slot) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack decrStackSize(int slot, int amount) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\tpublic void setInventorySlotContents(int slot, @Nullable ItemStack itemStack) {\n\n\t}\n\n\t@Override\n\tpublic int getInventoryStackLimit() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void markDirty() {\n\t}\n\n\t@Override\n\tpublic boolean isUsableByPlayer(@Nonnull EntityPlayer player) {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean isItemValidForSlot(int slot, @Nonnull ItemStack itemStack) {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic int[] getSlotsForFace(@Nonnull EnumFacing side) {\n\t\treturn new int[0];\n\t}\n\n\t@Override\n\tpublic boolean canInsertItem(int slot, @Nonnull ItemStack itemStack, @Nonnull EnumFacing side) {\n\t\treturn isItemValidForSlot(slot, itemStack);\n\t}\n\n\t@Override\n\tpublic boolean canExtractItem(int slot, @Nonnull ItemStack itemStack, @Nonnull EnumFacing side) {\n\t\treturn slot >= 0 && slot < getSizeInventory();\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ItemStack removeStackFromSlot(int index) {\n\t\treturn ItemStack.EMPTY;\n\t}\n\n\t@Override\n\tpublic void openInventory(@Nonnull EntityPlayer player) {\n\t}\n\n\t@Override\n\tpublic void closeInventory(@Nonnull EntityPlayer player) {\n\t}\n\n\t@Override\n\tpublic int getField(int id) {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void setField(int id, int value) {\n\t}\n\n\t@Override\n\tpublic int getFieldCount() {\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic void clear() {\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic String getName() {\n\t\treturn \"\";\n\t}\n\n\t@Override\n\tpublic boolean hasCustomName() {\n\t\treturn false;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic ITextComponent getDisplayName() {\n\t\treturn new TextComponentString(\"\");\n\t}\n\n}"
  },
  {
    "path": "dummy/src/main/java/com/enderio/core/common/util/RoundRobinIterator.java",
    "content": "package com.enderio.core.common.util;\n\nimport java.util.Iterator;\nimport javax.annotation.Nonnull;\n\npublic class RoundRobinIterator<T> implements Iterable<T>, Iterator<T> {\n\n\t@Override\n\t@Nonnull\n\tpublic Iterator<T> iterator() {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic boolean hasNext() {\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic T next() {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void remove() {\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/cpw/mods/ironchest/client/gui/chest/GUIChest.java",
    "content": "package cpw.mods.ironchest.client.gui.chest;\n\nimport net.minecraft.client.gui.inventory.GuiContainer;\nimport net.minecraft.inventory.Container;\n\npublic class GUIChest extends GuiContainer {\n\n\tpublic GUIChest(Container par1Container) {\n\t\tsuper(par1Container);\n\t}\n\n\t@Override\n\tprotected void drawGuiContainerBackgroundLayer(float f, int i, int j) {}\n}\n"
  },
  {
    "path": "dummy/src/main/java/cpw/mods/ironchest/common/tileentity/chest/TileEntityIronChest.java",
    "content": "package cpw.mods.ironchest.common.tileentity.chest;\n\nimport net.minecraft.tileentity.TileEntity;\n\npublic class TileEntityIronChest extends TileEntity {\n\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/AbstractConduit.java",
    "content": "package crazypants.enderio.conduit;\n\nimport net.minecraft.util.EnumFacing;\n\nimport com.enderio.core.common.util.BlockCoord;\n\npublic class AbstractConduit implements IConduit {\n\n\t@Override\n\tpublic ConnectionMode getConnectionMode(EnumFacing dir) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic BlockCoord getLocation() {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/ConnectionMode.java",
    "content": "package crazypants.enderio.conduit;\n\npublic enum ConnectionMode {\n\tIN_OUT(),\n\tINPUT(),\n\tOUTPUT(),\n\tDISABLED(),\n\tNOT_SET()\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/IConduit.java",
    "content": "package crazypants.enderio.conduit;\n\nimport net.minecraft.util.EnumFacing;\n\nimport com.enderio.core.common.util.BlockCoord;\n\npublic interface IConduit {\n\n\tConnectionMode getConnectionMode(EnumFacing dir);\n\n\tBlockCoord getLocation();\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/IConduitBundle.java",
    "content": "package crazypants.enderio.conduit;\n\npublic interface IConduitBundle {\n\n\tboolean hasType(Class<? extends IConduit> type);\n\n\t<T extends IConduit> T getConduit(Class<T> type);\n\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/item/IItemConduit.java",
    "content": "package crazypants.enderio.conduit.item;\n\nimport crazypants.enderio.conduit.IConduit;\n\npublic interface IItemConduit extends IConduit {\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/item/ItemConduit.java",
    "content": "package crazypants.enderio.conduit.item;\n\nimport com.enderio.core.common.util.BlockCoord;\nimport crazypants.enderio.conduit.AbstractConduit;\n\npublic class ItemConduit extends AbstractConduit implements IItemConduit {\n\n\t@Override\n\tpublic BlockCoord getLocation() {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/conduit/liquid/ILiquidConduit.java",
    "content": "package crazypants.enderio.conduit.liquid;\n\nimport crazypants.enderio.conduit.IConduit;\n\npublic interface ILiquidConduit extends IConduit {\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/machine/transceiver/Channel.java",
    "content": "package crazypants.enderio.machine.transceiver;\n\npublic class Channel {\n\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/machine/transceiver/ChannelType.java",
    "content": "package crazypants.enderio.machine.transceiver;\n\npublic enum ChannelType {\n\tPOWER,\n\tITEM,\n\tFLUID;\n\n\tpublic static final ChannelType[] VALUES = values();\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/machine/transceiver/ServerChannelRegister.java",
    "content": "package crazypants.enderio.machine.transceiver;\n\nimport com.enderio.core.common.util.RoundRobinIterator;\n\npublic class ServerChannelRegister {\n\n\tpublic static ServerChannelRegister instance;\n\n\tpublic RoundRobinIterator<TileTransceiver> getIterator(Channel channel) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/crazypants/enderio/machine/transceiver/TileTransceiver.java",
    "content": "package crazypants.enderio.machine.transceiver;\n\nimport java.util.Set;\n\nimport net.minecraft.tileentity.TileEntity;\n\npublic class TileTransceiver extends TileEntity {\n\n\tpublic Set<Channel> getSendChannels(ChannelType type) {\n\t\treturn null;\n\t}\n\n\tpublic Set<Channel> getRecieveChannels(ChannelType type) {\n\t\treturn null;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/ic2/api/classic/tile/machine/IProgressMachine.java",
    "content": "package ic2.api.classic.tile.machine;\n\npublic interface IProgressMachine {\n\tfloat getProgress();\n\tfloat getMaxProgress();\n}\n"
  },
  {
    "path": "dummy/src/main/java/ic2/core/block/machine/tileentity/TileEntityStandardMachine.java",
    "content": "package ic2.core.block.machine.tileentity;\n\nimport net.minecraft.tileentity.TileEntity;\n\npublic class TileEntityStandardMachine extends TileEntity {\n\n\tpublic float getProgress() {\n\t\treturn 0.0F;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/org/luaj/vm2/LuaNil.java",
    "content": "package org.luaj.vm2;\n\npublic class LuaNil extends LuaValue {\n\n\tstatic final LuaNil _NIL = new LuaNil();\n\n\t@Override\n\tpublic int type() {\n\t\treturn 0;\n\t}\n\n}\n"
  },
  {
    "path": "dummy/src/main/java/org/luaj/vm2/LuaTable.java",
    "content": "package org.luaj.vm2;\n\npublic class LuaTable extends LuaValue {\n\n\tpublic Varargs next(LuaValue k) {\n\t\treturn null;\n\t}\n\n\tpublic void set(LuaValue k, LuaValue v) {\n\n\t}\n\n\t@Override\n\tpublic int type() {\n\t\treturn 0;\n\t}\n}\n"
  },
  {
    "path": "dummy/src/main/java/org/luaj/vm2/LuaValue.java",
    "content": "package org.luaj.vm2;\n\npublic abstract class LuaValue {\n\n\tpublic static final LuaValue NIL = LuaNil._NIL;\n\tpublic static final int TTABLE = 5;\n\n\tpublic boolean isnil() {\n\t\treturn false;\n\t}\n\n\tpublic String tojstring() {\n\t\treturn null;\n\t}\n\n\tabstract public int type();\n}\n"
  },
  {
    "path": "dummy/src/main/java/org/luaj/vm2/Varargs.java",
    "content": "package org.luaj.vm2;\n\npublic abstract class Varargs {\n\n\tabstract public LuaValue arg1();\n\n\tabstract public LuaValue arg(int i);\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.jar",
    "content": "version https://git-lfs.github.com/spec/v1\noid sha256:575098db54a998ff1c6770b352c3b16766c09848bee7555dab09afc34e8cf590\nsize 59821\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Sets default memory used for gradle commands. Can be overridden by user or command line properties.\n# This is required to provide enough memory for the Minecraft decompilation process.\norg.gradle.jvmargs=-Xmx3G\norg.gradle.daemon=false\nkotlin_version = 1.7.10\nkannotations_version = 23.0.0\nkcoroutines_version = 1.6.4\nkserialization_version = 1.4.0\nkaml_version = 0.47.0\nshadow_version = 6.1.0\nmcversion = 1.12.2\nforge_version = 1.12.2-14.23.5.2860\nmappings_version = 20180814-1.12\nforgegradle_version = 5.1.61\ncursegradle_version = 1.4.0\nlombok_plugin_version = 5.3.3.3\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\nAPP_HOME=$( cd \"${APP_HOME:-./}\" && pwd -P ) || exit\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=${0##*/}\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n# Collect all arguments for the java command;\n#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of\n#     shell script including quotes and variable substitutions, so put them in\n#     double quotes to make sure that they get re-expanded; and\n#   * put everything else in single quotes, so that it's not re-expanded.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        org.gradle.wrapper.GradleWrapperMain \\\n        \"$@\"\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "jitpack.yml",
    "content": "jdk:\n  - openjdk8\nbefore_install:\n  - git lfs install\n  - git lfs fetch\n  - git lfs checkout\ninstall:\n  - ./gradlew clean install -xtest\n"
  },
  {
    "path": "lib/appliedenergistics2-rv6-stable-7-api.jar",
    "content": "version https://git-lfs.github.com/spec/v1\noid sha256:4e43f36b649880fe178260da2261e9c0781aacbbd03aedda8a267e88f017a7b6\nsize 434012\n"
  },
  {
    "path": "lombok.config",
    "content": "lombok.accessors.chain = true\n"
  },
  {
    "path": "resources/META-INF/lp_at.cfg",
    "content": "public net.minecraft.client.gui.Gui field_73735_i #zLevel\npublic-f net.minecraft.inventory.Slot field_75224_c #inventory\nprotected net.minecraft.client.gui.inventory.GuiContainer func_146977_a(Lnet/minecraft/inventory/Slot;)V #drawSlot\nprotected net.minecraft.client.gui.inventory.GuiContainer func_146981_a(Lnet/minecraft/inventory/Slot;II)Z #isMouseOverSlot\nprotected net.minecraft.inventory.Container field_94536_g #dragEvent\nprotected net.minecraft.inventory.Container field_94535_f #dragMode\nprotected net.minecraft.inventory.Container field_94537_h #dragSlots\npublic net.minecraft.client.renderer.EntityRenderer func_78479_a(FI)V #setupCameraTransform\npublic-f net.minecraft.creativetab.CreativeTabs field_78034_o #tabLabel\nprotected net.minecraft.client.gui.GuiScreen field_175286_t #clickedLinkURI\npublic net.minecraft.client.gui.inventory.GuiContainer field_147006_u # hoveredSlot\n"
  },
  {
    "path": "resources/assets/logisticspipes/blockstates/pipe.json",
    "content": "{\n  \"variants\": {\n    \"normal\": [\n      {\n        \"model\": \"logisticspipes:pipe\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/blockstates/solid_block.json",
    "content": "{\n  \"forge_marker\": 1,\n  \"defaults\": {\n    \"custom\": {\n      \"flip-v\": true\n    },\n    \"model\": \"logisticspipes:solid_block\"\n  },\n  \"variants\": {\n    \"block_sub_type\": {\n      \"0\": {},\n      \"1\": {},\n      \"2\": {},\n      \"3\": {},\n      \"4\": {},\n      \"5\": {},\n      \"6\": {},\n      \"7\": {},\n      \"8\": {},\n      \"9\": {},\n      \"10\": {},\n      \"11\": {}\n    }\n  }\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/blockstates/sub_multiblock.json",
    "content": "{\n  \"variants\": {\n    \"normal\": [\n      {\n        \"model\": \"logisticspipes:sub_multiblock\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/dev_zero_guides/active_routing.md",
    "content": "<!---\ntitle: Active Routing\nicon: logisticspipes:pipe_supplier\n--->\n\n## Logistics Pipes Tutorial Part 2 - Active Routing\n\nIn this part of the tutorial we make it possible to request items from storage.\n\n### Provider Pipes\n\nPreviously, we discussed passive routing, in which a Logistics Pipes network\ndecides what to do with an item when one presents itself. In addition to this,\nLP networks support _active routing_, in which pipes can _provide_ items to the\nnetwork so other pipes can actively request them. When that happens the pipe\nproviding an item will pull it out of its inventory and send it toward the\npipe that requested it. By crafting some new types of logistics pipes we can\nuse this to pull items out of storage without having to know which chests\ncontain them.\n\nPipes more complicated than a Basic pipe need a little more infrastructure\nto craft. Let’s begin by crafting the [Logistics Program Compiler](item://logisticspipes:program_compiler), placing\nit in the world, and providing it with power by attaching a [Basic pipe](item://logisticspipes:pipe_basic) to\nits side and connecting that to the rest of the LP network.\n\n![The Compiler](image://02-01-compiler.png)\n\nThe Compiler provides us with the programs needed to craft each type of\npipe, but to get access to those we first need to unlock them. Click “Basic”,\nthen “Unlock” to start the process.\n\n![Unlocking Basic tech](image://02-02-basic.png)\n\nThis will take some time. While we wait for it to complete we can craft a\n[Logistics Programmer](item://logisticspipes:logistics_programmer). The Programmer\nis part of the crafting recipes for\npipes and more. The Compiler builds a program specific to one type of pipe\nand loads it onto the Programmer for use in crafting.\n\nLet’s craft some [Provider pipes](item://logisticspipes:pipe_provider), which\nwill provide the items we have in\nstorage to the LP network. When the Compiler is ready, open it, click\n“Provider Logistics Pipe”, then click “Compile”. This is only necessary\nonce per type of pipe; the [disk](item://logisticspipes:disk) we inserted\nearlier stores it for future\nuse. When that finishes, we need only put the Programmer in the slot on\nthe top right of the Compiler and click “Flash” to load the program for\nthat type of pipe onto the Programmer.\n\n![Flashing the Programmer](image://02-03-flashing.png)\n\nWith this program loaded we can finally use the Programmer to craft some\nProvider pipes. Thankfully, while it is part of pipe’s recipe, the Programmer\nis not consumed in the process. After crafting a few we can connect one to\neach chest that we want to provide to the network.\n\n![Provider pipes](image://02-04-provider-pipes.png)\n\n### Request Pipes\n\nTo request items from the Provider pipes we just placed we can use a [Request\npipe](item://logisticspipes:pipe_request), which will serve as our way of accessing\nthe contents of the LP network.\nCrafting this works the same way as the Provider pipe: go back to the Compiler,\ncompile the “Request Logistics Pipe” program, and load it onto the Programmer.\nThen we can use it to craft pipes as before.\n\nWe can connect the Request pipe to the network anywhere. If the pipe leads to\na dead end it will drop whatever you request on the floor. If it is connected\nto a chest it will instead add whatever you request to the chest.\n\n![Request pipe with an unrouted intersection](image://02-05-request-pipe-err.png)\n\nHere we placed a Request pipe overhead, where we can order items to be dropped\ninto our inventory. Notice that one of the unrouted pipes on the left turned\nred, indicating an issue. Unrouted pipes do not know where to send incoming\nitems, so if an item arrives at an unrouted pipe, and it has more than one\ndirection that it can send it then it will choose a direction at random. If\nit chooses the wrong direction the next routed pipe the item encounters will\nsend it back where it came from and the unrouted pipe will randomly choose a\ndirection again. This wastes time. We can ensure that items always go in the\ncorrect direction by replacing the pipe at the intersection with a pipe that\ncan do routing – a Basic pipe. As a general rule, never use an unrouted pipe\nat an intersection.\n\n![Request pipe with a routed intersection](image://02-06-request-pipe-fixed.png)\n\nWith that problem resolved we can now request items from the LP network. Upon\nright-clicking the Request pipe we are presented with a box that shows every\nitem provided by the network. Click an item in the list on the top, choose how\nmany to request on the bottom, and click “Request”. The Provider pipes with the\nitem we requested will pull that item out of its chest and send it to the Request\npipe we used to ask for it.\n\nIt is important to note that the two pipes connected to each chest play different\nroles: the Basic pipes are sinks for items and do not provide items to the network,\nwhile the Provider pipes provide items to the network and cannot sink items themselves.\n\n### Supplier Pipes\n\nThe generator that powers our stuff needs a continuous source of coal to keep running.\nWe can automate this with a [Supplier pipe](item://logisticspipes:pipe_request), an\nautomated version of the Request pipe that monitors an inventory and tries to keep\nitems in stock by requesting more when needed. Go back to the Compiler, compile and\nflash the “Supplier Logistics Pipe” program, and use it to craft a Supplier pipe.\n\nNow let’s attach the Supplier pipe to the generator and right-click it with\nthe Pipe Manager to tell it how many to keep in stock. If the item is on hand\nthis is easy: just click the item into the list. If the item is not on hand but\nJEI is installed then we can instead click an item in JEI’s list to get a\n“ghost” item that we can place into the list instead. In either case we can\nuse the mouse wheel to change the number to keep in stock.\n\n![Supplier pipe attached to the generator](image://02-07-supplier-pipe.png)\n\nThe Supplier pipe can use any of several strategies to keep items in stock:\n\n- Partial: request more items every time too few are in stock\n- Bulk50: wait until only half of the desired amount is in stock, then order enough\n  to refill\n- Bulk100: wait until none of the desired item remains, then order enough to refill\n- Full: same as Bulk100, but do not request anything unless the entire order can\n  be fulfilled\n- Infinite: ignore the requested number of items and continue requesting more until\n  the inventory is full\n\nI prefer to use Bulk50 for most things. It reduces the number of requests in\nflight at once, which is more power-efficient and can make machines spend less\ntime busy. Infinite mode is useful for pulling all of a certain item out of a network.\n\nIn [part 3](page://dev_zero_guides/crafting.md) we will add automatic crafting\ncapabilities to our LP network.  \n\n"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/dev_zero_guides/consolidating_pipes.md",
    "content": "<!---\ntitle: Consolidating Pipes\nicon: logisticspipes:pipe_chassis_mk1\n--->\n## Logistics Pipes Tutorial Part 4 - Consolidating Pipes\n\nIn this part of the tutorial we make use of modules to clean up our \nLP network, which is becoming a bit of a mess at this point.\n\n### Logistics Chassis\n\nA Logistics Chassis is a pipe that can do several things at once. \nWe can use this to simplify our LP network by consolidating the \nfunctions of the pipes we already have. Let’s open up the [Compiler](item://logisticspipes:program_compiler) \nand tell it to start unlocking Chassis.\n\nA [Chassis](item://logisticspipes:pipe_chassis_mk1) does nothing \nby itself. Instead, we add modules to it that give it different things to do. There are five type of \nChassis, but the only functional difference between them is how \nmany modules they can have at once. Once the Compiler has finished, \nlet’s build the program for a [Chassis Mk2](item://logisticspipes:pipe_chassis_mk2), which can fit two modules, \nand craft some of those.\n\nNext, we’ll remove one of the [Basic pipes](item://logisticspipes:pipe_basic) we have attached to a \nstorage chest, replace it with the Chassis, then use the [Pipe \nManager](item://logisticspipes:pipe_manager) on it to have a look inside.\n\n![Chassis GUI](image://04-01-chassis-gui.png)\n\n### ItemSink Modules\n\nThe two slots on the top are where modules go. To make this a \nfunctional replacement for the Basic Pipe it is taking the place \nof we can craft an ItemSink Module and add that to the Chassis \nwith the Pipe Manager.\n\n![ItemSink Module installed](image://04-02-itemsink.png)\n\nIf we click the [!] next to the ItemSink Module we can access its \nsettings and then set it up just like we did with the pipe that \nit replaced.\n\nNext, let’s replace the Basic pipe that has the default route \nwith another Mk2 Chassis, add an [ItemSink Module](item://logisticspipes:module_item_sink), and tell that \nmodule to act as a default route.\n\nA variant of the ItemSink Module is the [Polymorphic ItemSink Module](item://logisticspipes:module_item_sink_polymorphic), \nwhich cannot be programmed with a list of items.\n\n![Polymorphic ItemSink Module](image://04-03-polysink.png)\n\nInstead of waiting for us to tell it what items it should sink, \nthe Polymorphic version automatically sinks anything that is \nalready in the chest to which it is attached. Liberal use of these \nmodules makes chest storage fast and easy. Let’s replace \nall the remaining Basic pipes that we are using for storage with Mk2 \nChassis and Polymorphic ItemSink Modules.\n\n### Provider Modules\n\nNext, we can consolidate the pipes on our storage chests by \ncrafting some [Provider Modules](item://logisticspipes:module_provider) and adding them to the Chassis \non our storage chests. Let’s install one in a Chassis that has \na Polymorphic ItemSink Module and look at its settings.\n\n![Provider Settings](image://04-04-provider-settings.png)\n\nThis is where we can tell the Provider Module to include or \nexclude specific things if we don’t want it to provide everything \nit has to the network. The most relevant setting to us right now \nis the “Excess Inventory” setting on the bottom, which has several \noptions:\n\n - Normal, which provides all items it has\n - Leave first stack\n - Leave last stack\n - Leave first & last stack\n - Leave 1 item per stack\n - Leave 1 item per type\n\nSince this Chassis uses a Polymorphic sink it needs to reserve at \nleast one of each item for itself – if it were to give up all of \nan item then it would stop sinking them, and they would start going \nsomewhere else. For this reason a setting like “Leave 1 item per \ntype” is ideal. The “Normal” setting is good for machines’ output \nbuffers or chests with regular ItemSink modules. The “Leave 1 item \nper stack” setting can be useful when we want to assign specific \nslots in chests to specific types of items so one doesn’t crowd \nthe other out. To save some time we can configure a stack of \nfreshly-crafted modules by holding them and simply right-clicking \nthem in the air. Be careful – once they have been installed, modules \nwith settings no longer stack.\n\nNow that the Provider Modules are installed and set up we can remove \nthe [Provider Pipes](item://logisticspipes:pipe_provider) since they are no longer necessary. At the moment, \nremoving them is even more important because the Provider Pipes and \nmodules both provide the same items to the network, leading to \ndouble-counting. With those cleaned up, things are looking better already.\n\n![Cleaned up](image://04-05-cleaned-up.png)\n\nProvider Pipes have the same settings as Provider Modules, by the \nway. We just skipped over them earlier since Normal mode was fine.\n\nA close look at these new Chassis reveals a problem: a given Chassis \nattaches to only one thing at a time, indicated by orange dots on one \nside. The Chassis on the left has attached itself to the Power Junction \ninstead of the chest. The Chassis in the center has attached itself to \nthe hopper. This is preventing these Chassis from doing what we need \nthem to do, but if we pull out the Pipe Manager, hold shift, and \nright-click each of the problematic Chassis, we can easily fix the problem.\n\n![Reoriented Chassis](image://04-06-fixed-chassis.png)\n\n### Crafting Modules\n\nWe already have automatic crafting of iron ingots, so let’s add automatic \ncrafting of gold ingots, too. We could set up another furnace and set \nof pipes, but since this furnace sits idle most of the time we can have \nit smelt gold as well. This is possible with the power of Crafting Modules. \nLet’s craft a couple of those and a Mk2 Chassis to replace the Crafting \nPipe underneath the furnace.\n\n![Crafting Modules](image://04-07-crafting-modules.png)\n\nAfter we insert the two Crafting Modules and open up the Chassis we can \nset them up, one per recipe, just like we did for the original Crafting \nPipe. They both still need to use the Satellite Pipe since the furnace \naccepts ore only on the top, but since Satellite Pipes have no recipes \nof their own both Crafting Modules can share it.\n\nWhen two different crafting processes can use the same machines those \nprocesses can sometimes come into conflict. With this furnace, for example, \nif we request some iron and gold ingots in quick succession, the crafting \npipe will ask for iron and gold ores to be sent to the furnace. When the \niron ore arrives at the furnace it will begin smelting, but when the gold \nore arrives the top of the furnace will be occupied by the iron and the \nSatellite Pipe will fail to insert it. This will cause the gold ore to \nappear to _bounce_ off of the furnace, re-enter the LP network, and then \nget sent back to storage. The Crafting Pipe remains aware of this and \nwill make another request for gold ore when the top of the furnace is \nagain empty. Item bouncing is one reason it is generally crucial to \nhave Providers everywhere that can sink items. If a crafting ingredient \nbounces and ends up somewhere that does not provide it to the network \nthen the Crafting Module will never finish its crafting because it cannot \nfulfill its requests for ingredients unless more of them are already \nin storage.\n\n### Sneaky Upgrades\n\nThe furnace’s sidedness makes it deceptively complicated to automate, \nbut we can tweak our pipes’ behavior to handle this sidedness more \nseamlessly and clean things up a little more by using upgrades. Upgrades \nare items we can install in pipes that alter existing functionality \nrather than adding major new functionality like modules do. They also \ndiffer in that they can work in many different types of pipes, not just \nChassis. To manage upgrades we need to craft a Pipe Controller. It looks \nlike a red Pipe Manager.\n\nThe most useful upgrade to us right now is the [Sneaky Upgrade](item://logisticspipes:upgrade_sneaky). Adding \na Sneaky Upgrade to a pipe causes it to pretend as if it was on a different \nside of the thing to which it is attached when it tries to add something \nto its inventory. This is best illustrated by example: the reason we used \na Satellite Pipe on the furnace was so that pipe can insert ore into the \ntop of the furnace while the Crafting Modules extract finished ingots from \nthe bottom. If we use a Sneaky Upgrade on the Chassis with the Crafting \nModules then we can make it insert ore into the top of the furnace by itself.\n\nLet’s craft a Sneaky Upgrade and right-click the Chassis with the Crafting \nModules with the Pipe Controller, so we can install the upgrade.\n\n![Upgrade list](image://04-08-upgrade-list.png)\n\nClicking the [!] under the upgrade brings us to a 3D view of the furnace \nthat we can use to decide what side the pipe should insert into. Rotate \nthe furnace by holding the left mouse button and moving the mouse, then \nright-click on the top to tell it to insert into the top. The 3D view \nwill close without showing anything, which is not the greatest feedback, \nbut we can ensure that it worked when we test crafting shortly.\n\n![3D view](image://04-09-3d-view.png)\n\nWe can test this by removing the Satellite Pipe and updating the recipes \nin the Crafting Modules to no longer use it.\n\n![Updated recipe](image://04-10-updated-recipe.png)\n\nThen we request an iron ingot. Success! This works because the Sneaky \nUpgrade changes the side from which the Chassis inserts items, but does \nnot change the side from which it extracts items. For this reason the \nChassis must continue to be on the bottom.\n\nIn [part 5](page://dev_zero_guides/managing_items_with_pipes.md) we will employ \nmore types of modules to manage our items more smoothly.\n"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/dev_zero_guides/crafting.md",
    "content": "<!---\ntitle: Crafting\nicon: logisticspipes:crafting_table\n--->\n## Logistics Pipes Tutorial Part 3 - Automatic Crafting\n\nIn this part of the tutorial we explore how to use the items provided \nby our LP network to automatically craft other items.\n\n### Crafting Pipes\n\nRequesting something that is already in stock is useful, but requesting \nsomething that is not in stock, but we can craft, is even better and \nforms the basis of one of a LP network’s most powerful features. [Crafting \nPipes](item://logisticspipes:pipe_crafting) tell the network that it can take a set of ingredients and feed them \nto the machine to which it is attached to create something else. As a \nquick test of this, let’s set up automatic crafting of wood planks using \nwood logs. Craft a Crafting Pipe and a [Logistics Crafting Table](item://logisticspipes:crafting_table) to connect \nit to. As before, we will need to use the Compiler and Programmer to create \nthe Crafting Pipe.\n\nLet’s place the Logistics Crafting Table in the world and choose a recipe \nfor it. Unlike a regular crafting table, this one’s grid holds “ghosts” of \nthe items needed for its crafting recipe rather than the items themselves; \nthe grid’s job is simply to tell the crafting table what recipe to use. \nItems needed for crafting instead land in the inventory below the grid, \nwhich reserves some space for each slot in the grid. Let’s tell this one \nto craft wooden planks.\n\n![LCT with a plank recipe](image://03-01-lct-recipe.png)\n\nNow we need to connect a Crafting Pipe to the crafting table as well as \nthe rest of the network, then use the [Pipe Manager](item://logisticspipes:pipe_manager) to open its settings. \nOn this page we tell the pipe what the ingredients and products of its \ncrafting recipe are. While we can set this up by hand, since this is \nconnected to a Logistics Crafting Table we can simply press the “Import” \nbutton, and it will do that automatically.\n\nLet’s open the [Request Pipe](item://logisticspipes:pipe_request) again. Now that something on the network can \ncraft them, wood planks show up even though it shows that none are on hand. \nWhen we request one it will pull a block of wood out of storage, send it to \nthe crafting table, and then extract the four planks that it crafted. The \nplank that we asked for will then make its way to the Request Pipe. The \nremaining three look for a pipe that can sink them and then go there so we\ncan store them to use them later.\n\n![Request Pipe with craftable planks](image://03-02-craftable-planks.png)\n\nCrafting Pipes can request ingredients from other Crafting Pipes, creating \na “tree” of work to automatically do. By building a lot of Crafting Pipes \nand Logistics Crafting Tables we can make the LP network automatically \ncraft all kinds of complex things. For instance, we may wish to automate \ncrafting of more Crafting Pipes and other logistics pipes. In doing so \nwe also need to automate crafting of [Basic pipes](item://logisticspipes:pipe_basic), [Unrouted pipes](item://logisticspipes:pipe_transport_basic), and so \non, until the network has enough crafting recipes available to it that it \ncan craft them all from raw materials.\n\nThe recipe for the Crafting Pipe is a little problematic because it \ncontains a programmer that is not consumed during the crafting process. \nTo handle this we can simply place the Programmer in the inventory of \nthe crafting table with the Crafting Pipe’s recipe, then open the Crafting \nPipe and remove the Programmer from the list of ingredients since the \nnetwork does not have to craft more for the table to work. However, this \ndedicates the programmer we have used by hand up until now to automatically \nCrafting Pipe crafting, so we will need to craft a new one for our personal \nuse instead. We will similarly need to craft dedicated Programmers for each \nother logistics pipe recipe that calls for one as well.\n\n### Non-Crafting Recipes\n\nAdding a recipe to a Crafting Pipe tells the network that if it inserts a \nset of ingredients into an inventory then the Crafting Pipe will eventually \nbe able to extract the product of that recipe from the inventory to which \nit is attached. Crafting tables are the most obvious way of doing this, but \nCrafting Pipes can do other types of processing as well, such as smelting \nore. By attaching a [Supplier Pipe](item://logisticspipes:pipe_supplier) to the side of a furnace to feed it with \ncoal and a Crafting Pipe to the top to feed it iron ore we can tell the \nCrafting Pipe that the furnace will smelt one piece of iron ore into one \niron ingot.\n\n![This doesn't work](image://03-03-this-doesnt-work.png)\n\nOr can we?\n\nThis setup doesn’t work because furnaces are sided – each side corresponds \nto a specific slot in the furnace’s inventory. To make automation with \nhoppers work well, the top feeds into the top slot, the sides feed into \nthe fuel slot, and the bottom lets things pull from the output slot. The \nCrafting Pipe thus has to be on the bottom of the furnace, so it can pull \niron ingots out of the output slot as they finish smelting. But since ore \nstill has to go into the top of the furnace we need to craft a [Satellite \nPipe](item://logisticspipes:pipe_satellite), which allows a Crafting Pipe to send some of its ingredients elsewhere – \nin this case, the top of the furnace.\n\n![A Satellite Pipe](image://03-04-satellite-pipe.png)\n\nAfter placing the Crafting Pipe on the bottom of the furnace and the Satellite \nPipe on the top we need to tell them how to find each other. Use the Pipe \nManager on the Satellite Pipe and give it a name.\n\n![Naming the Satellite Pipe](image://03-05-naming-satellite-pipe.png)\n\nThen we can go back to the Crafting Pipe and give it the same recipe, but \nthis time using the Satellite Pipe. Clicking the “Select” button brings us \nto a list of available Satellite Pipes. After we choose one and go back to \nthe Crafting Pipe’s recipe page the ingredients in the rightmost three slots \nwill go to the Satellite Pipe we chose instead of the Crafting Pipe, so we \njust need to place a piece of iron ore in one of those slots instead of where \nwe previously had it on the left.\n\n![updated crafting recipe](image://03-06-satellite-recipe.png)\n\nNow if we go to smelt iron ore the ore will go to the Satellite Pipe on the \ntop of the furnace, while the Crafting Pipe waits for the ingot to appear on \nthe bottom.\n\nSome mods’ machines allow us to control which sides can access each part of \nits inventory, which can simplify things quite a bit. One crucial thing to \nremember when interactive with other mods is that machines must not automatically \neject their crafting outputs into the LP network – the Crafting Pipe has to be \nthe thing that pulls out crafting outputs for it to count the crafting operation \nas complete. This is in stark contrast with Applied Energistics, which expects \nus to take care of putting crafting outputs into the AE network and does not \ncare where we do so.\n\nIn [part 4](page://dev_zero_guides/consolidating_pipes.md) we will work on \ncombining pipes together to save ourselves future headaches.\n"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/dev_zero_guides/index.md",
    "content": "<!---\ntitle: dev/zero's Guides\nicon: minecraft:apple\nmenu:\n  index:\n    Available Guides:\n      - passive_routing.md\n      - active_routing.md\n      - crafting.md\n      - consolidating_pipes.md\n      - managing_items_with_pipes.md\n--->\n\nThis is a series of guides gracefully provided by [marth](https://www.devzero.com/about/), you can find the original [here](https://www.devzero.com/gaming/lp-tutorial/).\n\n[Guides](menu://index?type=list)"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/dev_zero_guides/managing_items_with_pipes.md",
    "content": "<!---\ntitle: Managing Items with Modules\nicon: logisticspipes:module_blank\n--->\n## Logistics Pipes Tutorial Part 5 - Managing Items with Modules\n\nIn this part of the tutorial we use more types of modules to \nimprove our item management.\n\n### Upgrades\n\nAfter returning home from a log mining trip one of the first \nthings we want to do is empty our inventory out. Hoppers work great \nfor this, but they only pull from their tops and they are not \nespecially fast at moving large numbers of items. Let’s build \nan [Extractor Module](item://logisticspipes:module_extractor), \nwhich constantly pulls items out of whatever it is attached to and \ninjects them into the LP network to be sunk somewhere. Then we just \nneed to craft a [Chassis](item://logisticspipes:pipe_chassis_mk1), \nattach that Chassis to a chest, and add that module to it. Now we can \ndump everything that we want to get rid of into this chest and it will \nmake its way into the network.\n\n![Dump chest](image://05-01-dump-chest.png)\n\nOut of the box, this module actually runs more slowly than \na hopper, extracting one item every five seconds. We can \nimprove this with [Item Extraction Upgrades](item://logisticspipes:upgrade_item_extraction), \nwhich increase the number of items it extracts each time, and [Action Speed \nUpgrades](item://logisticspipes:upgrade_action_speed), which \nincrease how frequently it runs. I tend to \nuse five or six Action Speed Upgrades and a few more Item \nExtraction Upgrades for this sort of item-dumping chest, but \nthey can go as high as 16 of each if necessary. Remember that \nextraction uses power.\n\nWe can’t use the [Pipe Controller](item://logisticspipes:pipe_controller) to add these upgrades \nsince we need to add them to the [Extractor Module](item://logisticspipes:module_extractor), not \nthe Chassis. Instead, we need to craft a [Module Upgrade](item://logisticspipes:upgrade_module_upgrade), \nan upgrade that, when installed into a Chassis, gives \nus slots to add upgrades to individual modules. After \nadding that to the Chassis we can grab the [Pipe Manager](item://logisticspipes:pipe_manager), \nopen the Chassis, and add modules in the new slots that \nappeared on the right.\n\n![Module upgrades](image://05-01-dump-chest.png)\n\n[Item Extraction Upgrades](item://logisticspipes:upgrade_item_extraction) also work on [Provider](item://logisticspipes:pipe_crafting) and [Crafting \nPipes](item://logisticspipes:pipe_crafting). This can be useful when something needs to request \nan enormous quantity of something, as the extraction speed \nof the pipe itself can otherwise be a bottleneck. The same \ngoes for [Provider](item://logisticspipes:module_provider) and [Crafting Modules](item://logisticspipes:module_crafter).\n\n### Item Sink Priority\n\nWhen an item enters the network and more than one pipe \ncan serve as a sink for it the network uses a list of \npriorities to decide where it is needed most:\n\n- [Passive Supplier Modules](item://logisticspipes:module_passive_supplier)\n- Item Sinks, including [Basic Pipes](item://logisticspipes:pipe_basic) and all ItemSink Modules\n- [Terminus Modules](item://logisticspipes:module_terminus)\n- Default routes\n\n[Passive Supplier Modules](item://logisticspipes:module_passive_supplier) are largely a relic from the \ntime before [Active Supplier Modules](item://logisticspipes:module_active_supplier) existed. They attempt \nto keep a certain number of an item in stock, but unlike \n[Supplier Pipes](item://logisticspipes:pipe_supplier) and [Active Supplier Modules](item://logisticspipes:module_active_supplier), they will not \nrequest them from the network. Instead, when an item a \nPassive Supplier Module needs enters the network it will \nsink that item before anything else has a chance to do so.\n\n[Terminus Modules](item://logisticspipes:module_terminus), with their lower-than-normal priority, \nusually serve as a means of getting rid of excess items \nonce storage for it fills up. A LP network will frequently \nhave a Terminus Module that sinks excess cobblestone and \ndirt into a trash can, matter condenser, or even pool of \nlava so that it doesn’t fill up the default route’s storage.\n\n![Trash can](image://05-01-dump-chest.png)\n\n### Re-sorting Items\n\nSupplier Pipes, Crafting Pipes, and similar things are \nnotably absent from the list above. Supplier Pipes do not \nsink items when they enter the network because they use \nactive routing, which can only request items from providers. \nBy contrast, Basic Pipes and other item sinks do not request \nitems because they use passive routing, which means they can \nonly respond to items entering the network that need a place \nto go.\n\nThis dichotomy can become a problem for the default route. \nEven if it has a provider attached to it, the default route \nmay not empty itself out over time; there is no priority \nsystem for providers. If the default route runs out of space \nthen the network will begin spilling items onto the floor. \nThis is where the [QuickSort Module](item://logisticspipes:module_quick_sort), along with a little \nattention on our part, can come in handy.\n\nA QuickSort module inspects the items it has and looks for \nsomewhere else on the network that can sink it that is not a \ndefault route. If it finds one it injects it back into the \nnetwork so the network can re-sink it. This is a valuable way \nto keep a default route chest clean – when storage becomes \navailable for something the QuickSort module sees to it that \nit goes elsewhere. Let’s put this into practice by upgrading \nour default route’s Mk2 Chassis to Mk3 and then add a \nQuickSort Module to it.\n\n![QuickSort Module](image://05-01-dump-chest.png)\n\nWith this setup in place we can check the chest periodically \nto see if anything is building up. If it is then we can take \none out of the chest, place it in a chest with a [Polymorphic \nsink](item://logisticspipes:module_item_sink_polymorphic), and the [QuickSort Module](item://logisticspipes:module_quick_sort) will quickly move the rest of \nthat type of item over. Or we can add it to a Terminus Module \nsomewhere and have the QuickSort Module send it there for \ndisposal. Or we can do something more involved. This combination \nof modules makes for an efficient and easy-to-manage system \nfor item storage.\n\n[QuickSort Module](item://logisticspipes:module_quick_sort) are also great alternatives to Extractor Modules \nfor a factory’s post-outing, item-dumping chest. They have the \nadded benefit of not extracting items that have nowhere other \nthan the default route to go, which makes it immediately obvious \nwhen something is in need of storage. In fact, in most of my \nfactories the default route and the item-dump chest are one and \nthe same.\n\nA word of warning: do not place a QuickSort Module in the same \nplace as an item sink unless that item sink is a default route. \nIf you choose to ignore this warning, do not do so more than \nonce in a given network or the QuickSort Modules will endlessly \ntrade items with one another.\n"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/dev_zero_guides/passive_routing.md",
    "content": "<!---\ntitle: Passive Routing\nicon: logisticspipes:module_item_sink\n--->\n\n## Logistics Pipes Tutorial Part 1 - Sorting Items\n\nIn this part of the tutorial we craft our first logistics pipes \nand build a basic item-sorting system.\n\n### Getting Started\n\nThe Logistics Pipes mod has two major types of pipes. Routed pipes \nconnect to each other to form a network that can intelligently \npass items between connected pipes and the rest of the world. \n[Unrouted pipes](item://logisticspipes:pipe_transport_basic) lack \nthe intelligence of routed pipes; they connect only to other pipes \nto provide transportation between them.\n\nLet’s build a simple item-sorting system using logistics pipes. \nStart with some chests.\n\n![Some chests](image://01-01-some-chests.png)\n\nLogistics pipes require power to operate. To supply this power \nwe construct a [Power Junction](item://logisticspipes:power_junction) \nand then connect it to some sort of generator, such as this \ncoal-powered generator.\n\n![Power Junction connected to a generator](image://01-02-power.png)\n\nTo actually sort items, let’s craft some [Basic Logistics Pipes](item://pipe_basic) \nand attach one to each chest. A Basic pipe also needs to be \nconnected to a side of the Power Junction (not the top or bottom), \nbut it is fine for one pipe can do double-duty and connect to both. \nIf there is space in between the basic pipes we can connect them \nto each other using unrouted pipes.\n\n![Pipes attached to the chests](image://01-03-pipes.png)\n\n### Passive Routing\n\nWhen a routed pipe such as one of these Basic pipes encounters \nan item it will attempt to find a _sink_ for that item – a pipe \nthat can accept it and add it to the chest or other inventory \nto which it is connected. It will then _sink_ the item by sending \nit in that direction. Each routed pipe along the way will send \nit in the right direction until it finally reaches the pipe that \noffered to sink the item. That pipe then adds it to its chest.\n\nEach Basic pipe contains a list that we can use to control \nwhich types of items that it can sink. To edit this list, \nlet’s craft a [Pipe Manager](item://logisticspipes:pipe_manager), \nright-click a pipe, and add some items to its list.\n\nWrenches from many other mods can substitute for the Pipe Manager \nas well.\n\n![The Basic pipe configuration dialog](image://01-04-config.png)\n\nWe can continue this process for the other pipes to assign \ndifferent types of items to different chests. We also need to \nset at least one pipe as a _default route_, a pipe that can sink \nitems that have nowhere else to go. A LP network with no default \nroute will drop items on the floor if it cannot find a place to \nsink them.\n\n![Setting a default route](image://01-05-default-route.png)\n\nAll that is left is to connect a hopper for adding items to the \nnetwork. The sorting system is now complete! Let’s drop some items \ninto the hopper and watch it work.\n\n![Sorting items](image://01-06-working.png)\n\nIn [part 2](page://dev_zero_guides/active_routing.md) we will expand \non this system to make its inventory more accessible.\n"
  },
  {
    "path": "resources/assets/logisticspipes/book/en_us/main_menu.md",
    "content": "<!---\ntitle: Logistics Pipes Quick Start\n--->\n\n[marth's guide](page://dev_zero_guides/index.md)\n\n*\"It's been a long time. How have you been?\"*\n\nFirst off, thanks for playing Logistics Pipes.<br>\nA lot of changes have been made since the last release of LP in Minecraft 1.7.10. We'll try to explain some of these in this book. Read the next pages, if you'd like to know them.\n\nI hope you already have your Logistics Power Junction set up and crafted your first Basic Logistics Pipes :)<br>\nIf not, go for it.<br>\nYou might have recognized that all other types of pipes and modules now need something called a Logistics Programmer.\n\nThe Logistics Programmer is an item that wont be used up in any crafting recipes, but you need to set it up first. That is to be done with a Logistics Program Compiler. I know, I know, it sounds complicated. But it really isn't. Craft both of these and a Logistics Disk.\n\nNow you place the Logistics Program Compiler (further just compiler) next to a Logistics Basic Pipe that is - by other pipes or directly - connected to the Power Junction, because the compiler needs power and will take that from the LP network.\n\nThe compiler can be used to research new tiers, pipes, modules and upgrades. Insert the Logistics Disk on the top left. Then you are able to unlock different tiers. Let's start with 'Basic'. Researching takes some time, so relax and get some coffee.\n\nAfter unlocking a tier, you should be able to see the different pipe, module or upgrade names on the right. You can now compile each of these, which takes a shorter amount of time. Compiling makes those programs flashable onto the Logistics Programmer.\n\nTo flash a program, simply insert the Logistics Programmer into the top right slot and flash one of those programs onto the programmer. Afterwards you can use this programmer in the crafting of that item. Module programs can be found within the chassis tiers.\n\nYou might be asking where the Mk2 and Mk3 pipes and modules are. They are gone, but you can recreate their effects by adding upgrades to your pipes and modules. Those upgrades are named 'Action Speed', 'Item Extraction' or 'ItemStack Extraction'.\n\nTo upgrade your modules, you need an upgrade for your chassis pipe called the 'Module Upgrade'. After applying it to your chassis pipe, new slots appear to the right of every inserted module. That's where the upgrades for the module go.\n\nI hope you got a good overview on how to start with this brand-new LP version. While you're at it you can also check out our new Highspeed Tubes. \\\n***But most importantly: Have fun!***\n\n---\n\n[Bug Reports](https://github.com/RS485/LogisticsPipes/issues)\n\n---\n\n[Official Builds](https://ci.rs485.network)\n\n---\n\n[Help us improve this book](https://github.com/RS485/LogisticsPipes/wiki/How-does-the-guide-book-work-and-how-to-create-content)\n\n---\n"
  },
  {
    "path": "resources/assets/logisticspipes/fonts/OFL.TXT",
    "content": "Copyright (c) 2019 Dimitar Toshkov Zhekov,\r\nwith Reserved Font Name \"Terminus Font\".\r\n\r\nThis Font Software is licensed under the SIL Open Font License, Version 1.1.\r\nThis license is copied below, and is also available with a FAQ at:\r\nhttp://scripts.sil.org/OFL\r\n\r\n\r\n-----------------------------------------------------------\r\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\r\n-----------------------------------------------------------\r\n\r\nPREAMBLE\r\nThe goals of the Open Font License (OFL) are to stimulate worldwide\r\ndevelopment of collaborative font projects, to support the font creation\r\nefforts of academic and linguistic communities, and to provide a free and\r\nopen framework in which fonts may be shared and improved in partnership\r\nwith others.\r\n\r\nThe OFL allows the licensed fonts to be used, studied, modified and\r\nredistributed freely as long as they are not sold by themselves. The\r\nfonts, including any derivative works, can be bundled, embedded, \r\nredistributed and/or sold with any software provided that any reserved\r\nnames are not used by derivative works. The fonts and derivatives,\r\nhowever, cannot be released under any other type of license. The\r\nrequirement for fonts to remain under this license does not apply\r\nto any document created using the fonts or their derivatives.\r\n\r\nDEFINITIONS\r\n\"Font Software\" refers to the set of files released by the Copyright\r\nHolder(s) under this license and clearly marked as such. This may\r\ninclude source files, build scripts and documentation.\r\n\r\n\"Reserved Font Name\" refers to any names specified as such after the\r\ncopyright statement(s).\r\n\r\n\"Original Version\" refers to the collection of Font Software components as\r\ndistributed by the Copyright Holder(s).\r\n\r\n\"Modified Version\" refers to any derivative made by adding to, deleting,\r\nor substituting -- in part or in whole -- any of the components of the\r\nOriginal Version, by changing formats or by porting the Font Software to a\r\nnew environment.\r\n\r\n\"Author\" refers to any designer, engineer, programmer, technical\r\nwriter or other person who contributed to the Font Software.\r\n\r\nPERMISSION & CONDITIONS\r\nPermission is hereby granted, free of charge, to any person obtaining\r\na copy of the Font Software, to use, study, copy, merge, embed, modify,\r\nredistribute, and sell modified and unmodified copies of the Font\r\nSoftware, subject to the following conditions:\r\n\r\n1) Neither the Font Software nor any of its individual components,\r\nin Original or Modified Versions, may be sold by itself.\r\n\r\n2) Original or Modified Versions of the Font Software may be bundled,\r\nredistributed and/or sold with any software, provided that each copy\r\ncontains the above copyright notice and this license. These can be\r\nincluded either as stand-alone text files, human-readable headers or\r\nin the appropriate machine-readable metadata fields within text or\r\nbinary files as long as those fields can be easily viewed by the user.\r\n\r\n3) No Modified Version of the Font Software may use the Reserved Font\r\nName(s) unless explicit written permission is granted by the corresponding\r\nCopyright Holder. This restriction only applies to the primary font name as\r\npresented to the users.\r\n\r\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\r\nSoftware shall not be used to promote, endorse or advertise any\r\nModified Version, except to acknowledge the contribution(s) of the\r\nCopyright Holder(s) and the Author(s) or with their explicit written\r\npermission.\r\n\r\n5) The Font Software, modified or unmodified, in part or in whole,\r\nmust be distributed entirely under this license, and must not be\r\ndistributed under any other license. The requirement for fonts to\r\nremain under this license does not apply to any document created\r\nusing the Font Software.\r\n\r\nTERMINATION\r\nThis license becomes null and void if any of the above conditions are\r\nnot met.\r\n\r\nDISCLAIMER\r\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\r\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\r\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\r\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\r\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\r\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\r\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\r\nOTHER DEALINGS IN THE FONT SOFTWARE.\r\n"
  },
  {
    "path": "resources/assets/logisticspipes/fonts/minecraft-bold.bdf",
    "content": "STARTFONT 2.1\nCOMMENT Exported by Fony v1.4.7\nFONT Minecraft Bold\nSIZE 12 96 96\nFONTBOUNDINGBOX 10 11 0 -2\nSTARTPROPERTIES 6\nCOPYRIGHT \"Created by Bernasss12 for Logistics Pipes\"\nRESOLUTION_X 96\nRESOLUTION_Y 96\nFONT_ASCENT 10\nFONT_DESCENT 2\nDEFAULT_CHAR 0\nENDPROPERTIES\nCHARS 256\nSTARTCHAR 000\nENCODING 0\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 001\nENCODING 1\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 002\nENCODING 2\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 003\nENCODING 3\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 004\nENCODING 4\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 005\nENCODING 5\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 006\nENCODING 6\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 007\nENCODING 7\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 008\nENCODING 8\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 009\nENCODING 9\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 010\nENCODING 10\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 011\nENCODING 11\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 012\nENCODING 12\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 013\nENCODING 13\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 014\nENCODING 14\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 015\nENCODING 15\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 016\nENCODING 16\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 017\nENCODING 17\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 018\nENCODING 18\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 019\nENCODING 19\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 020\nENCODING 20\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 021\nENCODING 21\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 022\nENCODING 22\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 023\nENCODING 23\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 024\nENCODING 24\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 025\nENCODING 25\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 026\nENCODING 26\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 027\nENCODING 27\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 028\nENCODING 28\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 029\nENCODING 29\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 030\nENCODING 30\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 031\nENCODING 31\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 032\nENCODING 32\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 033\nENCODING 33\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\nC0\nC0\nC0\nC0\n00\nC0\nENDCHAR\nSTARTCHAR 034\nENCODING 34\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 3 0 4\nBITMAP\n78\n78\nF0\nENDCHAR\nSTARTCHAR 035\nENCODING 35\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\n78\nFC\n78\nFC\n78\n78\nENDCHAR\nSTARTCHAR 036\nENCODING 36\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n30\n7C\nC0\n78\n0C\nF8\n30\nENDCHAR\nSTARTCHAR 037\nENCODING 37\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nD8\n18\n30\n60\n6C\nCC\nENDCHAR\nSTARTCHAR 038\nENCODING 38\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n30\n78\n30\n7C\nF8\nD8\n7C\nENDCHAR\nSTARTCHAR 039\nENCODING 39\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 3 0 4\nBITMAP\n60\n60\nC0\nENDCHAR\nSTARTCHAR 040\nENCODING 40\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n38\n60\nC0\nC0\nC0\n60\n38\nENDCHAR\nSTARTCHAR 041\nENCODING 41\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nE0\n30\n18\n18\n18\n30\nE0\nENDCHAR\nSTARTCHAR 042\nENCODING 42\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 3 0 4\nBITMAP\nD8\n70\nD8\nENDCHAR\nSTARTCHAR 043\nENCODING 43\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 1\nBITMAP\n30\n30\nFC\n30\n30\nENDCHAR\nSTARTCHAR 044\nENCODING 44\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 3 0 -1\nBITMAP\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 045\nENCODING 45\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 1 0 3\nBITMAP\nFC\nENDCHAR\nSTARTCHAR 046\nENCODING 46\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 2 0 0\nBITMAP\nC0\nC0\nENDCHAR\nSTARTCHAR 047\nENCODING 47\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n0C\n18\n18\n30\n60\n60\nC0\nENDCHAR\nSTARTCHAR 048\nENCODING 48\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nDC\nFC\nEC\nCC\n78\nENDCHAR\nSTARTCHAR 049\nENCODING 49\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n30\n70\n30\n30\n30\n30\nFC\nENDCHAR\nSTARTCHAR 050\nENCODING 50\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\n0C\n38\n60\nC0\nFC\nENDCHAR\nSTARTCHAR 051\nENCODING 51\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\n0C\n38\n0C\nCC\n78\nENDCHAR\nSTARTCHAR 052\nENCODING 52\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n1C\n3C\n6C\nCC\nFC\n0C\n0C\nENDCHAR\nSTARTCHAR 053\nENCODING 53\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\nC0\nF8\n0C\n0C\nCC\n78\nENDCHAR\nSTARTCHAR 054\nENCODING 54\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n38\n60\nC0\nF8\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 055\nENCODING 55\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\nCC\n0C\n18\n30\n30\n30\nENDCHAR\nSTARTCHAR 056\nENCODING 56\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nCC\n78\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 057\nENCODING 57\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nCC\n7C\n0C\n18\n70\nENDCHAR\nSTARTCHAR 058\nENCODING 58\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 6 0 0\nBITMAP\nC0\nC0\n00\n00\nC0\nC0\nENDCHAR\nSTARTCHAR 059\nENCODING 59\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 -1\nBITMAP\nC0\nC0\n00\n00\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 060\nENCODING 60\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n18\n30\n60\nC0\n60\n30\n18\nENDCHAR\nSTARTCHAR 061\nENCODING 61\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 4 0 1\nBITMAP\nFC\n00\n00\nFC\nENDCHAR\nSTARTCHAR 062\nENCODING 62\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nC0\n60\n30\n18\n30\n60\nC0\nENDCHAR\nSTARTCHAR 063\nENCODING 63\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\n0C\n18\n30\n00\n30\nENDCHAR\nSTARTCHAR 064\nENCODING 64\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 7 0 0\nBITMAP\n7C\nC6\nFE\nFE\nFE\nC0\n7E\nENDCHAR\nSTARTCHAR 065\nENCODING 65\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 066\nENCODING 66\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nF8\nCC\nF8\nCC\nCC\nCC\nF8\nENDCHAR\nSTARTCHAR 067\nENCODING 67\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nC0\nC0\nC0\nCC\n78\nENDCHAR\nSTARTCHAR 068\nENCODING 68\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nF8\nCC\nCC\nCC\nCC\nCC\nF8\nENDCHAR\nSTARTCHAR 069\nENCODING 69\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\nC0\nF0\nC0\nC0\nC0\nFC\nENDCHAR\nSTARTCHAR 070\nENCODING 70\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\nC0\nF0\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 071\nENCODING 71\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n7C\nC0\nFC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 072\nENCODING 72\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 073\nENCODING 73\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n60\n60\n60\n60\n60\nF0\nENDCHAR\nSTARTCHAR 074\nENCODING 74\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n0C\n0C\n0C\n0C\n0C\nCC\n78\nENDCHAR\nSTARTCHAR 075\nENCODING 75\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nD8\nF0\nD8\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 076\nENCODING 76\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nC0\nC0\nC0\nC0\nC0\nC0\nFC\nENDCHAR\nSTARTCHAR 077\nENCODING 77\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nFC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 078\nENCODING 78\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nEC\nFC\nDC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 079\nENCODING 79\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 080\nENCODING 80\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nF8\nCC\nF8\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 081\nENCODING 81\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nCC\nCC\nCC\nD8\n7C\nENDCHAR\nSTARTCHAR 082\nENCODING 82\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nF8\nCC\nF8\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 083\nENCODING 83\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n7C\nC0\n78\n0C\n0C\nCC\n78\nENDCHAR\nSTARTCHAR 084\nENCODING 84\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR 085\nENCODING 85\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 086\nENCODING 86\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nCC\nCC\nCC\n78\n78\n30\nENDCHAR\nSTARTCHAR 087\nENCODING 87\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\nCC\nCC\nCC\nFC\nFC\nCC\nENDCHAR\nSTARTCHAR 088\nENCODING 88\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\n78\n30\n78\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 089\nENCODING 89\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\n78\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR 090\nENCODING 90\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\n0C\n18\n30\n60\nC0\nFC\nENDCHAR\nSTARTCHAR 091\nENCODING 91\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\nC0\nC0\nC0\nC0\nC0\nF0\nENDCHAR\nSTARTCHAR 092\nENCODING 92\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nC0\n60\n60\n30\n18\n18\n0C\nENDCHAR\nSTARTCHAR 093\nENCODING 93\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n30\n30\n30\n30\n30\nF0\nENDCHAR\nSTARTCHAR 094\nENCODING 94\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 3 0 4\nBITMAP\n30\n78\nCC\nENDCHAR\nSTARTCHAR 095\nENCODING 95\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 1 0 -1\nBITMAP\nFC\nENDCHAR\nSTARTCHAR 096\nENCODING 96\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 3 0 4\nBITMAP\nC0\nC0\n60\nENDCHAR\nSTARTCHAR 097\nENCODING 97\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 098\nENCODING 98\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nC0\nC0\nF8\nEC\nCC\nCC\nF8\nENDCHAR\nSTARTCHAR 099\nENCODING 99\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\n78\nCC\nC0\nCC\n78\nENDCHAR\nSTARTCHAR 100\nENCODING 100\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n0C\n0C\n7C\nDC\nCC\nCC\n7C\nENDCHAR\nSTARTCHAR 101\nENCODING 101\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\n78\nCC\nFC\nC0\n7C\nENDCHAR\nSTARTCHAR 102\nENCODING 102\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n38\n60\nF8\n60\n60\n60\n60\nENDCHAR\nSTARTCHAR 103\nENCODING 103\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 6 0 -1\nBITMAP\n7C\nCC\nCC\n7C\n0C\nF8\nENDCHAR\nSTARTCHAR 104\nENCODING 104\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nC0\nC0\nF8\nEC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 105\nENCODING 105\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\n00\nC0\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 106\nENCODING 106\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 -2\nBITMAP\n0C\n00\n0C\n0C\n0C\n0C\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 107\nENCODING 107\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nC0\nC0\nD8\nF0\nE0\nF0\nD8\nENDCHAR\nSTARTCHAR 108\nENCODING 108\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nC0\nC0\nC0\nC0\nC0\nC0\n60\nENDCHAR\nSTARTCHAR 109\nENCODING 109\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nF8\nFC\nFC\nCC\nCC\nENDCHAR\nSTARTCHAR 110\nENCODING 110\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nF8\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 111\nENCODING 111\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\n78\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 112\nENCODING 112\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 -2\nBITMAP\nF8\nEC\nCC\nCC\nF8\nC0\nC0\nENDCHAR\nSTARTCHAR 113\nENCODING 113\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 -2\nBITMAP\n7C\nDC\nCC\nCC\n7C\n0C\n0C\nENDCHAR\nSTARTCHAR 114\nENCODING 114\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nF8\nEC\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 115\nENCODING 115\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\n7C\nC0\n78\n0C\nF8\nENDCHAR\nSTARTCHAR 116\nENCODING 116\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n60\nF0\n60\n60\n60\n60\n30\nENDCHAR\nSTARTCHAR 117\nENCODING 117\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nCC\nCC\nCC\nCC\n7C\nENDCHAR\nSTARTCHAR 118\nENCODING 118\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nCC\nCC\nCC\n78\n30\nENDCHAR\nSTARTCHAR 119\nENCODING 119\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nCC\nCC\nFC\nFC\n7C\nENDCHAR\nSTARTCHAR 120\nENCODING 120\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nCC\n78\n30\n78\nCC\nENDCHAR\nSTARTCHAR 121\nENCODING 121\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 -2\nBITMAP\nCC\nCC\nCC\n7C\n0C\n0C\nF8\nENDCHAR\nSTARTCHAR 122\nENCODING 122\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\nFC\n18\n30\n60\nFC\nENDCHAR\nSTARTCHAR 123\nENCODING 123\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n38\n60\n60\nC0\n60\n60\n38\nENDCHAR\nSTARTCHAR 124\nENCODING 124\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 125\nENCODING 125\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nE0\n30\n30\n18\n30\n30\nE0\nENDCHAR\nSTARTCHAR 126\nENCODING 126\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 2 0 5\nBITMAP\n76\nDC\nENDCHAR\nSTARTCHAR 127\nENCODING 127\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nF0\n90\n90\n90\n90\n90\nF0\nENDCHAR\nSTARTCHAR 128\nENCODING 128\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 129\nENCODING 129\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 130\nENCODING 130\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 131\nENCODING 131\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 132\nENCODING 132\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 133\nENCODING 133\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 134\nENCODING 134\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 135\nENCODING 135\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 136\nENCODING 136\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 137\nENCODING 137\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 138\nENCODING 138\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 139\nENCODING 139\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 140\nENCODING 140\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 141\nENCODING 141\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 142\nENCODING 142\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 143\nENCODING 143\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 144\nENCODING 144\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 145\nENCODING 145\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 146\nENCODING 146\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 147\nENCODING 147\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 148\nENCODING 148\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 149\nENCODING 149\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 150\nENCODING 150\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 151\nENCODING 151\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 152\nENCODING 152\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 153\nENCODING 153\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 154\nENCODING 154\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 155\nENCODING 155\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 156\nENCODING 156\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 157\nENCODING 157\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 158\nENCODING 158\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 159\nENCODING 159\nSWIDTH 72 0\nDWIDTH 1 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 160\nENCODING 160\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 161\nENCODING 161\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\n00\nC0\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 162\nENCODING 162\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n30\n78\nC0\n78\n30\nENDCHAR\nSTARTCHAR 163\nENCODING 163\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n3C\n60\n60\nF8\n60\n60\nFC\nENDCHAR\nSTARTCHAR 164\nENCODING 164\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 1\nBITMAP\nCC\n78\n78\n78\nCC\nENDCHAR\nSTARTCHAR 165\nENCODING 165\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\n78\n30\n78\n30\n78\n30\nENDCHAR\nSTARTCHAR 166\nENCODING 166\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\nC0\nC0\n00\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 167\nENCODING 167\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n7C\nC0\n78\n78\n78\n0C\nF8\nENDCHAR\nSTARTCHAR 168\nENCODING 168\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 1 0 6\nBITMAP\nF0\nENDCHAR\nSTARTCHAR 169\nENCODING 169\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 5 0 0\nBITMAP\n7C\nDE\nF6\nDE\n7C\nENDCHAR\nSTARTCHAR 170\nENCODING 170\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 6 0 1\nBITMAP\n78\n0C\nFC\n7C\n00\nFC\nENDCHAR\nSTARTCHAR 171\nENCODING 171\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 5 0 0\nBITMAP\n36\n6C\nD8\n6C\n36\nENDCHAR\nSTARTCHAR 172\nENCODING 172\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 2 0 3\nBITMAP\nF8\n18\nENDCHAR\nSTARTCHAR 173\nENCODING 173\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 1 0 2\nBITMAP\nF0\nENDCHAR\nSTARTCHAR 174\nENCODING 174\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 5 0 1\nBITMAP\n7C\nFE\nF6\nFE\n7C\nENDCHAR\nSTARTCHAR 175\nENCODING 175\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 1 0 8\nBITMAP\nFC\nENDCHAR\nSTARTCHAR 176\nENCODING 176\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 3 0 5\nBITMAP\n60\nF0\n60\nENDCHAR\nSTARTCHAR 177\nENCODING 177\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n30\n30\nFC\n30\n30\n00\nFC\nENDCHAR\nSTARTCHAR 178\nENCODING 178\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 4 0 3\nBITMAP\nE0\n30\n60\nF0\nENDCHAR\nSTARTCHAR 179\nENCODING 179\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 4 0 3\nBITMAP\nE0\n70\n30\nE0\nENDCHAR\nSTARTCHAR 180\nENCODING 180\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 2 0 6\nBITMAP\n60\nC0\nENDCHAR\nSTARTCHAR 181\nENCODING 181\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 -2\nBITMAP\nCC\nCC\nCC\nDC\nFC\nC0\nC0\nENDCHAR\nSTARTCHAR 182\nENCODING 182\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n7C\nFC\nFC\n7C\n3C\n3C\n3C\nENDCHAR\nSTARTCHAR 183\nENCODING 183\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 1 0 3\nBITMAP\nC0\nENDCHAR\nSTARTCHAR 184\nENCODING 184\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 2 0 -2\nBITMAP\n60\nE0\nENDCHAR\nSTARTCHAR 185\nENCODING 185\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 4 0 4\nBITMAP\n60\nE0\n60\nF0\nENDCHAR\nSTARTCHAR 186\nENCODING 186\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 6 0 1\nBITMAP\n78\nCC\nCC\n78\n00\nFC\nENDCHAR\nSTARTCHAR 187\nENCODING 187\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 5 0 0\nBITMAP\nD8\n6C\n36\n6C\nD8\nENDCHAR\nSTARTCHAR 188\nENCODING 188\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n8C\n98\n18\n30\n6C\n6C\nC4\nENDCHAR\nSTARTCHAR 189\nENCODING 189\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n8C\n98\n18\n30\n64\n68\nCC\nENDCHAR\nSTARTCHAR 190\nENCODING 190\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nCC\n58\nD8\n30\n6C\n6C\nC4\nENDCHAR\nSTARTCHAR 191\nENCODING 191\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n30\n00\n30\n60\nC0\nCC\n78\nENDCHAR\nSTARTCHAR 192\nENCODING 192\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nE0\n00\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 193\nENCODING 193\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n1C\n00\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 194\nENCODING 194\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n78\nCC\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 195\nENCODING 195\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nFC\n00\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 196\nENCODING 196\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n48\n00\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 197\nENCODING 197\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n78\nCC\n78\nCC\nFC\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 198\nENCODING 198\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 8 7 0 0\nBITMAP\n7F\nD8\nFE\nD8\nD8\nD8\nDF\nENDCHAR\nSTARTCHAR 199\nENCODING 199\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 -2\nBITMAP\n78\nCC\nC0\nC0\nC0\nCC\n78\n18\n38\nENDCHAR\nSTARTCHAR 200\nENCODING 200\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nE0\n00\nFC\nC0\nF0\nC0\nC0\nC0\nFC\nENDCHAR\nSTARTCHAR 201\nENCODING 201\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n1C\n00\nFC\nC0\nF0\nC0\nC0\nC0\nFC\nENDCHAR\nSTARTCHAR 202\nENCODING 202\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n78\nCC\nFC\nC0\nF0\nC0\nC0\nC0\nFC\nENDCHAR\nSTARTCHAR 203\nENCODING 203\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n48\n00\nFC\nC0\nF0\nC0\nC0\nC0\nFC\nENDCHAR\nSTARTCHAR 204\nENCODING 204\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 9 0 0\nBITMAP\nE0\n00\nF0\n60\n60\n60\n60\n60\nF0\nENDCHAR\nSTARTCHAR 205\nENCODING 205\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 9 0 0\nBITMAP\n70\n00\nF0\n60\n60\n60\n60\n60\nF0\nENDCHAR\nSTARTCHAR 206\nENCODING 206\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 9 0 0\nBITMAP\n60\n90\nF0\n60\n60\n60\n60\n60\nF0\nENDCHAR\nSTARTCHAR 207\nENCODING 207\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 9 0 0\nBITMAP\n90\n00\nF0\n60\n60\n60\n60\n60\nF0\nENDCHAR\nSTARTCHAR 208\nENCODING 208\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 7 7 0 0\nBITMAP\n7C\n66\nF6\n66\n66\n66\n7C\nENDCHAR\nSTARTCHAR 209\nENCODING 209\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nFC\n00\nCC\nEC\nFC\nDC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 210\nENCODING 210\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nE0\n00\n78\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 211\nENCODING 211\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n1C\n00\n78\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 212\nENCODING 212\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n78\nCC\n78\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 213\nENCODING 213\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nFC\n00\n78\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 214\nENCODING 214\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n48\n00\n78\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 215\nENCODING 215\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 4 0 0\nBITMAP\nD8\n70\n70\nD8\nENDCHAR\nSTARTCHAR 216\nENCODING 216\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\nDC\nFC\nEC\nCC\n78\nENDCHAR\nSTARTCHAR 217\nENCODING 217\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\nE0\n00\nCC\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 218\nENCODING 218\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n1C\n00\nCC\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 219\nENCODING 219\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 10 0 0\nBITMAP\n78\nCC\n00\nCC\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 220\nENCODING 220\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n48\n00\nCC\nCC\nCC\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 221\nENCODING 221\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 9 0 0\nBITMAP\n1C\n00\nCC\n78\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR 222\nENCODING 222\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nC0\nF8\nCC\nF8\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 223\nENCODING 223\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n70\nD8\nF8\nCC\nCC\nCC\nF8\nENDCHAR\nSTARTCHAR 224\nENCODING 224\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nE0\n00\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 225\nENCODING 225\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n1C\n00\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 226\nENCODING 226\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 227\nENCODING 227\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\n00\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 228\nENCODING 228\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n48\n00\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 229\nENCODING 229\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n30\n00\n78\n0C\n7C\nCC\n7C\nENDCHAR\nSTARTCHAR 230\nENCODING 230\nSWIDTH 720 0\nDWIDTH 10 0\nBBX 9 5 0 0\nBITMAP\n7F00\n1980\n7F80\nD800\n7F80\nENDCHAR\nSTARTCHAR 231\nENCODING 231\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 -2\nBITMAP\n78\nCC\nC0\nCC\n78\n18\n38\nENDCHAR\nSTARTCHAR 232\nENCODING 232\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nE0\n00\n78\nCC\nFC\nC0\n7C\nENDCHAR\nSTARTCHAR 233\nENCODING 233\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n1C\n00\n78\nCC\nFC\nC0\n7C\nENDCHAR\nSTARTCHAR 234\nENCODING 234\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 8 0 0\nBITMAP\n78\nCC\n00\n78\nCC\nFC\nC0\n7C\nENDCHAR\nSTARTCHAR 235\nENCODING 235\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\n00\n78\nCC\nFC\nC0\n7C\nENDCHAR\nSTARTCHAR 236\nENCODING 236\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\n00\n60\n60\n60\n60\n60\nENDCHAR\nSTARTCHAR 237\nENCODING 237\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\n00\nC0\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR 238\nENCODING 238\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 8 0 0\nBITMAP\n60\nF0\n00\n60\n60\n60\n60\n60\nENDCHAR\nSTARTCHAR 239\nENCODING 239\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n90\n00\n60\n60\n60\n60\n60\nENDCHAR\nSTARTCHAR 240\nENCODING 240\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n3C\n18\n3C\n0C\n7C\nCC\n78\nENDCHAR\nSTARTCHAR 241\nENCODING 241\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\n00\nF8\nCC\nCC\nCC\nCC\nENDCHAR\nSTARTCHAR 242\nENCODING 242\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nE0\n00\n78\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 243\nENCODING 243\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n1C\n00\n78\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 244\nENCODING 244\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\nCC\n78\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 245\nENCODING 245\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nFC\n00\n78\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 246\nENCODING 246\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n48\n00\n78\nCC\nCC\nCC\n78\nENDCHAR\nSTARTCHAR 247\nENCODING 247\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 1\nBITMAP\n30\n00\nFC\n00\n30\nENDCHAR\nSTARTCHAR 248\nENCODING 248\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 5 0 0\nBITMAP\n78\nDC\nFC\nEC\n78\nENDCHAR\nSTARTCHAR 249\nENCODING 249\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\nE0\n00\nCC\nCC\nCC\nCC\n7C\nENDCHAR\nSTARTCHAR 250\nENCODING 250\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n1C\n00\nCC\nCC\nCC\nCC\n7C\nENDCHAR\nSTARTCHAR 251\nENCODING 251\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 8 0 0\nBITMAP\n78\nCC\n00\nCC\nCC\nCC\nCC\n7C\nENDCHAR\nSTARTCHAR 252\nENCODING 252\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\n00\nCC\nCC\nCC\nCC\n7C\nENDCHAR\nSTARTCHAR 253\nENCODING 253\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 8 0 -1\nBITMAP\n1C\n00\nCC\nCC\nCC\n7C\n0C\nF8\nENDCHAR\nSTARTCHAR 254\nENCODING 254\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 8 0 0\nBITMAP\nC0\nC0\nF8\nEC\nCC\nF8\nC0\nC0\nENDCHAR\nSTARTCHAR 255\nENCODING 255\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 8 0 -1\nBITMAP\n78\n00\nCC\nCC\nCC\n7C\n0C\nF8\nENDCHAR\nENDFONT\n"
  },
  {
    "path": "resources/assets/logisticspipes/fonts/minecraft-plain.bdf",
    "content": "STARTFONT 2.1\nCOMMENT Exported by Fony v1.4.7\nFONT Minecraft\nSIZE 11 96 96\nFONTBOUNDINGBOX 10 10 0 -2\nSTARTPROPERTIES 6\nCOPYRIGHT \"Created by Bernasss12 for Logistics Pipes\"\nRESOLUTION_X 96\nRESOLUTION_Y 96\nFONT_ASCENT 9\nFONT_DESCENT 2\nDEFAULT_CHAR 0\nENDPROPERTIES\nCHARS 256\nSTARTCHAR 000\nENCODING 0\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 001\nENCODING 1\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 002\nENCODING 2\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 003\nENCODING 3\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 004\nENCODING 4\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 005\nENCODING 5\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 006\nENCODING 6\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 007\nENCODING 7\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 008\nENCODING 8\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 009\nENCODING 9\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 010\nENCODING 10\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 011\nENCODING 11\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 012\nENCODING 12\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 013\nENCODING 13\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 014\nENCODING 14\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 015\nENCODING 15\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 016\nENCODING 16\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 017\nENCODING 17\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 018\nENCODING 18\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 019\nENCODING 19\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 020\nENCODING 20\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 021\nENCODING 21\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 022\nENCODING 22\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 023\nENCODING 23\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 024\nENCODING 24\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 025\nENCODING 25\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 026\nENCODING 26\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 027\nENCODING 27\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 028\nENCODING 28\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 029\nENCODING 29\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 030\nENCODING 30\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 031\nENCODING 31\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 032\nENCODING 32\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 033\nENCODING 33\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 7 0 0\nBITMAP\n80\n80\n80\n80\n80\n00\n80\nENDCHAR\nSTARTCHAR 034\nENCODING 34\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 3 0 4\nBITMAP\n50\n50\nA0\nENDCHAR\nSTARTCHAR 035\nENCODING 35\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n50\n50\nF8\n50\nF8\n50\n50\nENDCHAR\nSTARTCHAR 036\nENCODING 36\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n20\n78\n80\n70\n08\nF0\n20\nENDCHAR\nSTARTCHAR 037\nENCODING 37\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n90\n10\n20\n40\n48\n88\nENDCHAR\nSTARTCHAR 038\nENCODING 38\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n20\n50\n20\n68\nB0\n90\n68\nENDCHAR\nSTARTCHAR 039\nENCODING 39\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 3 0 4\nBITMAP\n40\n40\n80\nENDCHAR\nSTARTCHAR 040\nENCODING 40\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n30\n40\n80\n80\n80\n40\n30\nENDCHAR\nSTARTCHAR 041\nENCODING 41\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nC0\n20\n10\n10\n10\n20\nC0\nENDCHAR\nSTARTCHAR 042\nENCODING 42\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 3 0 3\nBITMAP\n90\n60\n90\nENDCHAR\nSTARTCHAR 043\nENCODING 43\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 1\nBITMAP\n20\n20\nF8\n20\n20\nENDCHAR\nSTARTCHAR 044\nENCODING 44\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 3 0 -1\nBITMAP\n80\n80\n80\nENDCHAR\nSTARTCHAR 045\nENCODING 45\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 1 0 3\nBITMAP\nF8\nENDCHAR\nSTARTCHAR 046\nENCODING 46\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 2 0 0\nBITMAP\n80\n80\nENDCHAR\nSTARTCHAR 047\nENCODING 47\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n08\n10\n10\n20\n40\n40\n80\nENDCHAR\nSTARTCHAR 048\nENCODING 48\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n98\nA8\nC8\n88\n70\nENDCHAR\nSTARTCHAR 049\nENCODING 49\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n20\n60\n20\n20\n20\n20\nF8\nENDCHAR\nSTARTCHAR 050\nENCODING 50\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n08\n30\n40\n80\nF8\nENDCHAR\nSTARTCHAR 051\nENCODING 51\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n08\n30\n08\n88\n70\nENDCHAR\nSTARTCHAR 052\nENCODING 52\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n18\n28\n48\n88\nF8\n08\n08\nENDCHAR\nSTARTCHAR 053\nENCODING 53\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n80\nF0\n08\n08\n88\n70\nENDCHAR\nSTARTCHAR 054\nENCODING 54\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n30\n40\n80\nF0\n88\n88\n70\nENDCHAR\nSTARTCHAR 055\nENCODING 55\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n88\n08\n10\n20\n20\n20\nENDCHAR\nSTARTCHAR 056\nENCODING 56\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n88\n70\n88\n88\n70\nENDCHAR\nSTARTCHAR 057\nENCODING 57\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n88\n78\n08\n10\n60\nENDCHAR\nSTARTCHAR 058\nENCODING 58\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 6 0 0\nBITMAP\n80\n80\n00\n00\n80\n80\nENDCHAR\nSTARTCHAR 059\nENCODING 59\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 7 0 -1\nBITMAP\n80\n80\n00\n00\n80\n80\n80\nENDCHAR\nSTARTCHAR 060\nENCODING 60\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n10\n20\n40\n80\n40\n20\n10\nENDCHAR\nSTARTCHAR 061\nENCODING 61\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 4 0 1\nBITMAP\nF8\n00\n00\nF8\nENDCHAR\nSTARTCHAR 062\nENCODING 62\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n80\n40\n20\n10\n20\n40\n80\nENDCHAR\nSTARTCHAR 063\nENCODING 63\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n08\n10\n20\n00\n20\nENDCHAR\nSTARTCHAR 064\nENCODING 64\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\n84\nB4\nB4\nBC\n80\n7C\nENDCHAR\nSTARTCHAR 065\nENCODING 65\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 066\nENCODING 66\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF0\n88\nF0\n88\n88\n88\nF0\nENDCHAR\nSTARTCHAR 067\nENCODING 67\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n80\n80\n80\n88\n70\nENDCHAR\nSTARTCHAR 068\nENCODING 68\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF0\n88\n88\n88\n88\n88\nF0\nENDCHAR\nSTARTCHAR 069\nENCODING 69\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n80\nE0\n80\n80\n80\nF8\nENDCHAR\nSTARTCHAR 070\nENCODING 70\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n80\nE0\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR 071\nENCODING 71\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n78\n80\nB8\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 072\nENCODING 72\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 073\nENCODING 73\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\n40\n40\n40\n40\n40\nE0\nENDCHAR\nSTARTCHAR 074\nENCODING 74\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n08\n08\n08\n08\n08\n88\n70\nENDCHAR\nSTARTCHAR 075\nENCODING 75\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n90\nE0\n90\n88\n88\n88\nENDCHAR\nSTARTCHAR 076\nENCODING 76\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n80\n80\n80\n80\n80\n80\nF8\nENDCHAR\nSTARTCHAR 077\nENCODING 77\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\nD8\nA8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 078\nENCODING 78\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\nC8\nA8\n98\n88\n88\n88\nENDCHAR\nSTARTCHAR 079\nENCODING 79\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 080\nENCODING 80\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF0\n88\nF0\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR 081\nENCODING 81\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n88\n88\n88\n90\n68\nENDCHAR\nSTARTCHAR 082\nENCODING 82\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF0\n88\nF0\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 083\nENCODING 83\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n78\n80\n70\n08\n08\n88\n70\nENDCHAR\nSTARTCHAR 084\nENCODING 84\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR 085\nENCODING 85\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 086\nENCODING 86\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n88\n88\n88\n50\n50\n20\nENDCHAR\nSTARTCHAR 087\nENCODING 87\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n88\n88\n88\nA8\nD8\n88\nENDCHAR\nSTARTCHAR 088\nENCODING 88\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n50\n20\n50\n88\n88\n88\nENDCHAR\nSTARTCHAR 089\nENCODING 89\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n88\n50\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR 090\nENCODING 90\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n08\n10\n20\n40\n80\nF8\nENDCHAR\nSTARTCHAR 091\nENCODING 91\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\n80\n80\n80\n80\n80\nE0\nENDCHAR\nSTARTCHAR 092\nENCODING 92\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n80\n40\n40\n20\n10\n10\n08\nENDCHAR\nSTARTCHAR 093\nENCODING 93\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\n20\n20\n20\n20\n20\nE0\nENDCHAR\nSTARTCHAR 094\nENCODING 94\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 3 0 4\nBITMAP\n20\n50\n88\nENDCHAR\nSTARTCHAR 095\nENCODING 95\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 1 0 -1\nBITMAP\nF8\nENDCHAR\nSTARTCHAR 096\nENCODING 96\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 3 0 4\nBITMAP\n80\n80\n40\nENDCHAR\nSTARTCHAR 097\nENCODING 97\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 098\nENCODING 98\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n80\n80\nB0\nC8\n88\n88\nF0\nENDCHAR\nSTARTCHAR 099\nENCODING 99\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n70\n88\n80\n88\n70\nENDCHAR\nSTARTCHAR 100\nENCODING 100\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n08\n08\n68\n98\n88\n88\n78\nENDCHAR\nSTARTCHAR 101\nENCODING 101\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n70\n88\nF8\n80\n78\nENDCHAR\nSTARTCHAR 102\nENCODING 102\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n30\n40\nF0\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR 103\nENCODING 103\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 -1\nBITMAP\n78\n88\n88\n78\n08\nF0\nENDCHAR\nSTARTCHAR 104\nENCODING 104\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n80\n80\nB0\nC8\n88\n88\n88\nENDCHAR\nSTARTCHAR 105\nENCODING 105\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 7 0 0\nBITMAP\n80\n00\n80\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR 106\nENCODING 106\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 8 0 -1\nBITMAP\n08\n00\n08\n08\n08\n08\n88\n88\nENDCHAR\nSTARTCHAR 107\nENCODING 107\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n80\n80\n90\nA0\nC0\nA0\n90\nENDCHAR\nSTARTCHAR 108\nENCODING 108\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\n80\n80\n80\n80\n80\n80\n40\nENDCHAR\nSTARTCHAR 109\nENCODING 109\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\nD0\nA8\nA8\n88\n88\nENDCHAR\nSTARTCHAR 110\nENCODING 110\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\nF0\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 111\nENCODING 111\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n70\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 112\nENCODING 112\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 -1\nBITMAP\nB0\nC8\n88\n88\nF0\n80\nENDCHAR\nSTARTCHAR 113\nENCODING 113\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 -1\nBITMAP\n68\n98\n88\n88\n78\n08\nENDCHAR\nSTARTCHAR 114\nENCODING 114\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\nB0\nC8\n80\n80\n80\nENDCHAR\nSTARTCHAR 115\nENCODING 115\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n78\n80\n70\n08\nF0\nENDCHAR\nSTARTCHAR 116\nENCODING 116\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\n40\n40\nE0\n40\n40\n40\n20\nENDCHAR\nSTARTCHAR 117\nENCODING 117\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n88\n88\n88\n88\n78\nENDCHAR\nSTARTCHAR 118\nENCODING 118\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n88\n88\n88\n50\n20\nENDCHAR\nSTARTCHAR 119\nENCODING 119\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n88\n88\nA8\nA8\n78\nENDCHAR\nSTARTCHAR 120\nENCODING 120\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n88\n50\n20\n50\n88\nENDCHAR\nSTARTCHAR 121\nENCODING 121\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 -1\nBITMAP\n88\n88\n88\n78\n08\nF0\nENDCHAR\nSTARTCHAR 122\nENCODING 122\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\nF8\n10\n20\n40\nF8\nENDCHAR\nSTARTCHAR 123\nENCODING 123\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\n30\n40\n40\n80\n40\n40\n30\nENDCHAR\nSTARTCHAR 124\nENCODING 124\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 7 0 0\nBITMAP\n80\n80\n80\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR 125\nENCODING 125\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 7 0 0\nBITMAP\nC0\n20\n20\n10\n20\n20\nC0\nENDCHAR\nSTARTCHAR 126\nENCODING 126\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 2 0 5\nBITMAP\n64\n98\nENDCHAR\nSTARTCHAR 127\nENCODING 127\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 7 0 0\nBITMAP\nE0\nA0\nA0\nA0\nA0\nA0\nE0\nENDCHAR\nSTARTCHAR 128\nENCODING 128\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 129\nENCODING 129\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 130\nENCODING 130\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 131\nENCODING 131\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 132\nENCODING 132\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 133\nENCODING 133\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 134\nENCODING 134\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 135\nENCODING 135\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 136\nENCODING 136\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 137\nENCODING 137\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 138\nENCODING 138\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 139\nENCODING 139\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 140\nENCODING 140\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 141\nENCODING 141\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 142\nENCODING 142\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 143\nENCODING 143\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 144\nENCODING 144\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 145\nENCODING 145\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 146\nENCODING 146\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 147\nENCODING 147\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 148\nENCODING 148\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 149\nENCODING 149\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 150\nENCODING 150\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 151\nENCODING 151\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 152\nENCODING 152\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 153\nENCODING 153\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 154\nENCODING 154\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 155\nENCODING 155\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 156\nENCODING 156\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 157\nENCODING 157\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 158\nENCODING 158\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 159\nENCODING 159\nSWIDTH 0 0\nDWIDTH 0 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 160\nENCODING 160\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 0 0 0 0\nBITMAP\nENDCHAR\nSTARTCHAR 161\nENCODING 161\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 7 0 0\nBITMAP\n80\n00\n80\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR 162\nENCODING 162\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 5 0 0\nBITMAP\n20\n70\n80\n70\n20\nENDCHAR\nSTARTCHAR 163\nENCODING 163\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n38\n40\n40\nF0\n40\n40\nF8\nENDCHAR\nSTARTCHAR 164\nENCODING 164\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 1\nBITMAP\n88\n70\n50\n70\n88\nENDCHAR\nSTARTCHAR 165\nENCODING 165\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 1\nBITMAP\n88\n50\n20\n70\n20\n70\n20\nENDCHAR\nSTARTCHAR 166\nENCODING 166\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 7 0 0\nBITMAP\n80\n80\n80\n00\n80\n80\n80\nENDCHAR\nSTARTCHAR 167\nENCODING 167\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n78\n80\n70\n50\n70\n08\nF0\nENDCHAR\nSTARTCHAR 168\nENCODING 168\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 1 0 6\nBITMAP\nA0\nENDCHAR\nSTARTCHAR 169\nENCODING 169\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 6 5 0 0\nBITMAP\n78\n94\nA4\n94\n78\nENDCHAR\nSTARTCHAR 170\nENCODING 170\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 1\nBITMAP\n70\n08\nF8\n78\n00\nF8\nENDCHAR\nSTARTCHAR 171\nENCODING 171\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n28\n50\nA0\n50\n28\nENDCHAR\nSTARTCHAR 172\nENCODING 172\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 2 0 3\nBITMAP\nF0\n10\nENDCHAR\nSTARTCHAR 173\nENCODING 173\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 1 0 2\nBITMAP\nE0\nENDCHAR\nSTARTCHAR 174\nENCODING 174\nSWIDTH 576 0\nDWIDTH 8 0\nBBX 6 5 0 1\nBITMAP\n78\nB4\nA4\nD4\n78\nENDCHAR\nSTARTCHAR 175\nENCODING 175\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 1 0 8\nBITMAP\nF8\nENDCHAR\nSTARTCHAR 176\nENCODING 176\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 3 0 5\nBITMAP\n40\nA0\n40\nENDCHAR\nSTARTCHAR 177\nENCODING 177\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n20\n20\nF8\n20\n20\n00\nF8\nENDCHAR\nSTARTCHAR 178\nENCODING 178\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 4 0 3\nBITMAP\nC0\n20\n40\nE0\nENDCHAR\nSTARTCHAR 179\nENCODING 179\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 4 0 3\nBITMAP\nC0\n60\n20\nC0\nENDCHAR\nSTARTCHAR 180\nENCODING 180\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 2 0 6\nBITMAP\n40\n80\nENDCHAR\nSTARTCHAR 181\nENCODING 181\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 -1\nBITMAP\n88\n88\n88\n98\nE8\n80\nENDCHAR\nSTARTCHAR 182\nENCODING 182\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n78\nE8\nE8\n68\n28\n28\n28\nENDCHAR\nSTARTCHAR 183\nENCODING 183\nSWIDTH 144 0\nDWIDTH 2 0\nBBX 1 1 0 3\nBITMAP\n80\nENDCHAR\nSTARTCHAR 184\nENCODING 184\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 1 1 1 -1\nBITMAP\n80\nENDCHAR\nSTARTCHAR 185\nENCODING 185\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 4 0 4\nBITMAP\n40\nC0\n40\nE0\nENDCHAR\nSTARTCHAR 186\nENCODING 186\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 6 0 1\nBITMAP\n70\n88\n88\n70\n00\nF8\nENDCHAR\nSTARTCHAR 187\nENCODING 187\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 5 5 0 0\nBITMAP\nA0\n50\n28\n50\nA0\nENDCHAR\nSTARTCHAR 188\nENCODING 188\nSWIDTH 648 0\nDWIDTH 9 0\nBBX 5 7 0 0\nBITMAP\n88\n90\n10\n20\n58\n58\n88\nENDCHAR\nSTARTCHAR 189\nENCODING 189\nSWIDTH 648 0\nDWIDTH 9 0\nBBX 5 7 0 0\nBITMAP\n88\n90\n10\n20\n48\n50\n98\nENDCHAR\nSTARTCHAR 190\nENCODING 190\nSWIDTH 648 0\nDWIDTH 9 0\nBBX 5 7 0 0\nBITMAP\nC8\n50\n90\n20\n58\n58\n88\nENDCHAR\nSTARTCHAR 191\nENCODING 191\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n20\n00\n20\n40\n80\n88\n70\nENDCHAR\nSTARTCHAR 192\nENCODING 192\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nC0\n00\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 193\nENCODING 193\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n18\n00\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 194\nENCODING 194\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n70\n88\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 195\nENCODING 195\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nF8\n00\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 196\nENCODING 196\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n50\n00\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 197\nENCODING 197\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n70\n88\n70\n88\nF8\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 198\nENCODING 198\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n7C\nA0\nF8\nA0\nA0\nA0\nBC\nENDCHAR\nSTARTCHAR 199\nENCODING 199\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 -2\nBITMAP\n70\n88\n80\n80\n80\n88\n70\n10\n20\nENDCHAR\nSTARTCHAR 200\nENCODING 200\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nC0\n00\nF8\n80\nE0\n80\n80\n80\nF8\nENDCHAR\nSTARTCHAR 201\nENCODING 201\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n18\n00\nF8\n80\nE0\n80\n80\n80\nF8\nENDCHAR\nSTARTCHAR 202\nENCODING 202\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n70\n88\nF8\n80\nE0\n80\n80\n80\nF8\nENDCHAR\nSTARTCHAR 203\nENCODING 203\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n50\n00\nF8\n80\nE0\n80\n80\n80\nF8\nENDCHAR\nSTARTCHAR 204\nENCODING 204\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 9 0 0\nBITMAP\nC0\n00\nE0\n40\n40\n40\n40\n40\nE0\nENDCHAR\nSTARTCHAR 205\nENCODING 205\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 9 0 0\nBITMAP\n60\n00\nE0\n40\n40\n40\n40\n40\nE0\nENDCHAR\nSTARTCHAR 206\nENCODING 206\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 9 0 0\nBITMAP\n40\nA0\nE0\n40\n40\n40\n40\n40\nE0\nENDCHAR\nSTARTCHAR 207\nENCODING 207\nSWIDTH 288 0\nDWIDTH 4 0\nBBX 3 9 0 0\nBITMAP\nA0\n00\nE0\n40\n40\n40\n40\n40\nE0\nENDCHAR\nSTARTCHAR 208\nENCODING 208\nSWIDTH 504 0\nDWIDTH 7 0\nBBX 6 7 0 0\nBITMAP\n78\n44\nE4\n44\n44\n44\n78\nENDCHAR\nSTARTCHAR 209\nENCODING 209\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nF8\n00\n88\nC8\nA8\n98\n88\n88\n88\nENDCHAR\nSTARTCHAR 210\nENCODING 210\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nC0\n00\n70\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 211\nENCODING 211\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n18\n00\n70\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 212\nENCODING 212\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n70\n88\n70\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 213\nENCODING 213\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nF8\n00\n70\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 214\nENCODING 214\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n50\n00\n70\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 215\nENCODING 215\nSWIDTH 360 0\nDWIDTH 5 0\nBBX 4 4 0 0\nBITMAP\n90\n60\n60\n90\nENDCHAR\nSTARTCHAR 216\nENCODING 216\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n98\nA8\nC8\n88\n70\nENDCHAR\nSTARTCHAR 217\nENCODING 217\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\nC0\n00\n88\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 218\nENCODING 218\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n18\n00\n88\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 219\nENCODING 219\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 11 0 -2\nBITMAP\n88\n00\n88\n88\n88\n88\n88\n88\n70\n00\n70\nENDCHAR\nSTARTCHAR 220\nENCODING 220\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n50\n00\n88\n88\n88\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 221\nENCODING 221\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 9 0 0\nBITMAP\n18\n00\n88\n50\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR 222\nENCODING 222\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n80\nF0\n88\nF0\n80\n80\n80\nENDCHAR\nSTARTCHAR 223\nENCODING 223\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n60\n90\nB0\n88\n88\n88\nB0\nENDCHAR\nSTARTCHAR 224\nENCODING 224\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nC0\n00\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 225\nENCODING 225\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n18\n00\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 226\nENCODING 226\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 227\nENCODING 227\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n00\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 228\nENCODING 228\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n50\n00\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 229\nENCODING 229\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n20\n00\n70\n08\n78\n88\n78\nENDCHAR\nSTARTCHAR 230\nENCODING 230\nSWIDTH 720 0\nDWIDTH 10 0\nBBX 8 5 0 0\nBITMAP\n6E\n11\n7F\n90\n6F\nENDCHAR\nSTARTCHAR 231\nENCODING 231\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 -2\nBITMAP\n70\n88\n80\n88\n70\n10\n20\nENDCHAR\nSTARTCHAR 232\nENCODING 232\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nC0\n00\n70\n88\nF8\n80\n78\nENDCHAR\nSTARTCHAR 233\nENCODING 233\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n18\n00\n70\n88\nF8\n80\n78\nENDCHAR\nSTARTCHAR 234\nENCODING 234\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 8 0 0\nBITMAP\n70\n88\n00\n70\n88\nF8\n80\n78\nENDCHAR\nSTARTCHAR 235\nENCODING 235\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n50\n00\n70\n88\nF8\n80\n78\nENDCHAR\nSTARTCHAR 236\nENCODING 236\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\n00\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR 237\nENCODING 237\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 2 7 0 0\nBITMAP\nC0\n00\n80\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR 238\nENCODING 238\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 3 8 0 0\nBITMAP\n40\nA0\n00\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR 239\nENCODING 239\nSWIDTH 216 0\nDWIDTH 3 0\nBBX 3 7 0 0\nBITMAP\nA0\n00\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR 240\nENCODING 240\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n28\n10\n28\n08\n78\n88\n70\nENDCHAR\nSTARTCHAR 241\nENCODING 241\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n00\nF0\n88\n88\n88\n88\nENDCHAR\nSTARTCHAR 242\nENCODING 242\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nC0\n00\n70\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 243\nENCODING 243\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n18\n00\n70\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 244\nENCODING 244\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n70\n88\n70\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 245\nENCODING 245\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nF8\n00\n70\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 246\nENCODING 246\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n50\n00\n70\n88\n88\n88\n70\nENDCHAR\nSTARTCHAR 247\nENCODING 247\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 1\nBITMAP\n20\n00\nF8\n00\n20\nENDCHAR\nSTARTCHAR 248\nENCODING 248\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 5 0 0\nBITMAP\n70\n98\nA8\nC8\n70\nENDCHAR\nSTARTCHAR 249\nENCODING 249\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\nC0\n00\n88\n88\n88\n88\n78\nENDCHAR\nSTARTCHAR 250\nENCODING 250\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n18\n00\n88\n88\n88\n88\n78\nENDCHAR\nSTARTCHAR 251\nENCODING 251\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 8 0 0\nBITMAP\n70\n88\n00\n88\n88\n88\n88\n78\nENDCHAR\nSTARTCHAR 252\nENCODING 252\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 7 0 0\nBITMAP\n50\n00\n88\n88\n88\n88\n78\nENDCHAR\nSTARTCHAR 253\nENCODING 253\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 8 0 -1\nBITMAP\n18\n00\n88\n88\n88\n78\n08\nF0\nENDCHAR\nSTARTCHAR 254\nENCODING 254\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 8 0 0\nBITMAP\n80\n80\nB0\nC8\n88\nF0\n80\n80\nENDCHAR\nSTARTCHAR 255\nENCODING 255\nSWIDTH 432 0\nDWIDTH 6 0\nBBX 5 8 0 -1\nBITMAP\n50\n00\n88\n88\n88\n78\n08\nF0\nENDCHAR\nENDFONT\n"
  },
  {
    "path": "resources/assets/logisticspipes/fonts/ter-u12n.bdf",
    "content": "STARTFONT 2.1\nFONT -xos4-Terminus-Medium-R-Normal--12-120-72-72-C-60-ISO10646-1\nSIZE 12 72 72\nFONTBOUNDINGBOX 6 12 0 -2\nSTARTPROPERTIES 20\nFAMILY_NAME \"Terminus\"\nFOUNDRY \"xos4\"\nSETWIDTH_NAME \"Normal\"\nADD_STYLE_NAME \"\"\nCOPYRIGHT \"Copyright (C) 2019 Dimitar Toshkov Zhekov\"\nNOTICE \"Licensed under the SIL Open Font License, Version 1.1\"\nWEIGHT_NAME \"Medium\"\nSLANT \"R\"\nPIXEL_SIZE 12\nPOINT_SIZE 120\nRESOLUTION_X 72\nRESOLUTION_Y 72\nSPACING \"C\"\nAVERAGE_WIDTH 60\nCHARSET_REGISTRY \"ISO10646\"\nCHARSET_ENCODING \"1\"\nMIN_SPACE 6\nFONT_ASCENT 10\nFONT_DESCENT 2\nDEFAULT_CHAR 65533\nENDPROPERTIES\nCHARS 1354\nSTARTCHAR char0\nENCODING 0\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nD8\n88\n00\n88\n88\n00\n88\nD8\n00\n00\nENDCHAR\nSTARTCHAR space\nENCODING 32\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR exclam\nENCODING 33\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n20\n20\n20\n00\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR quotedbl\nENCODING 34\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n50\n50\n50\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR numbersign\nENCODING 35\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\nF8\n50\n50\nF8\n50\n50\n00\n00\nENDCHAR\nSTARTCHAR dollar\nENCODING 36\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nA8\nA0\n70\n28\nA8\n70\n20\n00\nENDCHAR\nSTARTCHAR percent\nENCODING 37\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n48\nA8\n50\n10\n20\n28\n54\n48\n00\n00\nENDCHAR\nSTARTCHAR ampersand\nENCODING 38\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n50\n20\n68\n90\n90\n68\n00\n00\nENDCHAR\nSTARTCHAR quotesingle\nENCODING 39\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n20\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR parenleft\nENCODING 40\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n40\n40\n40\n40\n20\n10\n00\n00\nENDCHAR\nSTARTCHAR parenright\nENCODING 41\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n10\n10\n10\n10\n20\n40\n00\n00\nENDCHAR\nSTARTCHAR asterisk\nENCODING 42\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n50\n20\nF8\n20\n50\n00\n00\n00\nENDCHAR\nSTARTCHAR plus\nENCODING 43\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n20\nF8\n20\n20\n00\n00\n00\nENDCHAR\nSTARTCHAR comma\nENCODING 44\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n20\n20\n40\n00\nENDCHAR\nSTARTCHAR hyphen\nENCODING 45\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nF8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR period\nENCODING 46\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR slash\nENCODING 47\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n08\n10\n10\n20\n20\n40\n40\n00\n00\nENDCHAR\nSTARTCHAR zero\nENCODING 48\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n98\nA8\nC8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR one\nENCODING 49\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n60\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR two\nENCODING 50\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n08\n10\n20\n40\nF8\n00\n00\nENDCHAR\nSTARTCHAR three\nENCODING 51\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n30\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR four\nENCODING 52\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n18\n28\n48\n88\nF8\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR five\nENCODING 53\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR six\nENCODING 54\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n80\n80\nF0\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR seven\nENCODING 55\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n08\n10\n10\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR eight\nENCODING 56\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n70\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR nine\nENCODING 57\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n78\n08\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR colon\nENCODING 58\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n20\n00\n00\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR semicolon\nENCODING 59\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n20\n00\n00\n20\n20\n40\n00\nENDCHAR\nSTARTCHAR less\nENCODING 60\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n10\n20\n40\n20\n10\n08\n00\n00\nENDCHAR\nSTARTCHAR equal\nENCODING 61\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n00\n00\nF8\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR greater\nENCODING 62\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n20\n10\n08\n10\n20\n40\n00\n00\nENDCHAR\nSTARTCHAR question\nENCODING 63\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n10\n20\n00\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR at\nENCODING 64\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n98\nA8\nA8\n98\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR A\nENCODING 65\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR B\nENCODING 66\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\nF0\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR C\nENCODING 67\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n80\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR D\nENCODING 68\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n88\n88\n88\n88\n90\nE0\n00\n00\nENDCHAR\nSTARTCHAR E\nENCODING 69\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR F\nENCODING 70\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR G\nENCODING 71\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n80\nB8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR H\nENCODING 72\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\nF8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR I\nENCODING 73\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR J\nENCODING 74\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n38\n10\n10\n10\n10\n90\n90\n60\n00\n00\nENDCHAR\nSTARTCHAR K\nENCODING 75\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n90\nA0\nC0\nC0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR L\nENCODING 76\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\n80\n80\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR M\nENCODING 77\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\nD8\nA8\nA8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR N\nENCODING 78\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\n98\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR O\nENCODING 79\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR P\nENCODING 80\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\nF0\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR Q\nENCODING 81\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\nA8\n70\n08\n00\nENDCHAR\nSTARTCHAR R\nENCODING 82\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\nF0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR S\nENCODING 83\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n70\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR T\nENCODING 84\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR U\nENCODING 85\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR V\nENCODING 86\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n50\n50\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR W\nENCODING 87\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\nA8\nA8\nD8\n88\n00\n00\nENDCHAR\nSTARTCHAR X\nENCODING 88\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n20\n20\n50\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Y\nENCODING 89\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Z\nENCODING 90\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n10\n20\n40\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR bracketleft\nENCODING 91\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n40\n40\n40\n40\n40\n40\n70\n00\n00\nENDCHAR\nSTARTCHAR backslash\nENCODING 92\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n20\n20\n10\n10\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR bracketright\nENCODING 93\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n10\n10\n10\n10\n10\n10\n70\n00\n00\nENDCHAR\nSTARTCHAR asciicircum\nENCODING 94\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n50\n88\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR underscore\nENCODING 95\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nF8\n00\nENDCHAR\nSTARTCHAR grave\nENCODING 96\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR a\nENCODING 97\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR b\nENCODING 98\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\nF0\n88\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR c\nENCODING 99\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR d\nENCODING 100\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n08\n78\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR e\nENCODING 101\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR f\nENCODING 102\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n18\n20\n70\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR g\nENCODING 103\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR h\nENCODING 104\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR i\nENCODING 105\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n00\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR j\nENCODING 106\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n08\n08\n00\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR k\nENCODING 107\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n48\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR l\nENCODING 108\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR m\nENCODING 109\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\nA8\nA8\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR n\nENCODING 110\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR o\nENCODING 111\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR p\nENCODING 112\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\nF0\n80\n80\nENDCHAR\nSTARTCHAR q\nENCODING 113\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n88\n88\n88\n88\n78\n08\n08\nENDCHAR\nSTARTCHAR r\nENCODING 114\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nB8\nC0\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR s\nENCODING 115\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n80\n70\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR t\nENCODING 116\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n20\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR u\nENCODING 117\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR v\nENCODING 118\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n50\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR w\nENCODING 119\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\nA8\nA8\nA8\n70\n00\n00\nENDCHAR\nSTARTCHAR x\nENCODING 120\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n50\n20\n20\n50\n88\n00\n00\nENDCHAR\nSTARTCHAR y\nENCODING 121\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR z\nENCODING 122\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n10\n20\n40\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR braceleft\nENCODING 123\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n18\n20\n20\n40\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR bar\nENCODING 124\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR braceright\nENCODING 125\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n10\n10\n08\n10\n10\n10\n60\n00\n00\nENDCHAR\nSTARTCHAR asciitilde\nENCODING 126\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n48\nA8\n90\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR nbspace\nENCODING 160\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR exclamdown\nENCODING 161\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n00\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR cent\nENCODING 162\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n70\nA8\nA0\nA0\nA8\n70\n20\n00\nENDCHAR\nSTARTCHAR sterling\nENCODING 163\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n30\n48\n40\nF0\n40\n40\n48\nF8\n00\n00\nENDCHAR\nSTARTCHAR currency\nENCODING 164\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n30\n48\n48\n30\n48\n00\n00\n00\nENDCHAR\nSTARTCHAR yen\nENCODING 165\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n20\n70\n20\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR brokenbar\nENCODING 166\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n20\n00\n00\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR section\nENCODING 167\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n48\n20\n50\n48\n28\n10\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR dieresis\nENCODING 168\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR copyright\nENCODING 169\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n84\nB4\nA4\nA4\nB4\n84\n78\n00\n00\nENDCHAR\nSTARTCHAR ordfeminine\nENCODING 170\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n08\n38\n48\n38\n00\n78\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR guillemotleft\nENCODING 171\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n14\n28\n50\nA0\n50\n28\n14\n00\n00\nENDCHAR\nSTARTCHAR logicalnot\nENCODING 172\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n08\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR softhyphen\nENCODING 173\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n78\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR registered\nENCODING 174\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n84\nB4\nAC\nB4\nAC\n84\n78\n00\n00\nENDCHAR\nSTARTCHAR macron\nENCODING 175\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR degree\nENCODING 176\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n50\n20\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR plusminus\nENCODING 177\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n20\nF8\n20\n20\n00\nF8\n00\n00\nENDCHAR\nSTARTCHAR twosuperior\nENCODING 178\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n48\n10\n20\n78\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR threesuperior\nENCODING 179\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n70\n08\n30\n08\n70\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR acute\nENCODING 180\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR mu\nENCODING 181\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n98\nE8\n80\n80\nENDCHAR\nSTARTCHAR paragraph\nENCODING 182\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\nA8\nA8\nA8\n68\n28\n28\n28\n00\n00\nENDCHAR\nSTARTCHAR periodcentered\nENCODING 183\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n20\n20\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR cedilla\nENCODING 184\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n20\n20\n40\nENDCHAR\nSTARTCHAR onesuperior\nENCODING 185\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n10\n30\n10\n10\n38\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR ordmasculine\nENCODING 186\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n48\n48\n48\n30\n00\n78\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR guillemotright\nENCODING 187\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nA0\n50\n28\n14\n28\n50\nA0\n00\n00\nENDCHAR\nSTARTCHAR onequarter\nENCODING 188\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\nC0\n44\n48\n50\n20\n48\n98\n28\n78\n08\n08\nENDCHAR\nSTARTCHAR onehalf\nENCODING 189\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\nC0\n44\n48\n50\n20\n40\n98\n24\n08\n10\n3C\nENDCHAR\nSTARTCHAR threequarters\nENCODING 190\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nE0\n10\n60\n14\nE8\n10\n24\n4C\n94\n3C\n04\n04\nENDCHAR\nSTARTCHAR questiondown\nENCODING 191\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n00\n20\n40\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Agrave\nENCODING 192\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Aacute\nENCODING 193\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Acircumflex\nENCODING 194\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Atilde\nENCODING 195\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Adieresis\nENCODING 196\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Aring\nENCODING 197\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR AE\nENCODING 198\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n7C\n90\n90\nFC\n90\n90\n90\n9C\n00\n00\nENDCHAR\nSTARTCHAR Ccedilla\nENCODING 199\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n80\n80\n80\n88\n70\n20\n40\nENDCHAR\nSTARTCHAR Egrave\nENCODING 200\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Eacute\nENCODING 201\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Ecircumflex\nENCODING 202\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Edieresis\nENCODING 203\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Igrave\nENCODING 204\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Iacute\nENCODING 205\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Icircumflex\nENCODING 206\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Idieresis\nENCODING 207\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Eth\nENCODING 208\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n88\nE8\n88\n88\n90\nE0\n00\n00\nENDCHAR\nSTARTCHAR Ntilde\nENCODING 209\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n88\n88\nC8\nA8\n98\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Ograve\nENCODING 210\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Oacute\nENCODING 211\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Ocircumflex\nENCODING 212\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Otilde\nENCODING 213\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Odieresis\nENCODING 214\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR multiply\nENCODING 215\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n50\n20\n50\n88\n00\n00\n00\nENDCHAR\nSTARTCHAR Oslash\nENCODING 216\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n74\n88\n98\nA8\nC8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Ugrave\nENCODING 217\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Uacute\nENCODING 218\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Ucircumflex\nENCODING 219\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Udieresis\nENCODING 220\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Yacute\nENCODING 221\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Thorn\nENCODING 222\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\nF0\n88\n88\n88\nF0\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR germandbls\nENCODING 223\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n90\nF0\n88\n88\nC8\nB0\n00\n00\nENDCHAR\nSTARTCHAR agrave\nENCODING 224\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR aacute\nENCODING 225\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR acircumflex\nENCODING 226\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR atilde\nENCODING 227\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR adieresis\nENCODING 228\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR aring\nENCODING 229\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR ae\nENCODING 230\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n28\n68\nB0\nA0\n78\n00\n00\nENDCHAR\nSTARTCHAR ccedilla\nENCODING 231\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n80\n80\n88\n70\n20\n40\nENDCHAR\nSTARTCHAR egrave\nENCODING 232\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR eacute\nENCODING 233\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR ecircumflex\nENCODING 234\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR edieresis\nENCODING 235\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR igrave\nENCODING 236\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR iacute\nENCODING 237\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR icircumflex\nENCODING 238\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR idieresis\nENCODING 239\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR eth\nENCODING 240\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\nA0\n40\nA0\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ntilde\nENCODING 241\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR ograve\nENCODING 242\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR oacute\nENCODING 243\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ocircumflex\nENCODING 244\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR otilde\nENCODING 245\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR odieresis\nENCODING 246\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR divide\nENCODING 247\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n20\n00\nF8\n00\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR oslash\nENCODING 248\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n74\n98\nA8\nC8\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ugrave\nENCODING 249\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uacute\nENCODING 250\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR ucircumflex\nENCODING 251\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR udieresis\nENCODING 252\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR yacute\nENCODING 253\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR thorn\nENCODING 254\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\nF0\n88\n88\n88\n88\nF0\n80\n80\nENDCHAR\nSTARTCHAR ydieresis\nENCODING 255\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Amacron\nENCODING 256\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR amacron\nENCODING 257\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Abreve\nENCODING 258\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR abreve\nENCODING 259\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Aogonek\nENCODING 260\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\nF8\n88\n88\n88\n10\n0C\nENDCHAR\nSTARTCHAR aogonek\nENCODING 261\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n08\n78\n88\n88\n78\n10\n0C\nENDCHAR\nSTARTCHAR Cacute\nENCODING 262\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n70\n88\n80\n80\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR cacute\nENCODING 263\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Ccircumflex\nENCODING 264\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n88\n80\n80\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ccircumflex\nENCODING 265\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Cdotaccent\nENCODING 266\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n70\n88\n80\n80\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR cdotaccent\nENCODING 267\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Ccaron\nENCODING 268\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n80\n80\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ccaron\nENCODING 269\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Dcaron\nENCODING 270\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nA0\n40\nE0\n90\n88\n88\n88\n88\n90\nE0\n00\n00\nENDCHAR\nSTARTCHAR dcaron\nENCODING 271\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n08\n08\n78\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Dcroat\nENCODING 272\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n88\nE8\n88\n88\n90\nE0\n00\n00\nENDCHAR\nSTARTCHAR dcroat\nENCODING 273\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n3C\n08\n78\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Emacron\nENCODING 274\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR emacron\nENCODING 275\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR Ebreve\nENCODING 276\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR ebreve\nENCODING 277\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR Edotaccent\nENCODING 278\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR edotaccent\nENCODING 279\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR Eogonek\nENCODING 280\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n80\n80\n80\nF8\n10\n0C\nENDCHAR\nSTARTCHAR eogonek\nENCODING 281\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nF8\n80\n80\n78\n20\n18\nENDCHAR\nSTARTCHAR Ecaron\nENCODING 282\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR ecaron\nENCODING 283\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR Gcircumflex\nENCODING 284\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n88\n80\n80\nB8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR gcircumflex\nENCODING 285\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Gbreve\nENCODING 286\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n80\n80\nB8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR gbreve\nENCODING 287\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Gdotaccent\nENCODING 288\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n70\n88\n80\n80\nB8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR gdotaccent\nENCODING 289\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Gcommaaccent\nENCODING 290\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n80\nB8\n88\n88\n70\n20\n40\nENDCHAR\nSTARTCHAR gcommaaccent\nENCODING 291\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Hcircumflex\nENCODING 292\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n88\n88\n88\nF8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR hcircumflex\nENCODING 293\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n80\n80\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Hbar\nENCODING 294\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n48\nFC\n48\n78\n48\n48\n48\n48\n00\n00\nENDCHAR\nSTARTCHAR hbar\nENCODING 295\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\nF0\n40\n70\n48\n48\n48\n48\n00\n00\nENDCHAR\nSTARTCHAR Itilde\nENCODING 296\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR itilde\nENCODING 297\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Imacron\nENCODING 298\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR imacron\nENCODING 299\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Ibreve\nENCODING 300\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR ibreve\nENCODING 301\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Iogonek\nENCODING 302\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n20\n20\n20\n20\n20\n20\n70\n20\n18\nENDCHAR\nSTARTCHAR iogonek\nENCODING 303\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n00\n60\n20\n20\n20\n20\n70\n20\n18\nENDCHAR\nSTARTCHAR Idotaccent\nENCODING 304\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR dotlessi\nENCODING 305\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR IJ\nENCODING 306\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\nA8\nA8\n90\n00\n00\nENDCHAR\nSTARTCHAR ij\nENCODING 307\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n88\n88\n00\n98\n88\n88\n88\n88\n88\n28\n10\nENDCHAR\nSTARTCHAR Jcircumflex\nENCODING 308\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n28\n38\n10\n10\n10\n10\n90\n90\n60\n00\n00\nENDCHAR\nSTARTCHAR jcircumflex\nENCODING 309\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n14\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR Kcommaaccent\nENCODING 310\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n90\nA0\nC0\nC0\nA0\n90\nA8\n20\n40\nENDCHAR\nSTARTCHAR kcommaaccent\nENCODING 311\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n48\n50\n60\n60\n50\n68\n20\n40\nENDCHAR\nSTARTCHAR kgreenlandic\nENCODING 312\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n48\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR Lacute\nENCODING 313\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n40\n80\n80\n80\n80\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR lacute\nENCODING 314\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n60\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Lcommaaccent\nENCODING 315\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\n80\n80\n80\n80\n80\nF8\n20\n40\nENDCHAR\nSTARTCHAR lcommaaccent\nENCODING 316\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n20\n20\n20\n20\n20\n20\n70\n20\n40\nENDCHAR\nSTARTCHAR Lcaron\nENCODING 317\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n80\n80\n80\n80\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR lcaron\nENCODING 318\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n60\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Ldot\nENCODING 319\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\n80\n90\n90\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR ldot\nENCODING 320\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n20\n20\n24\n24\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Lslash\nENCODING 321\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n40\n60\nC0\n40\n40\n7C\n00\n00\nENDCHAR\nSTARTCHAR lslash\nENCODING 322\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n20\n20\n30\n60\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Nacute\nENCODING 323\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n88\n88\nC8\nA8\n98\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR nacute\nENCODING 324\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Ncommaaccent\nENCODING 325\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\n98\n88\n88\nA8\n20\n40\nENDCHAR\nSTARTCHAR ncommaaccent\nENCODING 326\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\nA8\n20\n40\nENDCHAR\nSTARTCHAR Ncaron\nENCODING 327\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n88\n88\nC8\nA8\n98\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR ncaron\nENCODING 328\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR napostrophe\nENCODING 329\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n40\n40\n80\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Eng\nENCODING 330\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\n98\n88\n88\n88\n08\n10\nENDCHAR\nSTARTCHAR eng\nENCODING 331\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\n88\n08\n10\nENDCHAR\nSTARTCHAR Omacron\nENCODING 332\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR omacron\nENCODING 333\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Obreve\nENCODING 334\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR obreve\nENCODING 335\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Ohungarumlaut\nENCODING 336\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ohungarumlaut\nENCODING 337\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR OE\nENCODING 338\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n7C\n90\n90\n9C\n90\n90\n90\n7C\n00\n00\nENDCHAR\nSTARTCHAR oe\nENCODING 339\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\nA8\nA8\nB0\nA0\n78\n00\n00\nENDCHAR\nSTARTCHAR Racute\nENCODING 340\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\nF0\n88\n88\n88\nF0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR racute\nENCODING 341\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\nB8\nC0\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR Rcommaaccent\nENCODING 342\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\nF0\nA0\n90\nA8\n20\n40\nENDCHAR\nSTARTCHAR rcommaaccent\nENCODING 343\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nB8\nC0\n80\n80\n80\nC0\n40\n80\nENDCHAR\nSTARTCHAR Rcaron\nENCODING 344\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF0\n88\n88\n88\nF0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR rcaron\nENCODING 345\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\nB8\nC0\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR Sacute\nENCODING 346\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n70\n88\n80\n70\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR sacute\nENCODING 347\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n78\n80\n70\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR Scircumflex\nENCODING 348\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n70\n88\n80\n70\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR scircumflex\nENCODING 349\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n78\n80\n70\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR Scedilla\nENCODING 350\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n70\n08\n08\n88\n70\n20\n40\nENDCHAR\nSTARTCHAR scedilla\nENCODING 351\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n80\n70\n08\n08\nF0\n20\n40\nENDCHAR\nSTARTCHAR Scaron\nENCODING 352\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n80\n70\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR scaron\nENCODING 353\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n78\n80\n70\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR Tcedilla\nENCODING 354\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n20\n20\n20\n20\n30\n10\n20\nENDCHAR\nSTARTCHAR tcedilla\nENCODING 355\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n20\n20\n20\n20\n18\n10\n20\nENDCHAR\nSTARTCHAR Tcaron\nENCODING 356\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF8\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR tcaron\nENCODING 357\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n20\n20\n70\n20\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR Tbar\nENCODING 358\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n70\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR tbar\nENCODING 359\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n20\n70\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR Utilde\nENCODING 360\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR utilde\nENCODING 361\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Umacron\nENCODING 362\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR umacron\nENCODING 363\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Ubreve\nENCODING 364\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR ubreve\nENCODING 365\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Uring\nENCODING 366\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\nA8\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uring\nENCODING 367\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\nA8\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Uhungarumlaut\nENCODING 368\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uhungarumlaut\nENCODING 369\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR Uogonek\nENCODING 370\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\n88\n88\n70\n20\n18\nENDCHAR\nSTARTCHAR uogonek\nENCODING 371\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n78\n10\n0C\nENDCHAR\nSTARTCHAR Wcircumflex\nENCODING 372\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n88\n88\n88\n88\nA8\nA8\nD8\n88\n00\n00\nENDCHAR\nSTARTCHAR wcircumflex\nENCODING 373\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n88\n88\nA8\nA8\nA8\n70\n00\n00\nENDCHAR\nSTARTCHAR Ycircumflex\nENCODING 374\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR ycircumflex\nENCODING 375\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n50\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Ydieresis\nENCODING 376\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Zacute\nENCODING 377\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\nF8\n08\n10\n20\n40\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR zacute\nENCODING 378\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\nF8\n10\n20\n40\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Zdotaccent\nENCODING 379\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\nF8\n08\n10\n20\n40\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR zdotaccent\nENCODING 380\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\nF8\n10\n20\n40\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Zcaron\nENCODING 381\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF8\n08\n10\n20\n40\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR zcaron\nENCODING 382\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\nF8\n10\n20\n40\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR longs\nENCODING 383\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n18\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni0186\nENCODING 390\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n08\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni018E\nENCODING 398\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n08\n78\n08\n08\n08\nF8\n00\n00\nENDCHAR\nSTARTCHAR Schwa\nENCODING 399\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n08\nF8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni0190\nENCODING 400\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n60\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR florin\nENCODING 402\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n28\n20\n70\n20\n20\n20\n20\nA0\n40\nENDCHAR\nSTARTCHAR uni019D\nENCODING 413\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\n98\n88\n88\nC8\n40\n80\nENDCHAR\nSTARTCHAR uni019E\nENCODING 414\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\n88\n08\n08\nENDCHAR\nSTARTCHAR uni01B5\nENCODING 437\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n10\nF8\n20\n40\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni01B6\nENCODING 438\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n10\n78\n20\n40\nF8\n00\n00\nENDCHAR\nSTARTCHAR Ezh\nENCODING 439\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n10\n30\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01CD\nENCODING 461\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni01CE\nENCODING 462\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uni01CF\nENCODING 463\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01D0\nENCODING 464\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01D1\nENCODING 465\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01D2\nENCODING 466\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01D3\nENCODING 467\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01D4\nENCODING 468\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uni01E2\nENCODING 482\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n78\n00\n7C\n90\n90\nFC\n90\n90\n90\n9C\n00\n00\nENDCHAR\nSTARTCHAR uni01E3\nENCODING 483\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n70\n28\n68\nB0\nA0\n78\n00\n00\nENDCHAR\nSTARTCHAR uni01E4\nENCODING 484\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n80\n80\nB8\n88\n9C\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01E5\nENCODING 485\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n88\n9C\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR Gcaron\nENCODING 486\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n80\n80\nB8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR gcaron\nENCODING 487\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR uni01E8\nENCODING 488\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n88\n90\nA0\nC0\nC0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR uni01E9\nENCODING 489\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n40\n40\n48\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR uni01EA\nENCODING 490\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n88\n70\n20\n18\nENDCHAR\nSTARTCHAR uni01EB\nENCODING 491\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\n70\n20\n18\nENDCHAR\nSTARTCHAR uni01EC\nENCODING 492\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n70\n88\n88\n88\n88\n88\n88\n70\n20\n18\nENDCHAR\nSTARTCHAR uni01ED\nENCODING 493\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n70\n88\n88\n88\n88\n70\n20\n18\nENDCHAR\nSTARTCHAR uni01EE\nENCODING 494\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF8\n08\n10\n30\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01EF\nENCODING 495\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\nF8\n08\n10\n30\n08\n08\n88\n70\nENDCHAR\nSTARTCHAR uni01F0\nENCODING 496\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n14\n08\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR uni01F4\nENCODING 500\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n70\n88\n80\n80\nB8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni01F5\nENCODING 501\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR AEacute\nENCODING 508\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n10\n7C\n90\n90\nFC\n90\n90\n90\n9C\n00\n00\nENDCHAR\nSTARTCHAR aeacute\nENCODING 509\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n28\n68\nB0\nA0\n78\n00\n00\nENDCHAR\nSTARTCHAR Oslashacute\nENCODING 510\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n74\n88\n98\nA8\nC8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR oslashacute\nENCODING 511\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n74\n98\nA8\nC8\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Scommaaccent\nENCODING 536\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n70\n08\n08\n88\n70\n20\n40\nENDCHAR\nSTARTCHAR scommaaccent\nENCODING 537\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n80\n70\n08\n08\nF0\n20\n40\nENDCHAR\nSTARTCHAR Tcommaaccent\nENCODING 538\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n20\n20\n20\n20\n30\n10\n20\nENDCHAR\nSTARTCHAR tcommaaccent\nENCODING 539\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n20\n20\n20\n20\n18\n08\n10\nENDCHAR\nSTARTCHAR uni0232\nENCODING 562\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni0233\nENCODING 563\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR dotlessj\nENCODING 567\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR uni0254\nENCODING 596\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni0258\nENCODING 600\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nF8\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR schwa\nENCODING 601\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n08\nF8\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni025B\nENCODING 603\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n60\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni0272\nENCODING 626\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\nC8\n40\n80\nENDCHAR\nSTARTCHAR ezh\nENCODING 658\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n08\n10\n30\n08\n08\n88\n70\nENDCHAR\nSTARTCHAR commaturnedmod\nENCODING 699\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii57929\nENCODING 700\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii64937\nENCODING 701\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n10\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR circumflex\nENCODING 710\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR caron\nENCODING 711\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR breve\nENCODING 728\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR dotaccent\nENCODING 729\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR ogonek\nENCODING 731\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n10\n20\n18\nENDCHAR\nSTARTCHAR tilde\nENCODING 732\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR hungarumlaut\nENCODING 733\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR gravecomb\nENCODING 768\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR acutecomb\nENCODING 769\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0302\nENCODING 770\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR tildecomb\nENCODING 771\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0304\nENCODING 772\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0305\nENCODING 773\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nF8\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0306\nENCODING 774\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0307\nENCODING 775\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0308\nENCODING 776\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni030A\nENCODING 778\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n50\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni030B\nENCODING 779\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni030C\nENCODING 780\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni0329\nENCODING 809\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n20\n20\nENDCHAR\nSTARTCHAR tonos\nENCODING 900\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR dieresistonos\nENCODING 901\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n50\n50\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR Alphatonos\nENCODING 902\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR anoteleia\nENCODING 903\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n20\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR Epsilontonos\nENCODING 904\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Etatonos\nENCODING 905\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n88\n88\n88\nF8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Iotatonos\nENCODING 906\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Omicrontonos\nENCODING 908\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Upsilontonos\nENCODING 910\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Omegatonos\nENCODING 911\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n80\n70\n88\n88\n88\n88\n88\n50\nD8\n00\n00\nENDCHAR\nSTARTCHAR iotadieresistonos\nENCODING 912\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n50\n50\n60\n20\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR Alpha\nENCODING 913\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Beta\nENCODING 914\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\nF0\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR Gamma\nENCODING 915\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR Delta\nENCODING 916\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n50\n50\n88\n88\n88\nF8\n00\n00\nENDCHAR\nSTARTCHAR Epsilon\nENCODING 917\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Zeta\nENCODING 918\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n10\n20\n40\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Eta\nENCODING 919\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\nF8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Theta\nENCODING 920\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\nA8\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Iota\nENCODING 921\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Kappa\nENCODING 922\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n90\nA0\nC0\nC0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR Lambda\nENCODING 923\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n50\n50\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Mu\nENCODING 924\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\nD8\nA8\nA8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Nu\nENCODING 925\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\n98\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Xi\nENCODING 926\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n00\n00\n70\n00\n00\n00\nF8\n00\n00\nENDCHAR\nSTARTCHAR Omicron\nENCODING 927\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR Pi\nENCODING 928\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n88\n88\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Rho\nENCODING 929\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\nF0\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR Sigma\nENCODING 931\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n40\n20\n10\n10\n20\n40\nF8\n00\n00\nENDCHAR\nSTARTCHAR Tau\nENCODING 932\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Upsilon\nENCODING 933\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Phi\nENCODING 934\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nA8\nA8\nA8\nA8\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR Chi\nENCODING 935\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n20\n20\n50\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR Psi\nENCODING 936\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA8\nA8\nA8\nA8\nA8\n70\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR Omega\nENCODING 937\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n50\nD8\n00\n00\nENDCHAR\nSTARTCHAR Iotadieresis\nENCODING 938\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR Upsilondieresis\nENCODING 939\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR alphatonos\nENCODING 940\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n68\n90\n90\n90\n90\n68\n00\n00\nENDCHAR\nSTARTCHAR epsilontonos\nENCODING 941\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n88\n60\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR etatonos\nENCODING 942\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\nF0\n88\n88\n88\n88\n88\n08\n08\nENDCHAR\nSTARTCHAR iotatonos\nENCODING 943\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n60\n20\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR upsilondieresistonos\nENCODING 944\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n50\n50\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR alpha\nENCODING 945\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n68\n90\n90\n90\n90\n68\n00\n00\nENDCHAR\nSTARTCHAR beta\nENCODING 946\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n90\nF0\n88\n88\n88\nF0\n80\n80\nENDCHAR\nSTARTCHAR gamma\nENCODING 947\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n50\n50\n20\n20\n20\nENDCHAR\nSTARTCHAR delta\nENCODING 948\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n40\n20\n70\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR epsilon\nENCODING 949\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n60\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR zeta\nENCODING 950\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n10\n20\n40\n80\n80\n80\n70\n08\n10\nENDCHAR\nSTARTCHAR eta\nENCODING 951\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\n88\n08\n08\nENDCHAR\nSTARTCHAR theta\nENCODING 952\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n30\n48\n48\n78\n48\n48\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR iota\nENCODING 953\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n60\n20\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR kappa\nENCODING 954\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n48\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR lambda\nENCODING 955\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n20\n20\n50\n50\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR mugreek\nENCODING 956\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n98\nE8\n80\n80\nENDCHAR\nSTARTCHAR nu\nENCODING 957\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n50\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR xi\nENCODING 958\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n80\n80\n70\n80\n80\n80\n70\n08\n10\nENDCHAR\nSTARTCHAR omicron\nENCODING 959\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR pi\nENCODING 960\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR rho\nENCODING 961\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\nF0\n80\n80\nENDCHAR\nSTARTCHAR sigma1\nENCODING 962\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n80\n80\n80\n70\n08\n10\nENDCHAR\nSTARTCHAR sigma\nENCODING 963\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n90\n90\n90\n90\n60\n00\n00\nENDCHAR\nSTARTCHAR tau\nENCODING 964\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n20\n20\n20\n20\n10\n00\n00\nENDCHAR\nSTARTCHAR upsilon\nENCODING 965\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR phi\nENCODING 966\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n90\nA8\nA8\nA8\nA8\n70\n20\n20\nENDCHAR\nSTARTCHAR chi\nENCODING 967\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n50\n20\n20\n50\n88\n88\nENDCHAR\nSTARTCHAR psi\nENCODING 968\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA8\nA8\nA8\nA8\nA8\n70\n20\n20\nENDCHAR\nSTARTCHAR omega\nENCODING 969\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n50\n88\nA8\nA8\nA8\n50\n00\n00\nENDCHAR\nSTARTCHAR iotadieresis\nENCODING 970\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n60\n20\n20\n20\n20\n18\n00\n00\nENDCHAR\nSTARTCHAR upsilondieresis\nENCODING 971\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR omicrontonos\nENCODING 972\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR upsilontonos\nENCODING 973\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR omegatonos\nENCODING 974\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\n50\n88\nA8\nA8\nA8\n50\n00\n00\nENDCHAR\nSTARTCHAR theta1\nENCODING 977\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n30\n48\n48\n3C\n08\nC8\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR phi1\nENCODING 981\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n70\nA8\nA8\nA8\nA8\n70\n20\n00\nENDCHAR\nSTARTCHAR uni03F0\nENCODING 1008\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nC4\n28\n10\n20\n50\n8C\n00\n00\nENDCHAR\nSTARTCHAR uni03F1\nENCODING 1009\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\nF0\n80\n70\nENDCHAR\nSTARTCHAR uni03F2\nENCODING 1010\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni03F3\nENCODING 1011\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n08\n08\n00\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR uni03F4\nENCODING 1012\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\nF8\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni03F5\nENCODING 1013\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n80\nF0\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR uni03F6\nENCODING 1014\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n08\n78\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR uni0400\nENCODING 1024\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR afii10023\nENCODING 1025\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR afii10051\nENCODING 1026\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n40\n40\n70\n48\n48\n48\n48\n08\n10\nENDCHAR\nSTARTCHAR afii10052\nENCODING 1027\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\nF8\n80\n80\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR afii10053\nENCODING 1028\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\nF0\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10054\nENCODING 1029\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n70\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10055\nENCODING 1030\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10056\nENCODING 1031\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10057\nENCODING 1032\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n38\n10\n10\n10\n10\n90\n90\n60\n00\n00\nENDCHAR\nSTARTCHAR afii10058\nENCODING 1033\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\nA0\nB0\nA8\nA8\nA8\nA8\nB0\n00\n00\nENDCHAR\nSTARTCHAR afii10059\nENCODING 1034\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA0\nA0\nB0\nE8\nA8\nA8\nA8\nB0\n00\n00\nENDCHAR\nSTARTCHAR afii10060\nENCODING 1035\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n40\n40\n70\n48\n48\n48\n48\n00\n00\nENDCHAR\nSTARTCHAR afii10061\nENCODING 1036\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n20\n88\n90\nA0\nC0\nC0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR uni040D\nENCODING 1037\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n88\n88\n98\nA8\nC8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10062\nENCODING 1038\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n88\n88\n88\n88\n78\n08\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10145\nENCODING 1039\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\n88\n88\nF8\n20\n20\nENDCHAR\nSTARTCHAR afii10017\nENCODING 1040\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10018\nENCODING 1041\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n80\n80\nF0\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii10019\nENCODING 1042\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\nF0\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii10020\nENCODING 1043\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR afii10021\nENCODING 1044\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n38\n48\n48\n48\n48\n48\n48\nFC\n84\n00\nENDCHAR\nSTARTCHAR afii10022\nENCODING 1045\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR afii10024\nENCODING 1046\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA8\nA8\nA8\n70\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR afii10025\nENCODING 1047\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n30\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10026\nENCODING 1048\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n98\nA8\nC8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10027\nENCODING 1049\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n88\n88\n98\nA8\nC8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10028\nENCODING 1050\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n90\nA0\nC0\nC0\nA0\n90\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10029\nENCODING 1051\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n38\n48\n48\n48\n48\n48\n48\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10030\nENCODING 1052\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\nD8\nA8\nA8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10031\nENCODING 1053\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\nF8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10032\nENCODING 1054\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10033\nENCODING 1055\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n88\n88\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10034\nENCODING 1056\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\nF0\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR afii10035\nENCODING 1057\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n80\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10036\nENCODING 1058\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR afii10037\nENCODING 1059\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n78\n08\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10038\nENCODING 1060\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n70\nA8\nA8\nA8\nA8\nA8\nA8\n70\n20\n00\nENDCHAR\nSTARTCHAR afii10039\nENCODING 1061\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n20\n20\n50\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10040\nENCODING 1062\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\n88\n88\n7C\n04\n04\nENDCHAR\nSTARTCHAR afii10041\nENCODING 1063\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n78\n08\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR afii10042\nENCODING 1064\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA8\nA8\nA8\nA8\nA8\nA8\nA8\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10043\nENCODING 1065\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA8\nA8\nA8\nA8\nA8\nA8\nA8\n7C\n04\n04\nENDCHAR\nSTARTCHAR afii10044\nENCODING 1066\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC0\n40\n70\n48\n48\n48\n48\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10045\nENCODING 1067\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\nA8\nA8\nA8\nC8\n00\n00\nENDCHAR\nSTARTCHAR afii10046\nENCODING 1068\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n70\n48\n48\n48\n48\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10047\nENCODING 1069\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n38\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10048\nENCODING 1070\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n90\nA8\nA8\nA8\nE8\nA8\nA8\n90\n00\n00\nENDCHAR\nSTARTCHAR afii10049\nENCODING 1071\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n88\n88\n88\n78\n28\n48\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10065\nENCODING 1072\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10066\nENCODING 1073\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n80\nF0\n88\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii10067\nENCODING 1074\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n90\nF0\n88\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii10068\nENCODING 1075\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR afii10069\nENCODING 1076\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR afii10070\nENCODING 1077\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10072\nENCODING 1078\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA8\nA8\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR afii10073\nENCODING 1079\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n30\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10074\nENCODING 1080\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10075\nENCODING 1081\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10076\nENCODING 1082\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n48\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR afii10077\nENCODING 1083\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n38\n48\n48\n48\n48\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10078\nENCODING 1084\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\nD8\nA8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10079\nENCODING 1085\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10080\nENCODING 1086\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10081\nENCODING 1087\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10082\nENCODING 1088\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\nF0\n80\n80\nENDCHAR\nSTARTCHAR afii10083\nENCODING 1089\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n80\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10084\nENCODING 1090\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR afii10085\nENCODING 1091\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR afii10086\nENCODING 1092\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n70\nA8\nA8\nA8\nA8\n70\n20\n00\nENDCHAR\nSTARTCHAR afii10087\nENCODING 1093\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n50\n20\n20\n50\n88\n00\n00\nENDCHAR\nSTARTCHAR afii10088\nENCODING 1094\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n7C\n04\n04\nENDCHAR\nSTARTCHAR afii10089\nENCODING 1095\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n78\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR afii10090\nENCODING 1096\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA8\nA8\nA8\nA8\nA8\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10091\nENCODING 1097\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA8\nA8\nA8\nA8\nA8\n7C\n04\n04\nENDCHAR\nSTARTCHAR afii10092\nENCODING 1098\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nC0\n40\n70\n48\n48\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10093\nENCODING 1099\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\nC8\nA8\nA8\nC8\n00\n00\nENDCHAR\nSTARTCHAR afii10094\nENCODING 1100\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n40\n40\n70\n48\n48\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10095\nENCODING 1101\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n38\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10096\nENCODING 1102\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n90\nA8\nA8\nE8\nA8\n90\n00\n00\nENDCHAR\nSTARTCHAR afii10097\nENCODING 1103\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n88\n88\n78\n28\n48\n00\n00\nENDCHAR\nSTARTCHAR uni0450\nENCODING 1104\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10071\nENCODING 1105\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10099\nENCODING 1106\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\nF0\n40\n70\n48\n48\n48\n48\n08\n10\nENDCHAR\nSTARTCHAR afii10100\nENCODING 1107\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n20\nF8\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR afii10101\nENCODING 1108\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nE0\n80\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10102\nENCODING 1109\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n80\n70\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii10103\nENCODING 1110\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n00\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10104\nENCODING 1111\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10105\nENCODING 1112\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n08\n08\n00\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR afii10106\nENCODING 1113\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n60\nA0\nB0\nA8\nA8\nB0\n00\n00\nENDCHAR\nSTARTCHAR afii10107\nENCODING 1114\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA0\nA0\nF0\nA8\nA8\nB0\n00\n00\nENDCHAR\nSTARTCHAR afii10108\nENCODING 1115\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\nF0\n40\n70\n48\n48\n48\n48\n00\n00\nENDCHAR\nSTARTCHAR afii10109\nENCODING 1116\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n10\n48\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR uni045D\nENCODING 1117\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n20\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR afii10110\nENCODING 1118\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR afii10193\nENCODING 1119\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\nF8\n20\n20\nENDCHAR\nSTARTCHAR afii10146\nENCODING 1122\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\nF0\n40\n70\n48\n48\n48\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10194\nENCODING 1123\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\nE0\n40\n70\n48\n48\n70\n00\n00\nENDCHAR\nSTARTCHAR uni046A\nENCODING 1130\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n88\n50\n20\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni046B\nENCODING 1131\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n50\n20\n70\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR afii10050\nENCODING 1168\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\nF8\n80\n80\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR afii10098\nENCODING 1169\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n08\nF8\n80\n80\n80\n80\n80\n00\n00\nENDCHAR\nSTARTCHAR uni0492\nENCODING 1170\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n7C\n40\n40\n40\nF0\n40\n40\n40\n00\n00\nENDCHAR\nSTARTCHAR uni0493\nENCODING 1171\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n40\n40\nF0\n40\n40\n00\n00\nENDCHAR\nSTARTCHAR uni0494\nENCODING 1172\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\n80\nF0\n88\n88\n88\n08\n10\nENDCHAR\nSTARTCHAR uni0495\nENCODING 1173\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n80\n80\nE0\n90\n90\n10\n20\nENDCHAR\nSTARTCHAR uni0496\nENCODING 1174\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA8\nA8\nA8\n70\n70\nA8\nA8\nAC\n04\n04\nENDCHAR\nSTARTCHAR uni0497\nENCODING 1175\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA8\nA8\n70\nA8\nA8\nAC\n04\n04\nENDCHAR\nSTARTCHAR uni0498\nENCODING 1176\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n30\n08\n08\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR uni0499\nENCODING 1177\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n30\n08\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR uni049A\nENCODING 1178\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n90\nA0\nC0\nC0\nA0\n90\n8C\n04\n04\nENDCHAR\nSTARTCHAR uni049B\nENCODING 1179\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n48\n50\n60\n60\n50\n4C\n04\n04\nENDCHAR\nSTARTCHAR uni049C\nENCODING 1180\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n84\nA8\nB0\nE0\nE0\nB0\nA8\n84\n00\n00\nENDCHAR\nSTARTCHAR uni049D\nENCODING 1181\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nA8\nB0\nE0\nE0\nB0\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni04A0\nENCODING 1184\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC4\n48\n50\n60\n60\n50\n48\n44\n00\n00\nENDCHAR\nSTARTCHAR uni04A1\nENCODING 1185\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nC8\n50\n60\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR uni04A2\nENCODING 1186\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\nF8\n88\n88\n88\n8C\n04\n04\nENDCHAR\nSTARTCHAR uni04A3\nENCODING 1187\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\nF8\n88\n88\n8C\n04\n04\nENDCHAR\nSTARTCHAR uni04A4\nENCODING 1188\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n9C\n90\n90\nF0\n90\n90\n90\n90\n00\n00\nENDCHAR\nSTARTCHAR uni04A5\nENCODING 1189\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n9C\n90\nF0\n90\n90\n90\n00\n00\nENDCHAR\nSTARTCHAR uni04AA\nENCODING 1194\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n80\n80\n80\n80\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR uni04AB\nENCODING 1195\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n80\n80\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR uni04AE\nENCODING 1198\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni04AF\nENCODING 1199\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n50\n50\n20\n20\n20\nENDCHAR\nSTARTCHAR uni04B0\nENCODING 1200\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n50\n20\n70\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni04B1\nENCODING 1201\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n50\n50\n20\n70\n20\nENDCHAR\nSTARTCHAR uni04B2\nENCODING 1202\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n20\n20\n50\n88\n8C\n04\n04\nENDCHAR\nSTARTCHAR uni04B3\nENCODING 1203\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n50\n20\n20\n50\n8C\n04\n04\nENDCHAR\nSTARTCHAR uni04B6\nENCODING 1206\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n78\n08\n08\n0C\n04\n04\nENDCHAR\nSTARTCHAR uni04B7\nENCODING 1207\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n78\n08\n0C\n04\n04\nENDCHAR\nSTARTCHAR uni04B8\nENCODING 1208\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nA8\nA8\n78\n28\n28\n08\n00\n00\nENDCHAR\nSTARTCHAR uni04B9\nENCODING 1209\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\nA8\nA8\n78\n28\n08\n00\n00\nENDCHAR\nSTARTCHAR uni04BA\nENCODING 1210\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\n80\nF0\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni04BB\nENCODING 1211\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n80\n80\nF0\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni04C0\nENCODING 1216\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04C1\nENCODING 1217\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nA8\nA8\nA8\n70\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni04C2\nENCODING 1218\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\nA8\nA8\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni04CF\nENCODING 1231\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n20\n20\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04D0\nENCODING 1232\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni04D1\nENCODING 1233\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uni04D2\nENCODING 1234\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n88\n88\nF8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni04D3\nENCODING 1235\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n08\n78\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uni04D4\nENCODING 1236\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n7C\n90\n90\nFC\n90\n90\n90\n9C\n00\n00\nENDCHAR\nSTARTCHAR uni04D5\nENCODING 1237\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n28\n68\nB0\nA0\n78\n00\n00\nENDCHAR\nSTARTCHAR uni04D6\nENCODING 1238\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n20\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni04D7\nENCODING 1239\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n20\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR uni04D8\nENCODING 1240\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n08\n08\nF8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii10846\nENCODING 1241\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n08\nF8\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04DA\nENCODING 1242\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n08\n08\nF8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04DB\nENCODING 1243\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\n08\nF8\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04DC\nENCODING 1244\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\nA8\nA8\nA8\n70\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni04DD\nENCODING 1245\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\nA8\nA8\n70\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni04DE\nENCODING 1246\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n08\n30\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04DF\nENCODING 1247\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\n30\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04E2\nENCODING 1250\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n88\n88\n98\nA8\nC8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni04E3\nENCODING 1251\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uni04E4\nENCODING 1252\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\n98\nA8\nC8\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni04E5\nENCODING 1253\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\n88\n88\n88\n78\n00\n00\nENDCHAR\nSTARTCHAR uni04E6\nENCODING 1254\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04E7\nENCODING 1255\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04E8\nENCODING 1256\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\nF8\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04E9\nENCODING 1257\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nF8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04EA\nENCODING 1258\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n88\n88\nF8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04EB\nENCODING 1259\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\nF8\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04EC\nENCODING 1260\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n70\n88\n08\n38\n08\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04ED\nENCODING 1261\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n70\n88\n38\n08\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04EE\nENCODING 1262\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n70\n00\n88\n88\n88\n88\n78\n08\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04EF\nENCODING 1263\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n00\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR uni04F0\nENCODING 1264\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\n88\n88\n78\n08\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04F1\nENCODING 1265\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR uni04F2\nENCODING 1266\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n88\n88\n88\n88\n78\n08\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR uni04F3\nENCODING 1267\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR uni04F4\nENCODING 1268\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\n88\n88\n78\n08\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR uni04F5\nENCODING 1269\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\n88\n78\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR uni04F8\nENCODING 1272\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n88\n88\nC8\nA8\nA8\nA8\nA8\nC8\n00\n00\nENDCHAR\nSTARTCHAR uni04F9\nENCODING 1273\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n88\n88\nC8\nA8\nA8\nC8\n00\n00\nENDCHAR\nSTARTCHAR afii57664\nENCODING 1488\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n50\n20\n50\n90\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii57665\nENCODING 1489\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n08\n08\n08\n08\n08\n08\nFC\n00\n00\nENDCHAR\nSTARTCHAR afii57666\nENCODING 1490\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n10\n10\n10\n10\n30\n48\n88\n00\n00\nENDCHAR\nSTARTCHAR afii57667\nENCODING 1491\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nFC\n08\n08\n08\n08\n08\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR afii57668\nENCODING 1492\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n08\n88\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii57669\nENCODING 1493\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC0\n20\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR afii57670\nENCODING 1494\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n10\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR afii57671\nENCODING 1495\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii57672\nENCODING 1496\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n90\n98\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR afii57673\nENCODING 1497\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC0\n20\n20\n20\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii57674\nENCODING 1498\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n08\n08\n08\n08\n08\n08\n08\n08\n08\nENDCHAR\nSTARTCHAR afii57675\nENCODING 1499\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n08\n08\n08\n08\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii57676\nENCODING 1500\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n80\nF8\n08\n08\n08\n10\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR afii57677\nENCODING 1501\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n88\n88\n88\n88\nF8\n00\n00\nENDCHAR\nSTARTCHAR afii57678\nENCODING 1502\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nB0\nC8\n88\n88\n88\n88\n88\n98\n00\n00\nENDCHAR\nSTARTCHAR afii57679\nENCODING 1503\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC0\n20\n20\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR afii57680\nENCODING 1504\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n10\n10\n10\n10\n10\n10\n70\n00\n00\nENDCHAR\nSTARTCHAR afii57681\nENCODING 1505\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n48\n48\n48\n48\n48\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR afii57682\nENCODING 1506\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n48\n48\n48\n30\nC0\n00\n00\nENDCHAR\nSTARTCHAR afii57683\nENCODING 1507\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n48\n08\n08\n08\n08\n08\n08\nENDCHAR\nSTARTCHAR afii57684\nENCODING 1508\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n88\n88\n48\n08\n08\n08\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii57685\nENCODING 1509\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n48\n50\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR afii57686\nENCODING 1510\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n48\n50\n20\n20\n10\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii57687\nENCODING 1511\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n08\n88\n88\n90\nA0\nA0\nA0\n80\n80\nENDCHAR\nSTARTCHAR afii57688\nENCODING 1512\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n08\n08\n08\n08\n08\n08\n08\n00\n00\nENDCHAR\nSTARTCHAR afii57689\nENCODING 1513\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nA8\nA8\nA8\nA8\nC8\n88\n88\nF0\n00\n00\nENDCHAR\nSTARTCHAR afii57690\nENCODING 1514\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n48\n48\n48\n48\n48\n48\n88\n00\n00\nENDCHAR\nSTARTCHAR uni1E0C\nENCODING 7692\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nE0\n90\n88\n88\n88\n88\n90\nE0\n20\n20\nENDCHAR\nSTARTCHAR uni1E0D\nENCODING 7693\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n08\n78\n88\n88\n88\n88\n78\n20\n20\nENDCHAR\nSTARTCHAR Klinebelow\nENCODING 7732\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n90\nA0\nC0\nC0\nA0\n90\n88\n00\n70\nENDCHAR\nSTARTCHAR klinebelow\nENCODING 7733\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n48\n50\n60\n60\n50\n48\n00\n70\nENDCHAR\nSTARTCHAR uni1E36\nENCODING 7734\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\n80\n80\n80\n80\n80\nF8\n20\n20\nENDCHAR\nSTARTCHAR uni1E37\nENCODING 7735\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n60\n20\n20\n20\n20\n20\n20\n70\n20\n20\nENDCHAR\nSTARTCHAR uni1E40\nENCODING 7744\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n88\nD8\nA8\nA8\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni1E41\nENCODING 7745\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\nF0\nA8\nA8\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni1E42\nENCODING 7746\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\nD8\nA8\nA8\n88\n88\n88\n88\n20\n20\nENDCHAR\nSTARTCHAR uni1E43\nENCODING 7747\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\nA8\nA8\nA8\nA8\nA8\n10\n10\nENDCHAR\nSTARTCHAR uni1E44\nENCODING 7748\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n88\n88\nC8\nA8\n98\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni1E45\nENCODING 7749\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni1E46\nENCODING 7750\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nC8\nA8\n98\n88\n88\n88\n20\n20\nENDCHAR\nSTARTCHAR uni1E47\nENCODING 7751\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n88\n88\n88\n88\n88\n20\n20\nENDCHAR\nSTARTCHAR uni1E6C\nENCODING 7788\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n20\n20\n20\n20\n20\n20\n10\n10\nENDCHAR\nSTARTCHAR uni1E6D\nENCODING 7789\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\n20\n20\n20\n20\n18\n10\n10\nENDCHAR\nSTARTCHAR Edotbelow\nENCODING 7864\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n80\n80\nF0\n80\n80\n80\nF8\n20\n20\nENDCHAR\nSTARTCHAR edotbelow\nENCODING 7865\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\nF8\n80\n80\n78\n20\n20\nENDCHAR\nSTARTCHAR Etilde\nENCODING 7868\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\nF8\n80\n80\nF0\n80\n80\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR etilde\nENCODING 7869\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n70\n88\nF8\n80\n80\n78\n00\n00\nENDCHAR\nSTARTCHAR uni1ECA\nENCODING 7882\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n20\n20\n20\n20\n20\n20\n70\n20\n20\nENDCHAR\nSTARTCHAR uni1ECB\nENCODING 7883\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n00\n60\n20\n20\n20\n20\n70\n20\n20\nENDCHAR\nSTARTCHAR Odotbelow\nENCODING 7884\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR odotbelow\nENCODING 7885\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR uni1EE4\nENCODING 7908\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\n88\n88\n70\n20\n20\nENDCHAR\nSTARTCHAR uni1EE5\nENCODING 7909\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n78\n20\n20\nENDCHAR\nSTARTCHAR Ytilde\nENCODING 7928\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n28\n50\n88\n88\n50\n50\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR ytilde\nENCODING 7929\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n28\n50\n88\n88\n88\n88\n88\n78\n08\n70\nENDCHAR\nSTARTCHAR uni2000\nENCODING 8192\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2001\nENCODING 8193\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR enspace\nENCODING 8194\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2003\nENCODING 8195\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2004\nENCODING 8196\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2005\nENCODING 8197\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2006\nENCODING 8198\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2007\nENCODING 8199\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2008\nENCODING 8200\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2009\nENCODING 8201\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni200A\nENCODING 8202\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni200B\nENCODING 8203\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii61664\nENCODING 8204\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii301\nENCODING 8205\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii299\nENCODING 8206\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii300\nENCODING 8207\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR hyphentwo\nENCODING 8208\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n78\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2011\nENCODING 8209\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n78\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR figuredash\nENCODING 8210\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nF8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR endash\nENCODING 8211\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nF8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR emdash\nENCODING 8212\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nF8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR afii00208\nENCODING 8213\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nF8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR dblverticalbar\nENCODING 8214\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n50\n50\n50\n50\n50\n50\n00\n00\nENDCHAR\nSTARTCHAR underscoredbl\nENCODING 8215\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\nF8\n00\nF8\nENDCHAR\nSTARTCHAR quoteleft\nENCODING 8216\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n10\n20\n20\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR quoteright\nENCODING 8217\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n40\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR quotesinglbase\nENCODING 8218\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n20\n20\n40\n00\nENDCHAR\nSTARTCHAR quotereversed\nENCODING 8219\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n10\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR quotedblleft\nENCODING 8220\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n28\n50\n50\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR quotedblright\nENCODING 8221\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n28\n28\n50\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR quotedblbase\nENCODING 8222\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n50\n50\nA0\n00\nENDCHAR\nSTARTCHAR uni201F\nENCODING 8223\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\nA0\nA0\n50\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR dagger\nENCODING 8224\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\n20\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR daggerdbl\nENCODING 8225\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\n20\n20\n20\n20\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR bullet\nENCODING 8226\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n30\n78\n78\n30\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR ellipsis\nENCODING 8230\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR perthousand\nENCODING 8240\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n44\nA8\n50\n20\n40\nA8\n54\n28\n00\n00\nENDCHAR\nSTARTCHAR minute\nENCODING 8242\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\n20\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR second\nENCODING 8243\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n50\n50\n50\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR guilsinglleft\nENCODING 8249\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n10\n20\n40\n20\n10\n08\n00\n00\nENDCHAR\nSTARTCHAR guilsinglright\nENCODING 8250\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n20\n10\n08\n10\n20\n40\n00\n00\nENDCHAR\nSTARTCHAR exclamdbl\nENCODING 8252\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n50\n50\n50\n00\n50\n50\n00\n00\nENDCHAR\nSTARTCHAR overline\nENCODING 8254\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nF8\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2070\nENCODING 8304\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n48\n48\n48\n30\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2071\nENCODING 8305\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n00\n60\n20\n20\n70\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2074\nENCODING 8308\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n08\n18\n28\n78\n08\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2075\nENCODING 8309\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n70\n40\n70\n08\n70\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2076\nENCODING 8310\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n40\n70\n48\n30\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2077\nENCODING 8311\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n78\n08\n10\n20\n20\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2078\nENCODING 8312\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n48\n30\n48\n30\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2079\nENCODING 8313\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n48\n38\n08\n30\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni207A\nENCODING 8314\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n20\nF8\n20\n20\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni207B\nENCODING 8315\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n78\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni207C\nENCODING 8316\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n00\n78\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni207D\nENCODING 8317\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n10\n20\n20\n20\n10\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni207E\nENCODING 8318\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n20\n10\n10\n10\n20\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR nsuperior\nENCODING 8319\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n70\n48\n48\n48\n48\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2080\nENCODING 8320\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n48\n48\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR uni2081\nENCODING 8321\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n10\n30\n10\n10\n38\n00\n00\nENDCHAR\nSTARTCHAR uni2082\nENCODING 8322\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n48\n10\n20\n78\n00\n00\nENDCHAR\nSTARTCHAR uni2083\nENCODING 8323\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n70\n08\n30\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR uni2084\nENCODING 8324\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n08\n18\n28\n78\n08\n00\n00\nENDCHAR\nSTARTCHAR uni2085\nENCODING 8325\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n70\n40\n70\n08\n70\n00\n00\nENDCHAR\nSTARTCHAR uni2086\nENCODING 8326\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n40\n70\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR uni2087\nENCODING 8327\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n78\n08\n10\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni2088\nENCODING 8328\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n48\n30\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR uni2089\nENCODING 8329\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n48\n38\n08\n30\n00\n00\nENDCHAR\nSTARTCHAR uni208A\nENCODING 8330\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n20\n20\nF8\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni208B\nENCODING 8331\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n78\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni208C\nENCODING 8332\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n78\n00\n78\n00\n00\n00\nENDCHAR\nSTARTCHAR uni208D\nENCODING 8333\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n10\n20\n20\n20\n10\n00\n00\nENDCHAR\nSTARTCHAR uni208E\nENCODING 8334\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n20\n10\n10\n10\n20\n00\n00\nENDCHAR\nSTARTCHAR uni2090\nENCODING 8336\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n08\n38\n48\n38\n00\n00\nENDCHAR\nSTARTCHAR uni2091\nENCODING 8337\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n48\n78\n40\n38\n00\n00\nENDCHAR\nSTARTCHAR uni2092\nENCODING 8338\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n48\n48\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR uni2093\nENCODING 8339\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n88\n50\n20\n50\n88\n00\n00\nENDCHAR\nSTARTCHAR uni2094\nENCODING 8340\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n70\n08\n78\n48\n30\n00\n00\nENDCHAR\nSTARTCHAR uni2095\nENCODING 8341\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n40\n70\n48\n48\n48\n48\n00\n00\nENDCHAR\nSTARTCHAR uni2096\nENCODING 8342\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n40\n48\n50\n60\n50\n48\n00\n00\nENDCHAR\nSTARTCHAR uni2097\nENCODING 8343\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n60\n20\n20\n20\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR uni2098\nENCODING 8344\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nF0\nA8\nA8\nA8\nA8\n00\n00\nENDCHAR\nSTARTCHAR uni209A\nENCODING 8346\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n70\n48\n48\n48\n70\n40\n40\nENDCHAR\nSTARTCHAR peseta\nENCODING 8359\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC0\nA0\nA0\nC8\n9C\n88\n88\n84\n00\n00\nENDCHAR\nSTARTCHAR afii57636\nENCODING 8362\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nC8\nA8\nA8\n88\n88\nA8\nA8\nB0\n00\n00\nENDCHAR\nSTARTCHAR Euro\nENCODING 8364\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n38\n44\nF0\n40\nF0\n44\n38\n00\n00\nENDCHAR\nSTARTCHAR uni20AE\nENCODING 8366\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n20\n30\n60\n30\n60\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni2102\nENCODING 8450\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\nA8\nA0\nA0\nA0\nA0\nA8\n70\n00\n00\nENDCHAR\nSTARTCHAR uni210E\nENCODING 8462\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\n80\nF0\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni210F\nENCODING 8463\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\nF0\n40\n70\n48\n48\n48\n48\n00\n00\nENDCHAR\nSTARTCHAR uni2115\nENCODING 8469\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\nC8\nA8\nD8\nA8\n98\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR afii61352\nENCODING 8470\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n94\n94\nD0\nF0\nF0\nB4\n90\n94\n00\n00\nENDCHAR\nSTARTCHAR uni211A\nENCODING 8474\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\nC8\nA8\nA8\nA8\nA8\nA8\n70\n18\n00\nENDCHAR\nSTARTCHAR uni211D\nENCODING 8477\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\nA8\nA8\nA8\nB0\nB0\nA8\nE4\n00\n00\nENDCHAR\nSTARTCHAR trademark\nENCODING 8482\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF4\n5C\n54\n54\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2124\nENCODING 8484\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n18\n28\n50\nA0\nC0\n80\nF8\n00\n00\nENDCHAR\nSTARTCHAR Ohm\nENCODING 8486\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n50\nD8\n00\n00\nENDCHAR\nSTARTCHAR aleph\nENCODING 8501\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n48\n48\n24\n68\n90\n90\n88\n48\n00\n00\nENDCHAR\nSTARTCHAR arrowleft\nENCODING 8592\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n60\nFC\n60\n20\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowup\nENCODING 8593\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nF8\n20\n20\n20\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR arrowright\nENCODING 8594\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n10\n18\nFC\n18\n10\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowdown\nENCODING 8595\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n20\n20\n20\nF8\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR arrowboth\nENCODING 8596\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\nCC\nFC\nCC\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowupdn\nENCODING 8597\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nF8\n20\n20\nF8\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR uni21A4\nENCODING 8612\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n24\n64\nFC\n64\n24\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni21A6\nENCODING 8614\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n90\n98\nFC\n98\n90\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowupdnbse\nENCODING 8616\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nF8\n20\nF8\n70\n20\nF8\n00\n00\nENDCHAR\nSTARTCHAR carriagereturn\nENCODING 8629\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n08\n08\n28\n68\nF8\n60\n20\n00\n00\nENDCHAR\nSTARTCHAR uni21BB\nENCODING 8635\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n30\n50\n94\n84\n84\n84\n78\n00\n00\nENDCHAR\nSTARTCHAR uni21CB\nENCODING 8651\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n40\nFC\n00\nFC\n08\n10\n00\n00\n00\nENDCHAR\nSTARTCHAR uni21CC\nENCODING 8652\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n08\nFC\n00\nFC\n40\n20\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowdblleft\nENCODING 8656\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n7C\nE0\n7C\n20\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowdblup\nENCODING 8657\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nF8\n50\n50\n50\n50\n50\n00\n00\nENDCHAR\nSTARTCHAR arrowdblright\nENCODING 8658\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n10\nF8\n1C\nF8\n10\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR arrowdbldown\nENCODING 8659\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n50\n50\n50\nF8\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR arrowdblboth\nENCODING 8660\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\nFC\nCC\nFC\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni21D5\nENCODING 8661\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\nF8\n50\n50\nF8\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR universal\nENCODING 8704\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\nF8\n50\n50\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR existential\nENCODING 8707\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nF8\n08\n08\nF8\n08\n08\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni2204\nENCODING 8708\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\nF8\n28\n28\nF8\n48\n48\nF8\n80\n00\nENDCHAR\nSTARTCHAR emptyset\nENCODING 8709\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n70\n98\nA8\nA8\nC8\n70\n80\n00\n00\nENDCHAR\nSTARTCHAR increment\nENCODING 8710\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n50\n50\n88\n88\n88\nF8\n00\n00\nENDCHAR\nSTARTCHAR gradient\nENCODING 8711\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n88\n88\n88\n50\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR element\nENCODING 8712\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n38\n40\n80\nF8\n80\n40\n38\n00\n00\nENDCHAR\nSTARTCHAR notelement\nENCODING 8713\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n38\n50\n90\nF8\nA0\n60\n78\n40\n00\nENDCHAR\nSTARTCHAR uni220A\nENCODING 8714\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n78\n80\nF8\n80\n78\n00\n00\n00\nENDCHAR\nSTARTCHAR suchthat\nENCODING 8715\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nE0\n10\n08\nF8\n08\n10\nE0\n00\n00\nENDCHAR\nSTARTCHAR uni220C\nENCODING 8716\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n80\nE0\n50\n48\nF8\n28\n30\nF0\n10\n00\nENDCHAR\nSTARTCHAR uni220D\nENCODING 8717\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n08\nF8\n08\nF0\n00\n00\n00\nENDCHAR\nSTARTCHAR minus\nENCODING 8722\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nF8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2213\nENCODING 8723\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nF8\n00\n20\n20\nF8\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni2214\nENCODING 8724\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n00\n20\n20\nF8\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni2215\nENCODING 8725\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n08\n10\n20\n40\n80\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2216\nENCODING 8726\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n80\n40\n20\n10\n08\n00\n00\n00\nENDCHAR\nSTARTCHAR bulletoperator\nENCODING 8729\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n30\n78\n30\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR radical\nENCODING 8730\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n0C\n08\n08\n08\n88\n88\n48\n28\n18\n00\n00\nENDCHAR\nSTARTCHAR infinity\nENCODING 8734\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n50\nA8\nA8\nA8\n50\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR orthogonal\nENCODING 8735\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n80\n80\n80\n80\nF8\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2225\nENCODING 8741\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n50\n50\n50\n50\n50\n50\n50\n50\n00\n00\nENDCHAR\nSTARTCHAR logicaland\nENCODING 8743\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n20\n50\n50\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR logicalor\nENCODING 8744\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n50\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR intersection\nENCODING 8745\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n70\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR union\nENCODING 8746\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR approxequal\nENCODING 8776\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n68\nB0\n00\n68\nB0\n00\n00\n00\nENDCHAR\nSTARTCHAR notequal\nENCODING 8800\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\nF8\n20\n40\nF8\n80\n00\n00\n00\nENDCHAR\nSTARTCHAR equivalence\nENCODING 8801\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n00\nF8\n00\nF8\n00\n00\n00\nENDCHAR\nSTARTCHAR lessequal\nENCODING 8804\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n10\n20\n40\n80\n40\n20\n10\n00\nF8\n00\n00\nENDCHAR\nSTARTCHAR greaterequal\nENCODING 8805\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n40\n20\n10\n08\n10\n20\n40\n00\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni226A\nENCODING 8810\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n14\n28\n50\nA0\n50\n28\n14\n00\n00\nENDCHAR\nSTARTCHAR uni226B\nENCODING 8811\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nA0\n50\n28\n14\n28\n50\nA0\n00\n00\nENDCHAR\nSTARTCHAR propersubset\nENCODING 8834\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n78\n80\n80\n80\n80\n78\n00\n00\n00\nENDCHAR\nSTARTCHAR propersuperset\nENCODING 8835\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nF0\n08\n08\n08\n08\nF0\n00\n00\n00\nENDCHAR\nSTARTCHAR reflexsubset\nENCODING 8838\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n80\n80\n80\n80\n78\n00\nF8\n00\n00\nENDCHAR\nSTARTCHAR reflexsuperset\nENCODING 8839\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF0\n08\n08\n08\n08\nF0\n00\nF8\n00\n00\nENDCHAR\nSTARTCHAR perpendicular\nENCODING 8869\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n20\n20\n20\n20\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni22C2\nENCODING 8898\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n88\n88\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uni22C3\nENCODING 8899\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n88\n88\n88\n88\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR uni2300\nENCODING 8960\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n08\n70\n98\nA8\nA8\nC8\n70\n80\n00\n00\nENDCHAR\nSTARTCHAR house\nENCODING 8962\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n20\n50\n88\n88\n88\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni2308\nENCODING 8968\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n40\n40\n40\n40\n40\n40\n40\n00\n00\nENDCHAR\nSTARTCHAR uni2309\nENCODING 8969\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n10\n10\n10\n10\n10\n10\n10\n00\n00\nENDCHAR\nSTARTCHAR uni230A\nENCODING 8970\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n40\n40\n40\n40\n40\n40\n40\n70\n00\n00\nENDCHAR\nSTARTCHAR uni230B\nENCODING 8971\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n10\n10\n10\n10\n10\n10\n70\n00\n00\nENDCHAR\nSTARTCHAR revlogicalnot\nENCODING 8976\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF8\n80\n80\n80\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2319\nENCODING 8985\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n80\n80\n80\nF8\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR integraltp\nENCODING 8992\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n10\n28\n28\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR integralbt\nENCODING 8993\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n20\n20\nA0\nA0\n40\n00\n00\nENDCHAR\nSTARTCHAR uni239B\nENCODING 9115\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n10\n10\n20\n20\n20\n40\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR uni239C\nENCODING 9116\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR uni239D\nENCODING 9117\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n40\n40\n40\n40\n20\n20\n20\n10\n10\n08\nENDCHAR\nSTARTCHAR uni239E\nENCODING 9118\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n20\n20\n10\n10\n10\n08\n08\n08\n08\n08\n08\nENDCHAR\nSTARTCHAR uni239F\nENCODING 9119\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\nENDCHAR\nSTARTCHAR uni23A0\nENCODING 9120\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n08\n08\n08\n08\n10\n10\n10\n20\n20\n40\nENDCHAR\nSTARTCHAR uni23A1\nENCODING 9121\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n78\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR uni23A2\nENCODING 9122\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\nENDCHAR\nSTARTCHAR uni23A3\nENCODING 9123\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n40\n78\nENDCHAR\nSTARTCHAR uni23A4\nENCODING 9124\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n78\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\nENDCHAR\nSTARTCHAR uni23A5\nENCODING 9125\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\nENDCHAR\nSTARTCHAR uni23A6\nENCODING 9126\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n08\n78\nENDCHAR\nSTARTCHAR uni23A7\nENCODING 9127\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n0C\n10\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni23A8\nENCODING 9128\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nC0\nC0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni23A9\nENCODING 9129\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n10\n0C\nENDCHAR\nSTARTCHAR uni23AB\nENCODING 9131\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nC0\n20\n10\n10\n10\n10\n10\n10\n10\n10\n10\n10\nENDCHAR\nSTARTCHAR uni23AC\nENCODING 9132\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n10\n10\n10\n10\n0C\n0C\n10\n10\n10\n10\n10\nENDCHAR\nSTARTCHAR uni23AD\nENCODING 9133\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n10\n10\n10\n10\n10\n10\n10\n10\n10\n10\n20\nC0\nENDCHAR\nSTARTCHAR uni23AE\nENCODING 9134\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni23AF\nENCODING 9135\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni23BA\nENCODING 9146\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni23BB\nENCODING 9147\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nFC\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni23BC\nENCODING 9148\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\nFC\n00\n00\n00\nENDCHAR\nSTARTCHAR uni23BD\nENCODING 9149\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nFC\nENDCHAR\nSTARTCHAR uni23D0\nENCODING 9168\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2409\nENCODING 9225\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n90\n90\nF0\n90\n90\n00\n7C\n10\n10\n10\n10\n00\nENDCHAR\nSTARTCHAR uni240A\nENCODING 9226\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n80\n80\n80\nF0\n00\n3C\n20\n38\n20\n20\n00\nENDCHAR\nSTARTCHAR uni240B\nENCODING 9227\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n88\n88\n88\n50\n20\n00\n7C\n10\n10\n10\n10\n00\nENDCHAR\nSTARTCHAR uni240C\nENCODING 9228\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nF0\n80\nE0\n80\n80\n00\n3C\n20\n38\n20\n20\n00\nENDCHAR\nSTARTCHAR uni240D\nENCODING 9229\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n60\n90\n80\n90\n60\n00\n38\n24\n38\n28\n24\n00\nENDCHAR\nSTARTCHAR uni2424\nENCODING 9252\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n90\nD0\nB0\n90\n90\n00\n20\n20\n20\n20\n3C\n00\nENDCHAR\nSTARTCHAR SF100000\nENCODING 9472\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2501\nENCODING 9473\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nFC\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF110000\nENCODING 9474\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2503\nENCODING 9475\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n30\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2508\nENCODING 9480\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nA8\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2509\nENCODING 9481\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nA8\nA8\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni250A\nENCODING 9482\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n00\n20\n20\n00\n20\n20\n00\n20\n20\n00\nENDCHAR\nSTARTCHAR uni250B\nENCODING 9483\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n00\n30\n30\n00\n30\n30\n00\n30\n30\n00\nENDCHAR\nSTARTCHAR SF010000\nENCODING 9484\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n3C\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni250D\nENCODING 9485\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n3C\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni250E\nENCODING 9486\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n3C\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni250F\nENCODING 9487\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n3C\n3C\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR SF030000\nENCODING 9488\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nE0\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2511\nENCODING 9489\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nE0\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2512\nENCODING 9490\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nF0\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2513\nENCODING 9491\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nF0\nF0\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR SF020000\nENCODING 9492\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n3C\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2515\nENCODING 9493\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n3C\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2516\nENCODING 9494\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n3C\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2517\nENCODING 9495\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n3C\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF040000\nENCODING 9496\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nE0\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2519\nENCODING 9497\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nE0\nE0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni251A\nENCODING 9498\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nF0\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni251B\nENCODING 9499\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nF0\nF0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF080000\nENCODING 9500\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n3C\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni251D\nENCODING 9501\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n3C\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni251E\nENCODING 9502\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n3C\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni251F\nENCODING 9503\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n3C\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2520\nENCODING 9504\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n3C\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2521\nENCODING 9505\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n3C\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2522\nENCODING 9506\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n3C\n3C\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2523\nENCODING 9507\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n3C\n3C\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR SF090000\nENCODING 9508\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nE0\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2525\nENCODING 9509\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nE0\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2526\nENCODING 9510\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nF0\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2527\nENCODING 9511\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nF0\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2528\nENCODING 9512\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nF0\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2529\nENCODING 9513\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nF0\nF0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni252A\nENCODING 9514\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nF0\nF0\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni252B\nENCODING 9515\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nF0\nF0\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR SF060000\nENCODING 9516\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni252D\nENCODING 9517\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni252E\nENCODING 9518\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni252F\nENCODING 9519\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nFC\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2530\nENCODING 9520\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2531\nENCODING 9521\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nF0\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2532\nENCODING 9522\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n3C\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2533\nENCODING 9523\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nFC\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR SF070000\nENCODING 9524\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2535\nENCODING 9525\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\nE0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2536\nENCODING 9526\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2537\nENCODING 9527\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\nFC\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2538\nENCODING 9528\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2539\nENCODING 9529\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\nF0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni253A\nENCODING 9530\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni253B\nENCODING 9531\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\nFC\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF050000\nENCODING 9532\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni253D\nENCODING 9533\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni253E\nENCODING 9534\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni253F\nENCODING 9535\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\nFC\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2540\nENCODING 9536\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2541\nENCODING 9537\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2542\nENCODING 9538\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2543\nENCODING 9539\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2544\nENCODING 9540\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2545\nENCODING 9541\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\nF0\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2546\nENCODING 9542\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\n3C\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2547\nENCODING 9543\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\nFC\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2548\nENCODING 9544\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\nFC\nFC\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni2549\nENCODING 9545\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\nF0\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni254A\nENCODING 9546\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\n3C\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni254B\nENCODING 9547\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\nFC\nFC\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR SF430000\nENCODING 9552\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nFC\n00\nFC\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF240000\nENCODING 9553\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\n50\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF510000\nENCODING 9554\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n3C\n20\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR SF520000\nENCODING 9555\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n7C\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF390000\nENCODING 9556\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n7C\n40\n5C\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF220000\nENCODING 9557\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nE0\n20\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR SF210000\nENCODING 9558\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nF0\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF250000\nENCODING 9559\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nF0\n10\nD0\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF500000\nENCODING 9560\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n3C\n20\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF490000\nENCODING 9561\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\n7C\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF380000\nENCODING 9562\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n5C\n40\n7C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF280000\nENCODING 9563\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\nE0\n20\nE0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF270000\nENCODING 9564\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\nF0\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF260000\nENCODING 9565\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\nD0\n10\nF0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF360000\nENCODING 9566\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n3C\n20\n3C\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR SF370000\nENCODING 9567\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\n5C\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF420000\nENCODING 9568\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n5C\n40\n5C\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF190000\nENCODING 9569\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\nE0\n20\nE0\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR SF200000\nENCODING 9570\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\nD0\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF230000\nENCODING 9571\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\nD0\n10\nD0\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF470000\nENCODING 9572\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nFC\n00\nFC\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR SF480000\nENCODING 9573\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF410000\nENCODING 9574\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\nFC\n00\nDC\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF450000\nENCODING 9575\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\nFC\n00\nFC\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF460000\nENCODING 9576\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\nFC\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF400000\nENCODING 9577\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\nDC\n00\nFC\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR SF540000\nENCODING 9578\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\nFC\n20\nFC\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR SF530000\nENCODING 9579\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\n50\nFC\n50\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR SF440000\nENCODING 9580\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n50\n50\n50\n50\nDC\n00\nDC\n50\n50\n50\n50\n50\nENDCHAR\nSTARTCHAR uni256D\nENCODING 9581\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n0C\n10\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni256E\nENCODING 9582\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n80\n40\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni256F\nENCODING 9583\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n40\n80\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2570\nENCODING 9584\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n10\n0C\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2571\nENCODING 9585\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n04\n04\n08\n08\n10\n10\n20\n20\n40\n40\n80\n80\nENDCHAR\nSTARTCHAR uni2572\nENCODING 9586\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n80\n40\n40\n20\n20\n10\n10\n08\n08\n04\n04\nENDCHAR\nSTARTCHAR uni2573\nENCODING 9587\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n84\n84\n48\n48\n30\n30\n30\n30\n48\n48\n84\n84\nENDCHAR\nSTARTCHAR uni2574\nENCODING 9588\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nE0\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2575\nENCODING 9589\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n20\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2576\nENCODING 9590\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n3C\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2577\nENCODING 9591\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n20\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR uni2578\nENCODING 9592\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nE0\nE0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2579\nENCODING 9593\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n30\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni257A\nENCODING 9594\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n3C\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni257B\nENCODING 9595\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n30\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni257C\nENCODING 9596\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\n3C\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni257D\nENCODING 9597\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n20\n20\n20\n20\n20\n30\n30\n30\n30\n30\n30\n30\nENDCHAR\nSTARTCHAR uni257E\nENCODING 9598\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nE0\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni257F\nENCODING 9599\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n30\n30\n30\n30\n30\n30\n20\n20\n20\n20\n20\n20\nENDCHAR\nSTARTCHAR upblock\nENCODING 9600\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\nFC\nFC\nFC\nFC\nFC\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2581\nENCODING 9601\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nFC\nENDCHAR\nSTARTCHAR uni2582\nENCODING 9602\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR uni2583\nENCODING 9603\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR dnblock\nENCODING 9604\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR uni2585\nENCODING 9605\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR uni2586\nENCODING 9606\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR uni2587\nENCODING 9607\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR block\nENCODING 9608\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR uni2589\nENCODING 9609\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nENDCHAR\nSTARTCHAR uni258A\nENCODING 9610\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nENDCHAR\nSTARTCHAR uni258B\nENCODING 9611\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nF0\nENDCHAR\nSTARTCHAR lfblock\nENCODING 9612\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nE0\nE0\nE0\nE0\nE0\nE0\nE0\nE0\nE0\nE0\nE0\nE0\nENDCHAR\nSTARTCHAR uni258D\nENCODING 9613\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nC0\nENDCHAR\nSTARTCHAR uni258E\nENCODING 9614\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n80\n80\n80\n80\n80\n80\n80\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR uni258F\nENCODING 9615\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n80\n80\n80\n80\n80\n80\n80\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR rtblock\nENCODING 9616\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n1C\n1C\n1C\n1C\n1C\n1C\n1C\n1C\n1C\n1C\n1C\n1C\nENDCHAR\nSTARTCHAR ltshade\nENCODING 9617\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n90\n24\n90\n24\n90\n24\n90\n24\n90\n24\n90\n24\nENDCHAR\nSTARTCHAR shade\nENCODING 9618\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nA8\n54\nA8\n54\nA8\n54\nA8\n54\nA8\n54\nA8\n54\nENDCHAR\nSTARTCHAR dkshade\nENCODING 9619\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nD8\nB4\nD8\nB4\nD8\nB4\nD8\nB4\nD8\nB4\nD8\nB4\nENDCHAR\nSTARTCHAR uni2596\nENCODING 9622\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\nE0\nE0\nE0\nE0\nE0\nE0\nENDCHAR\nSTARTCHAR uni2597\nENCODING 9623\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n1C\n1C\n1C\n1C\n1C\n1C\nENDCHAR\nSTARTCHAR uni2598\nENCODING 9624\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nE0\nE0\nE0\nE0\nE0\nE0\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2599\nENCODING 9625\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nE0\nE0\nE0\nE0\nE0\nE0\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR uni259A\nENCODING 9626\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nE0\nE0\nE0\nE0\nE0\nE0\n1C\n1C\n1C\n1C\n1C\n1C\nENDCHAR\nSTARTCHAR uni259B\nENCODING 9627\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\nFC\nFC\nFC\nFC\nFC\nE0\nE0\nE0\nE0\nE0\nE0\nENDCHAR\nSTARTCHAR uni259C\nENCODING 9628\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\nFC\nFC\nFC\nFC\nFC\n1C\n1C\n1C\n1C\n1C\n1C\nENDCHAR\nSTARTCHAR uni259D\nENCODING 9629\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n1C\n1C\n1C\n1C\n1C\n1C\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni259E\nENCODING 9630\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n1C\n1C\n1C\n1C\n1C\n1C\nE0\nE0\nE0\nE0\nE0\nE0\nENDCHAR\nSTARTCHAR uni259F\nENCODING 9631\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n1C\n1C\n1C\n1C\n1C\n1C\nFC\nFC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR filledbox\nENCODING 9632\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n78\n78\n78\n78\n78\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR filledrect\nENCODING 9644\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\nF8\nF8\nF8\n00\n00\nENDCHAR\nSTARTCHAR uni25AE\nENCODING 9646\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\nF8\nF8\nF8\nF8\nF8\nF8\nF8\n00\n00\nENDCHAR\nSTARTCHAR triagup\nENCODING 9650\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n30\n30\n78\n78\nFC\nFC\n00\n00\n00\nENDCHAR\nSTARTCHAR uni25B6\nENCODING 9654\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nC0\nF0\nFC\nFC\nF0\nC0\n00\n00\n00\nENDCHAR\nSTARTCHAR triagrt\nENCODING 9658\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nC0\nF0\nFC\nFC\nF0\nC0\n00\n00\n00\nENDCHAR\nSTARTCHAR triagdn\nENCODING 9660\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\nFC\nFC\n78\n78\n30\n30\n00\n00\n00\nENDCHAR\nSTARTCHAR uni25C0\nENCODING 9664\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n0C\n3C\nFC\nFC\n3C\n0C\n00\n00\n00\nENDCHAR\nSTARTCHAR triaglf\nENCODING 9668\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n0C\n3C\nFC\nFC\n3C\n0C\n00\n00\n00\nENDCHAR\nSTARTCHAR blackdiamond\nENCODING 9670\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n70\nF8\n70\n20\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR lozenge\nENCODING 9674\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n50\n88\n50\n20\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR circle\nENCODING 9675\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n30\n48\n48\n30\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR H18533\nENCODING 9679\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n30\n78\n78\n30\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR invbullet\nENCODING 9688\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\nFC\nFC\nFC\nCC\n84\n84\nCC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR invcircle\nENCODING 9689\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\nFC\nFC\nFC\nFC\nCC\nB4\nB4\nCC\nFC\nFC\nFC\nFC\nENDCHAR\nSTARTCHAR smileface\nENCODING 9786\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n84\nCC\n84\nB4\nB4\n84\n78\n00\n00\nENDCHAR\nSTARTCHAR invsmileface\nENCODING 9787\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\nFC\nB4\nFC\n84\nCC\nFC\n78\n00\n00\nENDCHAR\nSTARTCHAR sun\nENCODING 9788\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\nA8\n70\nD8\n70\nA8\n20\n00\n00\nENDCHAR\nSTARTCHAR female\nENCODING 9792\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n70\n88\n88\n88\n70\n20\nF8\n20\n00\n00\nENDCHAR\nSTARTCHAR male\nENCODING 9794\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n3C\n0C\n14\n70\n88\n88\n88\n70\n00\n00\nENDCHAR\nSTARTCHAR spade\nENCODING 9824\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n20\n70\nF8\nF8\n70\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR club\nENCODING 9827\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n20\n70\n20\nA8\nF8\nA8\n20\n70\n00\n00\nENDCHAR\nSTARTCHAR heart\nENCODING 9829\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n50\nF8\nF8\nF8\n70\n70\n20\n00\n00\nENDCHAR\nSTARTCHAR diamond\nENCODING 9830\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n20\n70\nF8\n70\n20\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR musicalnote\nENCODING 9834\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n48\n78\n40\n40\n40\n40\n80\n00\n00\nENDCHAR\nSTARTCHAR musicalnotedbl\nENCODING 9835\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n78\n48\n78\n48\n48\n48\n48\n50\n80\n00\nENDCHAR\nSTARTCHAR uni2713\nENCODING 10003\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n04\n04\n08\n88\n90\n50\n20\n20\n00\n00\nENDCHAR\nSTARTCHAR uni2714\nENCODING 10004\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n0C\n0C\n18\nD8\nF0\n70\n60\n60\n00\n00\nENDCHAR\nSTARTCHAR uni2717\nENCODING 10007\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n48\n28\n10\n10\n28\n24\n40\n40\n00\n00\nENDCHAR\nSTARTCHAR uni2718\nENCODING 10008\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n18\nD8\n70\n30\n78\n6C\nC0\nC0\n00\n00\nENDCHAR\nSTARTCHAR uni27E8\nENCODING 10216\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n10\n10\n20\n20\n40\n20\n20\n10\n10\n00\n00\nENDCHAR\nSTARTCHAR uni27E9\nENCODING 10217\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n40\n40\n20\n20\n10\n20\n20\n40\n40\n00\n00\nENDCHAR\nSTARTCHAR uni27EA\nENCODING 10218\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n28\n28\n50\n50\nA0\n50\n50\n28\n28\n00\n00\nENDCHAR\nSTARTCHAR uni27EB\nENCODING 10219\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\nA0\nA0\n50\n50\n28\n50\n50\nA0\nA0\n00\n00\nENDCHAR\nSTARTCHAR uni2800\nENCODING 10240\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2801\nENCODING 10241\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2802\nENCODING 10242\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2803\nENCODING 10243\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2804\nENCODING 10244\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2805\nENCODING 10245\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2806\nENCODING 10246\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2807\nENCODING 10247\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2808\nENCODING 10248\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2809\nENCODING 10249\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni280A\nENCODING 10250\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni280B\nENCODING 10251\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni280C\nENCODING 10252\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni280D\nENCODING 10253\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni280E\nENCODING 10254\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni280F\nENCODING 10255\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2810\nENCODING 10256\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2811\nENCODING 10257\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2812\nENCODING 10258\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2813\nENCODING 10259\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2814\nENCODING 10260\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2815\nENCODING 10261\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2816\nENCODING 10262\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2817\nENCODING 10263\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2818\nENCODING 10264\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2819\nENCODING 10265\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni281A\nENCODING 10266\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni281B\nENCODING 10267\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n00\n00\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni281C\nENCODING 10268\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni281D\nENCODING 10269\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni281E\nENCODING 10270\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni281F\nENCODING 10271\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n40\n40\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2820\nENCODING 10272\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2821\nENCODING 10273\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2822\nENCODING 10274\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2823\nENCODING 10275\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2824\nENCODING 10276\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2825\nENCODING 10277\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2826\nENCODING 10278\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2827\nENCODING 10279\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2828\nENCODING 10280\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2829\nENCODING 10281\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni282A\nENCODING 10282\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni282B\nENCODING 10283\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni282C\nENCODING 10284\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni282D\nENCODING 10285\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni282E\nENCODING 10286\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni282F\nENCODING 10287\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2830\nENCODING 10288\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2831\nENCODING 10289\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2832\nENCODING 10290\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2833\nENCODING 10291\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2834\nENCODING 10292\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2835\nENCODING 10293\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2836\nENCODING 10294\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2837\nENCODING 10295\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2838\nENCODING 10296\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2839\nENCODING 10297\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni283A\nENCODING 10298\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni283B\nENCODING 10299\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n08\n08\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni283C\nENCODING 10300\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni283D\nENCODING 10301\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni283E\nENCODING 10302\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni283F\nENCODING 10303\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n48\n48\n00\n00\n00\n00\nENDCHAR\nSTARTCHAR uni2840\nENCODING 10304\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2841\nENCODING 10305\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2842\nENCODING 10306\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2843\nENCODING 10307\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2844\nENCODING 10308\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2845\nENCODING 10309\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2846\nENCODING 10310\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2847\nENCODING 10311\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2848\nENCODING 10312\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2849\nENCODING 10313\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni284A\nENCODING 10314\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni284B\nENCODING 10315\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni284C\nENCODING 10316\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni284D\nENCODING 10317\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni284E\nENCODING 10318\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni284F\nENCODING 10319\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2850\nENCODING 10320\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2851\nENCODING 10321\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2852\nENCODING 10322\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2853\nENCODING 10323\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2854\nENCODING 10324\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2855\nENCODING 10325\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2856\nENCODING 10326\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2857\nENCODING 10327\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2858\nENCODING 10328\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2859\nENCODING 10329\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni285A\nENCODING 10330\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni285B\nENCODING 10331\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n00\n00\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni285C\nENCODING 10332\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni285D\nENCODING 10333\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni285E\nENCODING 10334\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni285F\nENCODING 10335\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n40\n40\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2860\nENCODING 10336\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2861\nENCODING 10337\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2862\nENCODING 10338\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2863\nENCODING 10339\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2864\nENCODING 10340\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2865\nENCODING 10341\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2866\nENCODING 10342\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2867\nENCODING 10343\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2868\nENCODING 10344\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2869\nENCODING 10345\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni286A\nENCODING 10346\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni286B\nENCODING 10347\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni286C\nENCODING 10348\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni286D\nENCODING 10349\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni286E\nENCODING 10350\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni286F\nENCODING 10351\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2870\nENCODING 10352\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2871\nENCODING 10353\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2872\nENCODING 10354\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2873\nENCODING 10355\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2874\nENCODING 10356\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2875\nENCODING 10357\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2876\nENCODING 10358\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2877\nENCODING 10359\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2878\nENCODING 10360\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2879\nENCODING 10361\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni287A\nENCODING 10362\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni287B\nENCODING 10363\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n08\n08\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni287C\nENCODING 10364\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni287D\nENCODING 10365\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni287E\nENCODING 10366\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni287F\nENCODING 10367\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n48\n48\n00\n40\n40\n00\nENDCHAR\nSTARTCHAR uni2880\nENCODING 10368\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2881\nENCODING 10369\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2882\nENCODING 10370\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2883\nENCODING 10371\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2884\nENCODING 10372\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2885\nENCODING 10373\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2886\nENCODING 10374\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2887\nENCODING 10375\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2888\nENCODING 10376\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2889\nENCODING 10377\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni288A\nENCODING 10378\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni288B\nENCODING 10379\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni288C\nENCODING 10380\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni288D\nENCODING 10381\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni288E\nENCODING 10382\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni288F\nENCODING 10383\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2890\nENCODING 10384\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2891\nENCODING 10385\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2892\nENCODING 10386\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2893\nENCODING 10387\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2894\nENCODING 10388\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2895\nENCODING 10389\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2896\nENCODING 10390\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2897\nENCODING 10391\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2898\nENCODING 10392\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni2899\nENCODING 10393\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni289A\nENCODING 10394\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni289B\nENCODING 10395\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n00\n00\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni289C\nENCODING 10396\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni289D\nENCODING 10397\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni289E\nENCODING 10398\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni289F\nENCODING 10399\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n40\n40\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A0\nENCODING 10400\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A1\nENCODING 10401\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A2\nENCODING 10402\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A3\nENCODING 10403\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A4\nENCODING 10404\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A5\nENCODING 10405\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A6\nENCODING 10406\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A7\nENCODING 10407\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A8\nENCODING 10408\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28A9\nENCODING 10409\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28AA\nENCODING 10410\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28AB\nENCODING 10411\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28AC\nENCODING 10412\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28AD\nENCODING 10413\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28AE\nENCODING 10414\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28AF\nENCODING 10415\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B0\nENCODING 10416\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B1\nENCODING 10417\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B2\nENCODING 10418\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B3\nENCODING 10419\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B4\nENCODING 10420\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B5\nENCODING 10421\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B6\nENCODING 10422\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B7\nENCODING 10423\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B8\nENCODING 10424\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28B9\nENCODING 10425\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28BA\nENCODING 10426\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28BB\nENCODING 10427\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n08\n08\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28BC\nENCODING 10428\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28BD\nENCODING 10429\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28BE\nENCODING 10430\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28BF\nENCODING 10431\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n48\n48\n00\n08\n08\n00\nENDCHAR\nSTARTCHAR uni28C0\nENCODING 10432\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C1\nENCODING 10433\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C2\nENCODING 10434\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C3\nENCODING 10435\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C4\nENCODING 10436\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C5\nENCODING 10437\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C6\nENCODING 10438\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C7\nENCODING 10439\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C8\nENCODING 10440\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28C9\nENCODING 10441\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28CA\nENCODING 10442\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28CB\nENCODING 10443\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28CC\nENCODING 10444\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28CD\nENCODING 10445\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28CE\nENCODING 10446\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28CF\nENCODING 10447\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D0\nENCODING 10448\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D1\nENCODING 10449\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D2\nENCODING 10450\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D3\nENCODING 10451\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D4\nENCODING 10452\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D5\nENCODING 10453\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D6\nENCODING 10454\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D7\nENCODING 10455\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D8\nENCODING 10456\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28D9\nENCODING 10457\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28DA\nENCODING 10458\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28DB\nENCODING 10459\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n00\n00\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28DC\nENCODING 10460\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28DD\nENCODING 10461\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28DE\nENCODING 10462\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28DF\nENCODING 10463\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n40\n40\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E0\nENCODING 10464\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E1\nENCODING 10465\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E2\nENCODING 10466\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E3\nENCODING 10467\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E4\nENCODING 10468\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n00\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E5\nENCODING 10469\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n00\n00\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E6\nENCODING 10470\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n40\n40\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E7\nENCODING 10471\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n40\n40\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E8\nENCODING 10472\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28E9\nENCODING 10473\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28EA\nENCODING 10474\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28EB\nENCODING 10475\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28EC\nENCODING 10476\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n00\n00\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28ED\nENCODING 10477\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n00\n00\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28EE\nENCODING 10478\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n40\n40\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28EF\nENCODING 10479\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n40\n40\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F0\nENCODING 10480\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F1\nENCODING 10481\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F2\nENCODING 10482\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F3\nENCODING 10483\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F4\nENCODING 10484\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n08\n08\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F5\nENCODING 10485\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n08\n08\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F6\nENCODING 10486\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n48\n48\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F7\nENCODING 10487\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n40\n40\n00\n48\n48\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F8\nENCODING 10488\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28F9\nENCODING 10489\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28FA\nENCODING 10490\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28FB\nENCODING 10491\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n08\n08\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28FC\nENCODING 10492\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n08\n08\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28FD\nENCODING 10493\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n08\n08\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28FE\nENCODING 10494\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n08\n08\n00\n48\n48\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni28FF\nENCODING 10495\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n48\n48\n00\n48\n48\n00\n48\n48\n00\n48\n48\n00\nENDCHAR\nSTARTCHAR uni2E2C\nENCODING 11820\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n88\n88\n00\n00\n88\n88\n00\n00\nENDCHAR\nSTARTCHAR uniE0A0\nENCODING 57504\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n90\nB8\n90\n90\n90\n20\n40\n80\n80\n80\n80\nENDCHAR\nSTARTCHAR uniE0A1\nENCODING 57505\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n80\n80\n80\nF0\n00\n24\n34\n2C\n24\n24\n00\nENDCHAR\nSTARTCHAR uniE0A2\nENCODING 57506\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n30\n48\n48\n48\nFC\nFC\nCC\nCC\nFC\nFC\n00\nENDCHAR\nSTARTCHAR uniE0B0\nENCODING 57520\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\nC0\nE0\nF0\nF8\nFC\nFC\nF8\nF0\nE0\nC0\n80\nENDCHAR\nSTARTCHAR uniE0B1\nENCODING 57521\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n80\n40\n20\n10\n08\n04\n04\n08\n10\n20\n40\n80\nENDCHAR\nSTARTCHAR uniE0B2\nENCODING 57522\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n04\n0C\n1C\n3C\n7C\nFC\nFC\n7C\n3C\n1C\n0C\n04\nENDCHAR\nSTARTCHAR uniE0B3\nENCODING 57523\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n04\n08\n10\n20\n40\n80\n80\n40\n20\n10\n08\n04\nENDCHAR\nSTARTCHAR uniF6BE\nENCODING 63166\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\n00\n00\n18\n08\n08\n08\n08\n08\n48\n30\nENDCHAR\nSTARTCHAR uniFFFD\nENCODING 65533\nSWIDTH 500 0\nDWIDTH 6 0\nBBX 6 12 0 -2\nBITMAP\n00\n00\nF8\n88\n88\n88\n88\n88\n88\nF8\n00\n00\nENDCHAR\nENDFONT\n"
  },
  {
    "path": "resources/assets/logisticspipes/lang/en_us.lang",
    "content": "# Master language file\n\n# Insert $ and the name of the TextFormatting entries.\n# Colors: BLACK, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED, DARK_PURPLE,\n#       GOLD, GRAY, DARK_GRAY, BLUE, GREEN, AQUA, RED, LIGHT_PURPLE, YELLOW and WHITE\n# Formatting: OBFUSCATED, BOLD, STRIKETHROUGH, UNDERLINE and ITALIC.\n#\n# You can also use RESET to clear all.\n#\n# Example '$YELLOW'\n\n# Pipes\nitem.logisticspipes.pipe_transport_basic.name=Unrouted Transport Pipe\nitem.logisticspipes.pipe_transport_basic.tip1=Type: Simple Transport Pipe\nitem.logisticspipes.pipe_transport_basic.tip2= - Serves for the Transport of Items\nitem.logisticspipes.pipe_transport_basic.tip3= - Doesn´t route Stuff\nitem.logisticspipes.pipe_transport_basic.tip4= - Can´t access Inventories\n\nitem.logisticspipes.pipe_basic.name=Basic Logistics Pipe\nitem.logisticspipes.pipe_basic.tip1=Type: Passive push destination\nitem.logisticspipes.pipe_basic.tip2= - Routes items around the network.\nitem.logisticspipes.pipe_basic.tip3= - Puts specific types of items into chests.\nitem.logisticspipes.pipe_basic.tip4= - Can be a default route.\n\nitem.logisticspipes.pipe_request.name=Request Logistics Pipe\nitem.logisticspipes.pipe_request.tip1=Type: Active requester\nitem.logisticspipes.pipe_request.tip2= - Lets you manually request items\nitem.logisticspipes.pipe_request.tip3= - Items can come from any Item Source pipe\nitem.logisticspipes.pipe_request.tip4= - Put a chest on the pipe to catch items coming out.\n\nitem.logisticspipes.pipe_request_mk2.name=Request Logistics Pipe Mk2\nitem.logisticspipes.pipe_request_mk2.tip1=Type: Active requester\nitem.logisticspipes.pipe_request_mk2.tip2= - Can have a Logistics Disk for macro requests\nitem.logisticspipes.pipe_request_mk2.tip3= - Lets you manually request items\nitem.logisticspipes.pipe_request_mk2.tip4= - Items can come from any Source pipe\nitem.logisticspipes.pipe_request_mk2.tip5= - Put a chest on the pipe to catch items coming out.\n\nitem.logisticspipes.pipe_provider.name=Provider Logistics Pipe\nitem.logisticspipes.pipe_provider.tip1=Type: Item Source\nitem.logisticspipes.pipe_provider.tip2= - Attaches to an inventory\nitem.logisticspipes.pipe_provider.tip3= - Sends 16 items into the network on request\nitem.logisticspipes.pipe_provider.tip4= - Ignores Suppliers on the same block.\n\nitem.logisticspipes.pipe_provider_mk2.name=Provider Logistics Pipe Mk2\nitem.logisticspipes.pipe_provider_mk2.tip1=Type: Item Source\nitem.logisticspipes.pipe_provider_mk2.tip2= - Attaches to an inventory\nitem.logisticspipes.pipe_provider_mk2.tip3= - Sends a stack of items into the network on request\nitem.logisticspipes.pipe_provider_mk2.tip4= - Ignores Suppliers on the same block.\n\nitem.logisticspipes.pipe_crafting.name=Crafting Logistics Pipe\nitem.logisticspipes.pipe_crafting.tip1=Type: Active Requester + Source\nitem.logisticspipes.pipe_crafting.tip2= - Crafts one item at a time.\nitem.logisticspipes.pipe_crafting.tip3= - Attaches to an Automatic Crafting Table.\nitem.logisticspipes.pipe_crafting.tip4= - Automatically crafts the item inside when requested.\nitem.logisticspipes.pipe_crafting.tip5= - Can use a satellite pipe to send inputs elsewhere.\n\nitem.logisticspipes.pipe_crafting_mk2.name=Crafting Logistics Pipe Mk2\nitem.logisticspipes.pipe_crafting_mk2.tip1=Type: Active Requester + Source\nitem.logisticspipes.pipe_crafting_mk2.tip2= - Crafts 16 items at a time.\nitem.logisticspipes.pipe_crafting_mk2.tip3= - Attaches to an Automatic Crafting Table.\nitem.logisticspipes.pipe_crafting_mk2.tip4= - Automatically crafts the item inside when requested.\nitem.logisticspipes.pipe_crafting_mk2.tip5= - Can use a satellite pipe to send inputs elsewhere.\n\nitem.logisticspipes.pipe_crafting_mk3.name=Crafting Logistics Pipe Mk3\nitem.logisticspipes.pipe_crafting_mk3.tip1=Type: Active Requester + Source\nitem.logisticspipes.pipe_crafting_mk3.tip2= - Crafts a stack at a time.\nitem.logisticspipes.pipe_crafting_mk3.tip3= - Attaches to an Automatic Crafting Table.\nitem.logisticspipes.pipe_crafting_mk3.tip4= - Automatically crafts the item inside when requested.\nitem.logisticspipes.pipe_crafting_mk3.tip5= - Can use a satellite pipe to send inputs elsewhere.\n\nitem.logisticspipes.pipe_satellite.name=Satellite Logistics Pipe\nitem.logisticspipes.pipe_satellite.tip1=Type: Active request destination\nitem.logisticspipes.pipe_satellite.tip2= - A crafting pipe can send additional inputs here\n\nitem.logisticspipes.pipe_supplier.name=Supplier Logistics Pipe\nitem.logisticspipes.pipe_supplier.tip1=Type: Active item requester\nitem.logisticspipes.pipe_supplier.tip2= - Automatically fills a chest or machine\nitem.logisticspipes.pipe_supplier.tip3= - Can get items from any Item Source.\nitem.logisticspipes.pipe_supplier.tip4= - Ignores Providers on the same block.\n\nitem.logisticspipes.pipe_builder_supplier.name=Builder Supplier Logistics Pipe\nitem.logisticspipes.pipe_builder_supplier.tip1=Type: Active item requester\nitem.logisticspipes.pipe_builder_supplier.tip2= - Automatically fills a builder with required materials\n\nitem.logisticspipes.pipe_chassis_mk1.name=Logistics Chassis Mk1\nitem.logisticspipes.pipe_chassis_mk1.tip1=Type: Mixed\nitem.logisticspipes.pipe_chassis_mk1.tip2= - Can hold 1 module by default.\n\nitem.logisticspipes.pipe_chassis_mk2.name=Logistics Chassis Mk2\nitem.logisticspipes.pipe_chassis_mk2.tip1=Type: Mixed\nitem.logisticspipes.pipe_chassis_mk2.tip2= - Can hold 2 modules by default.\n\nitem.logisticspipes.pipe_chassis_mk3.name=Logistics Chassis Mk3\nitem.logisticspipes.pipe_chassis_mk3.tip1=Type: Mixed\nitem.logisticspipes.pipe_chassis_mk3.tip2= - Can hold 3 modules by default.\n\nitem.logisticspipes.pipe_chassis_mk4.name=Logistics Chassis Mk4\nitem.logisticspipes.pipe_chassis_mk4.tip1=Type: Mixed\nitem.logisticspipes.pipe_chassis_mk4.tip2= - Can hold 4 modules by default.\n\nitem.logisticspipes.pipe_chassis_mk5.name=Logistics Chassis Mk5\nitem.logisticspipes.pipe_chassis_mk5.tip1=Type: Mixed\nitem.logisticspipes.pipe_chassis_mk5.tip2= - Can hold 8 modules by default.\n\nitem.logisticspipes.pipe_remote_orderer.name=Remote Orderer Logistics Pipe\nitem.logisticspipes.pipe_remote_orderer.tip1=Type: Active requester\nitem.logisticspipes.pipe_remote_orderer.tip2= - Lets you manually request items *remotely*\nitem.logisticspipes.pipe_remote_orderer.tip3= - Can pull from any Item Source\nitem.logisticspipes.pipe_remote_orderer.tip4= - You must right click a Remote Orderer on this pipe.\n\nitem.logisticspipes.pipe_inventory_system_connector.name=Logistics Inventory System Connector\nitem.logisticspipes.pipe_inventory_system_connector.tip1=Type: Bridge\nitem.logisticspipes.pipe_inventory_system_connector.tip2= - Connects two logistics networks together\nitem.logisticspipes.pipe_inventory_system_connector.tip3=   over a shared inventory\nitem.logisticspipes.pipe_inventory_system_connector.tip4= - Usually used with an ender chest but you\nitem.logisticspipes.pipe_inventory_system_connector.tip5=   can get clever with trains too...\n\nitem.logisticspipes.pipe_system_entrance.name=Logistics System Entrance Pipe\nitem.logisticspipes.pipe_system_entrance.tip1=Type: Router\nitem.logisticspipes.pipe_system_entrance.tip2= - Sends un-routable items to a matched\nitem.logisticspipes.pipe_system_entrance.tip3=   Destination Pipe.\nitem.logisticspipes.pipe_system_entrance.tip4= - Both Entrance and Destination pipe\nitem.logisticspipes.pipe_system_entrance.tip5=   must share a coded frequency card.\n\nitem.logisticspipes.pipe_system_destination.name=Logistics System Destination Pipe\nitem.logisticspipes.pipe_system_destination.tip1=Type: Special Destination\nitem.logisticspipes.pipe_system_destination.tip2= - Receives un-routeable items from a\nitem.logisticspipes.pipe_system_destination.tip3=   matched Entrance Pipe\nitem.logisticspipes.pipe_system_destination.tip4= - Both Entrance and Destination pipe\nitem.logisticspipes.pipe_system_destination.tip5=   must share a coded frequency card.\n\nitem.logisticspipes.pipe_firewall.name=Logistics Firewall Pipe\nitem.logisticspipes.pipe_firewall.tip1=Type: Request Filter\nitem.logisticspipes.pipe_firewall.tip2= - Allows connecting 'hostile' networks\nitem.logisticspipes.pipe_firewall.tip3=   while allowing only certain items to pass\n\nitem.logisticspipes.pipe_fluid_supplier.name=Logistics Fluid Container Supplier\nitem.logisticspipes.pipe_fluid_supplier.tip1=Uses buckets or other fluid containers to fill the connected tank\nitem.logisticspipes.pipe_fluid_supplier_mk2.name=Logistics Fluid Supplier\nitem.logisticspipes.pipe_fluid_supplier_mk2.tip1=Pulls Fluids from a Logistics Fluid Provider Pipe\nitem.logisticspipes.pipe_fluid_connector.name=Logistics Fluid Connector Pipe\nitem.logisticspipes.pipe_fluid_basic.name=Logistics Fluid Basic Pipe\nitem.logisticspipes.pipe_fluid_insertion.name=Logistics Fluid Insertion Pipe\nitem.logisticspipes.pipe_fluid_provider.name=Logistics Fluid Provider Pipe\nitem.logisticspipes.pipe_fluid_request.name=Logistics Fluid Request Pipe\nitem.logisticspipes.pipe_fluid_extractor.name=Logistics Fluid Extractor Pipe\nitem.logisticspipes.pipe_fluid_satellite.name=Logistics Fluid Satellite Pipe\nitem.logisticspipes.pipe_fluid_terminus.name=Logistics Fluid Terminus Pipe\nitem.logisticspipes.pipe_request_table.name=Logistics Request Table\n\nitem.logisticspipes.pipe_hs_curve.name=Highspeed Curve Tube\nitem.logisticspipes.pipe_hs_speedup.name=Highspeed Speedup Tube\nitem.logisticspipes.pipe_hs_s_curve.name=Highspeed S-Curve Tube\nitem.logisticspipes.pipe_hs_line.name=Highspeed Line Tube\nitem.logisticspipes.pipe_hs_gain.name=Highspeed Gain Tube\n\n# Modules\n\n#TODO: Add shift tooltip information\n\nitem.logisticspipes.module_blank.name=Blank Module\nitem.logisticspipes.module_item_sink.name=ItemSink Module\nitem.logisticspipes.module_passive_supplier.name=Passive Supplier Module\nitem.logisticspipes.module_extractor.name=Extractor Module\nitem.logisticspipes.module_item_sink_polymorphic.name=Polymorphic ItemSink Module\nitem.logisticspipes.module_quick_sort.name=QuickSort Module\nitem.logisticspipes.module_terminus.name=Terminus Module\nitem.logisticspipes.module_extractor_advanced.name=Advanced Extractor Module\nitem.logisticspipes.module_extractor_mk2.name=Extractor MK2 Module\nitem.logisticspipes.module_extractor_advanced_mk2.name=Advanced Extractor MK2\nitem.logisticspipes.module_extractor_mk3.name=Extractor MK3 Module\nitem.logisticspipes.module_extractor_advanced_mk3.name=Advanced Extractor MK3\nitem.logisticspipes.module_provider.name=Provider Module\nitem.logisticspipes.module_provider_mk2.name=Provider Module MK2\nitem.logisticspipes.module_item_sink_mod.name=Mod Based ItemSink Module\nitem.logisticspipes.module_item_sink_oredict.name=OreDict ItemSink Module\nitem.logisticspipes.module_thaumic_aspect_sink.name=Thaumic AspectSink Module\nitem.logisticspipes.module_enchantment_sink.name=Enchantment Sink Module\nitem.logisticspipes.module_enchantment_sink_mk2.name=Enchantment Sink Module MK2\nitem.logisticspipes.module_item_sink_cc.name=CC Based ItemSink Module\nitem.logisticspipes.module_quick_sort_cc.name=CC Based QuickSort Module\nitem.logisticspipes.module_crafter.name=Crafting Module\nitem.logisticspipes.module_crafter_mk2.name=Crafting Module MK2\nitem.logisticspipes.module_crafter_mk3.name=Crafting Module MK3\nitem.logisticspipes.module_active_supplier.name=Active Supplier Module\nitem.logisticspipes.module_item_sink_creativetab.name=Creative Tab Based ItemSink Module\n\n# Items\n\nitem.logisticspipes.broken_item.name=Logistics Broken Item\nitem.logisticspipes.broken_item.tip1=This is an useless item\nitem.logisticspipes.broken_item.tip2=You get this by trying to break a protected pipe\n\nitem.logisticspipes.fluid_container.name=Logistics Fluid Container\n# $RED (DEPRECATED) $RESET\nitem.logisticspipes.upgrade_manager.name=Upgrade Manager\nitem.logisticspipes.parts.0.name=Logistics HUD Bow\nitem.logisticspipes.parts.1.name=Logistics HUD Glass\nitem.logisticspipes.parts.2.name=Logistics HUD Nose Bridge\nitem.logisticspipes.parts.3.name=Nano Hopper\nitem.logisticspipes.item_card.0.name=Logistics Item Card\nitem.logisticspipes.disk.name=Logistics Disk\n# $RED (DEPRECATED) $RESET\nitem.logisticspipes.network_monitor.name=Network Monitor\nitem.logisticspipes.sign_creator.0.name=Crafting Sign Creator\nitem.logisticspipes.sign_creator.1.name=Item Amount Sign Creator\nitem.logisticspipes.hud_glasses.name=Logistics HUD Glasses\nitem.logisticspipes.remote_orderer.name=Remote Orderer\n\nitem.logisticspipes.pipe_controller.name=Pipe Controller\nitem.logisticspipes.pipe_manager.name=Pipe Manager\nitem.logisticspipes.logistics_programmer.name=Logistics Programmer\n\nitem.logisticspipes.chip_basic.name=Basic Chip\nitem.logisticspipes.chip_basic_raw.name=Raw Basic Chip\nitem.logisticspipes.chip_advanced.name=Advanced Chip\nitem.logisticspipes.chip_advanced_raw.name=Raw Advanced Chip\nitem.logisticspipes.chip_fpga.name=FPGA\nitem.logisticspipes.chip_fpga_raw.name=Raw FPGA\nitem.logisticspipes.guide_book.name=Logistics Pipes' Guide Book\n\n# Tooltips\ntooltip.logisticsItemCard=This is no valid Card\n\ntooltip.programmerForModule=Module program loaded\ntooltip.programmerForPipe=Pipe program loaded\ntooltip.programmerForUpgrade=Upgrade program loaded\ntooltip.programmerForUnknown.1=$REDNo valid program loaded $RESET\ntooltip.programmerForUnknown.2=$REDYOU $ITALICNEED$RESET $REDTO FLASH A PROGRAM $RESET\ntooltip.programmerForUnknown.3=$REDBEFORE YOU CAN USE THIS FOR CRAFTING $RESET\n\n# Upgrades\n\nitem.logisticspipes.upgrade_sneaky_up.name=Sneaky Upgrade (UP)\nitem.logisticspipes.upgrade_sneaky_down.name=Sneaky Upgrade (DOWN)\nitem.logisticspipes.upgrade_sneaky_north.name=Sneaky Upgrade (NORTH)\nitem.logisticspipes.upgrade_sneaky_south.name=Sneaky Upgrade (SOUTH)\nitem.logisticspipes.upgrade_sneaky_east.name=Sneaky Upgrade (EAST)\nitem.logisticspipes.upgrade_sneaky_west.name=Sneaky Upgrade (WEST)\nitem.logisticspipes.upgrade_sneaky_combination.name=Sneaky Combination Upgrade\nitem.logisticspipes.upgrade_speed.name=Item Speed Upgrade\nitem.logisticspipes.upgrade_disconnection_up.name=Disconnection Upgrade (UP)\nitem.logisticspipes.upgrade_disconnection_down.name=Disconnection Upgrade (DOWN)\nitem.logisticspipes.upgrade_disconnection_north.name=Disconnection Upgrade (NORTH)\nitem.logisticspipes.upgrade_disconnection_south.name=Disconnection Upgrade (SOUTH)\nitem.logisticspipes.upgrade_disconnection_east.name=Disconnection Upgrade (EAST)\nitem.logisticspipes.upgrade_disconnection_west.name=Disconnection Upgrade (WEST)\nitem.logisticspipes.upgrade_satellite_advanced.name=Advanced Satellite Upgrade\nitem.logisticspipes.upgrade_fluid_crafting.name=Fluid Crafting Upgrade\nitem.logisticspipes.upgrade_crafting_byproduct.name=Crafting Byproduct Extraction Upgrade\nitem.logisticspipes.upgrade_pattern.name=Placement Rules Upgrade\nitem.logisticspipes.upgrade_fuzzy.name=Fuzzy Upgrade\nitem.logisticspipes.upgrade_power_transportation.name=Power Transportation Upgrade\nitem.logisticspipes.upgrade_power_supplier_mj.name=MJ Power Supplier Upgrade\nitem.logisticspipes.upgrade_power_supplier_rf.name=RF Power Supplier Upgrade\nitem.logisticspipes.upgrade_power_supplier_eu_lv.name=EU LV Power Supplier Upgrade\nitem.logisticspipes.upgrade_power_supplier_eu_mv.name=EU MV Power Supplier Upgrade\nitem.logisticspipes.upgrade_power_supplier_eu_hv.name=EU HV Power Supplier Upgrade\nitem.logisticspipes.upgrade_power_supplier_eu_ev.name=EU EV Power Supplier Upgrade\nitem.logisticspipes.upgrade_cc_remote_control.name=CC Remote Control Upgrade\nitem.logisticspipes.upgrade_crafting_monitoring.name=Crafting Monitoring Upgrade\nitem.logisticspipes.upgrade_opaque.name=Opaque Upgrade\nitem.logisticspipes.upgrade_crafting_cleanup.name=Crafting Cleanup Upgrade\nitem.logisticspipes.upgrade_logic_controller.name=Logic Controller Upgrade\nitem.logisticspipes.upgrade_module_upgrade.name=Module Upgrade\nitem.logisticspipes.upgrade_sneaky.name=Sneaky Upgrade\nitem.logisticspipes.upgrade_disconnection.name=Disconnection Upgrade\nitem.logisticspipes.upgrade_action_speed.name=Action Speed Upgrade\nitem.logisticspipes.upgrade_item_extraction.name=Item Extraction Upgrade\nitem.logisticspipes.upgrade_item_stack_extraction.name=ItemStack Extraction Upgrade\n\n#Upgrade info\n\nitem.upgrade.info.both1=Can be applied to $YELLOW{0}$RESET$GRAY pipes\nitem.upgrade.info.both2=and $YELLOW{0} $RESET$GRAYmodules\nitem.upgrade.info.pipe=Can be applied to $YELLOW{0}$RESET$GRAY pipes\nitem.upgrade.info.module=Can be applied to $YELLOW{0}$RESET$GRAY modules\nitem.upgrade.info.all=All\nitem.upgrade.info.crafting=Crafting\nitem.upgrade.info.provider=Provider\nitem.upgrade.info.itemsink=Item Sink\nitem.upgrade.info.extractor=Extractor\nitem.upgrade.info.aextractor=Advanced Extractor\nitem.upgrade.info.supplier=Supplier\nitem.upgrade.info.requestblock=Request Block\nitem.upgrade.info.chassis=Chassis\nitem.upgrade.info.basic=Basic\n\n# Blocks\ntile.logisticspipes.frame.name=Logistics Block Frame\ntile.logisticspipes.soldering_station.name=Soldering Station\ntile.logisticspipes.power_junction.name=Logistics Power Junction\ntile.logisticspipes.security_station.name=Logistics Security Station\ntile.logisticspipes.crafting_table.name=Logistics Crafting Table\ntile.logisticspipes.crafting_table_fuzzy.name=Logistics Fuzzy Crafting Table\ntile.logisticspipes.power_provider_mj.name=Logistics MJ Power Provider\ntile.logisticspipes.power_provider_eu.name=Logistics EU Power Provider\ntile.logisticspipes.power_provider_rf.name=Logistics RF Power Provider\ntile.logisticspipes.statistics_table.name=Logistics Statistics Table\ntile.logisticspipes.program_compiler.name=Logistics Program Compiler\n\n# Misc\nitemGroup.Logistics_Pipes=Logistics Pipes\nmisc.holdshift=<Hold $YELLOW$ITALICShift$RESET$GRAY for details>\nmisc.extractionmode.Normal=Normal\nmisc.extractionmode.LeaveFirst=Leave 1st stack\nmisc.extractionmode.LeaveLast=Leave last stack\nmisc.extractionmode.LeaveFirstAndLast=Leave first & last stack\nmisc.extractionmode.Leave1PerStack=Leave 1 item per stack\nmisc.extractionmode.Leave1PerType=Leave 1 item per type\nmisc.selectType=Select Type\nmisc.selectOreDict=Select OreDict Type\nmisc.guide_book.home_button=Return to landing page.\nmisc.guide_book.bookmark_button.add=Add current page to bookmarks.\nmisc.guide_book.bookmark_button.remove=Remove current page from bookmarks.\nmisc.guide_book.missing_page_title=Page not found\nmisc.guide_book.missing_page=The requested page´s file ´{0}´ was not found.\n\n#Misc Chat messages\n\nlp.chat.slotnotfound=Couldn't find that slot internally. Sorry. Please try again.\nlp.chat.permissiondenied=Permission denied\nlp.chat.connectedtopipe=Connected to pipe\nlp.misc.noenergy=No Energy\nlp.hud.config.chassie.enabled=Enabled Chassis.\nlp.hud.config.chassie.disabled=Disabled Chassis.\nlp.hud.config.crafting.enabled=Enabled Crafting.\nlp.hud.config.crafting.disabled=Disabled Crafting.\nlp.hud.config.invsyscon.enabled=Enabled InvSysCon.\nlp.hud.config.invsyscon.disabled=Disabled InvSysCon.\nlp.hud.config.powerjunction.enabled=Enabled Power Junction.\nlp.hud.config.powerjunction.disabled=Disabled Power Junction.\nlp.hud.config.provider.enabled=Enabled Provider.\nlp.hud.config.provider.disabled=Disabled Provider.\nlp.hud.config.satellite.enabled=Enabled Satellite.\nlp.hud.config.satellite.disabled=Disabled Satellite.\n\n# GUI\n\ngui.itemsink.Yes=Yes\ngui.itemsink.No=No\ngui.itemsink.Inventory=Inventory\ngui.itemsink.Defaultroute=Default route\ngui.itemsink.IgnoreData=Ignore Data\ngui.itemsink.IgnoreNBT=Ignore NBT\ngui.itemsink.import=Import\n\ngui.crafting.Inputs=Inputs\ngui.crafting.Inventory=Inventory\ngui.crafting.Import=Import\ngui.crafting.Open=Open\ngui.crafting.Output=Output\ngui.crafting.Satellite=Satellite\ngui.crafting.Off=Off\ngui.crafting.Priority=Priority\ngui.crafting.Extra=Extra\ngui.crafting.OreDict=OreDict\ngui.crafting.IgnDamage=IgnDamage\ngui.crafting.IgnNBT=IgnNBT\ngui.crafting.OrePrefix=OrePrefix\ngui.crafting.Include=Include\ngui.crafting.Exclude=Exclude\ngui.crafting.Select=Select\ngui.crafting.Sel=Sel\n\ngui.firewall.Blocked=Blocked\ngui.firewall.Allowed=Allowed\ngui.firewall.Firewall=Firewall\ngui.firewall.Filter=Filter\ngui.firewall.Filtereditemsare=Filtered items are\ngui.firewall.Providing=Providing\ngui.firewall.Crafting=Crafting\ngui.firewall.Sorting=Sorting\ngui.firewall.Powerflow=Powerflow\n\ngui.fluidbasic.Empty=Empty\n\ngui.fluidsuppliermk2.Inventory=Inventory\ngui.fluidsuppliermk2.Fluid=Fluid\ngui.fluidsuppliermk2.Partial=Partial\ngui.fluidsuppliermk2.minMode=Min. Mode\ngui.fluidsuppliermk2.Yes=Yes\ngui.fluidsuppliermk2.No=No\ngui.fluidsuppliermk2.TargetInv=Fluid to keep stocked\ngui.fluidsuppliermk2.NONE=None\ngui.fluidsuppliermk2.ONEBUCKET=1 Bucket\ngui.fluidsuppliermk2.TWOBUCKET=2 Buckets\ngui.fluidsuppliermk2.FIVEBUCKET=5 Buckets\n\ngui.fluidsupplier.TargetInv=Fluids to keep stocked\ngui.fluidsupplier.Inventory=Inventory\ngui.fluidsupplier.Partialrequests=Partial requests\ngui.fluidsupplier.Yes=Yes\ngui.fluidsupplier.No=No\n\ngui.invsyscon.Refresh=Refresh\ngui.invsyscon.Save=Save\ngui.invsyscon.Change=Change\ngui.invsyscon.Channel=Channel\ngui.invsyscon.InventorySystemConnector=Inventory System Connector\ngui.invsyscon.ConnectionInformation=Connection Information\ngui.invsyscon.Waitingfor=Waiting for\ngui.invsyscon.Resistance=Resistance\n\ngui.powerjunction.LogisticsPowerJunction=Logistics Power Junction\ngui.powerjunction.StoredEnergy=Stored Energy\n\ngui.powerprovider.LogisticsMJPowerProvider=Logistics MJ Power Provider\ngui.powerprovider.LogisticsEUPowerProvider=Logistics EU Power Provider\ngui.powerprovider.LogisticsRFPowerProvider=Logistics RF Power Provider\ngui.powerprovider.StoredEnergy=Stored Energy\n\ngui.providerpipe.TargetInv=Items to provide (or empty for all)\ngui.providerpipe.Inventory=Inventory\ngui.providerpipe.Mode=Mode\ngui.providerpipe.ExcessInventory=Excess Inventory:\ngui.providerpipe.Exclude=Exclude\ngui.providerpipe.Include=Include\ngui.providerpipe.Switch=Switch\n\ngui.routingstats.Session=Session\ngui.routingstats.Lifetime=Lifetime\ngui.routingstats.Sent=Sent\ngui.routingstats.Recieved=Received\ngui.routingstats.Relayed=Relayed\ngui.routingstats.RoutingTableSize=RoutingTableSize\ngui.routingstats.exit=Press <ESC> to exit\n\ngui.satellite.SatelliteName=Satellite Name\ngui.satellite.naming_result.success=Success\ngui.satellite.naming_result.duplicate_name=Name already used.\ngui.satellite.naming_result.blank_name=Name can't be blank.\n\ngui.securitystation.Open=Open\ngui.securitystation.EditTable=Edit Table\ngui.securitystation.Authorize=Authorize\ngui.securitystation.Deauthorize=Deauthorize\ngui.securitystation.SecurityStation=Security Station\ngui.securitystation.allowCCAccess=Allow ComputerCraft Access\ngui.securitystation.excludeIDs=Excluded ComputerCraft IDs\ngui.securitystation.pipeRemove=Allow automated Pipe remove\ngui.securitystation.Player=Player\ngui.securitystation.SecurityCards=Security Cards\ngui.securitystation.Inventory=Inventory\ngui.securitystation.ChannelManager=Channel Manager\ngui.securitystation.popup.ccAccess.Remove=Remove\ngui.securitystation.popup.ccAccess.Add=Add\ngui.securitystation.popup.player.Close=Close\ngui.securitystation.popup.player.Player=Player\ngui.securitystation.popup.player.ConfigureSettings=Configure Settings\ngui.securitystation.popup.player.ActiveRequesting=Active Requesting\ngui.securitystation.popup.player.UpgradePipes=Upgrade Pipes\ngui.securitystation.popup.player.CheckNetwork=Check Network\ngui.securitystation.popup.player.RemovePipes=Remove Pipes\ngui.securitystation.popup.player.AccessRoutingChannels=Access Routing Channels\n\ngui.supplierpipe.TargetInv=Items to keep stocked\ngui.supplierpipe.TargetInvPattern=Items to keep in the specified slots\ngui.supplierpipe.Inventory=Inventory\ngui.supplierpipe.RequestMode=Request Mode\n\ngui.upgrademanager.Upgrades=Upgrades\ngui.upgrademanager.Inventory=Inventory\ngui.upgrademanager.SneakyUpgrades=Sneaky Upgrades\n\ngui.pipecontroller.upgrade=Upgrades\ngui.pipecontroller.inventory=Inventory\ngui.pipecontroller.sneakyUpgrades=Sneaky Upgrades\ngui.pipecontroller.security=Security\ngui.pipecontroller.Session=Session\ngui.pipecontroller.Lifetime=Lifetime\ngui.pipecontroller.Sent=Sent\ngui.pipecontroller.Recieved=Received\ngui.pipecontroller.Relayed=Relayed\ngui.pipecontroller.RoutingTableSize=RoutingTableSize\ngui.pipecontroller.popup.disconnectTitle=Disconnection Configuration\ngui.pipecontroller.popup.sneakyTitle=Sneaky Configuration\n\ngui.networkstatistics.amount=Track amount\ngui.networkstatistics.crafting=View active crafting tasks\ngui.networkstatistics.gettasks=Acquire tasks\ngui.networkstatistics.add.alreadytracked=This item type is already tracked\n\ngui.compiler.logisticspipes.compilercategory.basic=Basic\ngui.compiler.logisticspipes.compilercategory.tier_2=Tier 2\ngui.compiler.logisticspipes.compilercategory.fluid=Fluid\ngui.compiler.logisticspipes.compilercategory.tier_3=Tier 3\ngui.compiler.logisticspipes.compilercategory.chassis=Chassis\ngui.compiler.logisticspipes.compilercategory.chassis_2=Chassis 2\ngui.compiler.logisticspipes.compilercategory.chassis_3=Chassis 3\ngui.compiler.logisticspipes.compilercategory.modded=Modded\n\ngui.compiler.processing=Processing...\ngui.compiler.nopower.1=$REDNo power$RESET\ngui.compiler.nopower.2=$REDConnect to LP network$RESET\n\ngui.settings.pipenewrenderer=Use New Renderer\ngui.settings.pipefallbackrenderer=Use Fallback Renderer\ngui.settings.piperenderdistance=Max. Distance for new Renderer\ngui.settings.pipecontentrenderdistance=Max. Distance for Pipe Content\n\ngui.popup.selectchannel.title=Channel Selection\n\ngui.popup.addchannel.title=Add Channel\ngui.popup.addchannel.name=Name\ngui.popup.addchannel.access=Access rights\ngui.popup.addchannel.public=Public\ngui.popup.addchannel.security=Security Station\ngui.popup.addchannel.private=Private\ngui.popup.addchannel.save=Save\n\ngui.popup.editchannel.title=Edit Channel\ngui.popup.editchannel.save=Save\ngui.popup.editchannel.owner=Owner\n\ngui.popup.managechannel.title=Channel Manager\ngui.popup.managechannel.deletedialog.title=Do you really want to delete this channel?\ngui.popup.managechannel.deletedialog.yes=Yes\ngui.popup.managechannel.deletedialog.no=No\n\ngui.popup.selectsatellite.title=Select Satellite Pipe\ngui.popup.selectsatellite.select=Select\ngui.popup.selectsatellite.exit=Exit\ngui.popup.selectsatellite.unset=Unset\n\nitemstackinfo.lprouteditem=$REDItem with stored LogisticsPipes routing information\nitemstackinfo.lproutediteminfo=$YELLOWDrop to remove routing information and get original items back\nitemstackinfo.lprouteditemtype=Stored item\n\ntop.logisticspipes.general.upgrades=Installed upgrades: %s\ntop.logisticspipes.general.no_upgrades=$REDNo installed upgrades.\ntop.logisticspipes.general.is_default_route=This $GREENis$WHITE set as a default route.\ntop.logisticspipes.general.is_not_default_route=This $REDis not§f set as a default route.\n\ntop.logisticspipes.module.provider.all=Providing $GREENall$WHITE items.\ntop.logisticspipes.module.provider.none=Providing $REDno$WHITE items.\ntop.logisticspipes.module.provider.but=Providing all $YELLOWexcept$WHITE: %s\ntop.logisticspipes.module.provider.only=Providing $YELLOWonly$WHITE: %s\ntop.logisticspipes.module.provider.mode=Mode:\n\ntop.logisticspipes.module.crafting.result=Crafting $AQUA%s$WHITE.\ntop.logisticspipes.module.crafting.no_result=$REDNo crafting recipe set.\ntop.logisticspipes.module.crafting.result_with_byproduct=Crafting $AQUA%s$WHITE with $AQUA%s$WHITE as byproduct.\n\ntop.logisticspipes.module.terminus.filter=Terminated items: %s\ntop.logisticspipes.module.terminus.no_filter=There are $REDno terminated items$RESET.\n\ntop.logisticspipes.module.passive_supplier.filter=Requesting: %s\ntop.logisticspipes.module.passive_supplier.no_filter=Requesting $REDno$WHITE items.\n\ntop.logisticspipes.module.active_supplier.filter=Items: %s\ntop.logisticspipes.module.active_supplier.no_filter=$REDNo$WHITE items being supplied.\ntop.logisticspipes.module.active_supplier.mode=Requesting items in $AQUA%s$WHITE mode.\n\ntop.logisticspipes.module.enchantment_sink.filter=Accepting items: %s\ntop.logisticspipes.module.enchantment_sink.no_filter=There are $REDno items set$WHITE to filter.\n\ntop.logisticspipes.module.mod_item_sink.filter=Accepting items from mods: %s\ntop.logisticspipes.module.mod_item_sink.no_filter=There are $REDno mods set$WHITE to filter.\n\ntop.logisticspipes.module.creative_tab_item_sink.filter=Accepting items from tabs: %s\ntop.logisticspipes.module.creative_tab_item_sink.no_filter=There are $REDno creative tabs set$WHITE to filter.\n\ntop.logisticspipes.module.ore_item_sink.filter=Accepting ores matching: %s\ntop.logisticspipes.module.ore_item_sink.no_filter=There are $REDno ores set$WHITE to filter.\n\ntop.logisticspipes.module.extractor.side=Extracting from $AQUA%s$WHITE.\n\ntop.logisticspipes.module.advanced_extractor.all=Extracting $GREENall$WHITE items.\ntop.logisticspipes.module.advanced_extractor.none=Extracting $REDno$WHITE items.\ntop.logisticspipes.module.advanced_extractor.but=Extracting all $YELLOWexcept$WHITE: %s\ntop.logisticspipes.module.advanced_extractor.only=Extracting $YELLOWonly$WHITE: %s\n\ntop.logisticspipes.pipe.satellite.name=Satellite name: $AQUA%s$RESET.\ntop.logisticspipes.pipe.satellite.no_name=Satellite name $REDnot set$RESET.\n\ntop.logisticspipes.pipe.firewall.providing=Providing: %s\ntop.logisticspipes.pipe.firewall.crafting=Crafting: %s\ntop.logisticspipes.pipe.firewall.sorting=Sorting: %s\ntop.logisticspipes.pipe.firewall.power=Power: %s\ntop.logisticspipes.pipe.firewall.filtering=$AQUA%d$WHITE items are being %s.\ntop.logisticspipes.pipe.firewall.allowed=$GREENallowed$WHITE\ntop.logisticspipes.pipe.firewall.blocked=$REDblocked$WHITE\n\ntop.logisticspipes.pipe.unrouted.too_many_connections=Unrouted pipes $REDshould not$RESET have more than 2 connections!\n\ntop.logisticspipes.pipe.chassis.no_modules=$REDNo modules installed.\n\nenum.logisticspipes.fuzzy_flags.use_ore_dict=OreDict\nenum.logisticspipes.fuzzy_flags.ignore_damage=IgnDamage\nenum.logisticspipes.fuzzy_flags.ignore_nbt=IgnNBT\nenum.logisticspipes.fuzzy_flags.use_ore_category=OrePrefix\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/block/pipe.json",
    "content": "{\n\t\"parent\": \"block/cube_all\",\n\t\"textures\": {\n\t\t\"all\": \"logisticspipes:blocks/pipe\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/block/solid_block.json",
    "content": "{\n  \"parent\": \"block/cube_all\",\n  \"textures\": {\n    \"all\": \"logisticspipes:solid_block/frame\"\n  }\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/block/sub_multiblock.json",
    "content": "{\n\t\"parent\": \"block/cube_all\",\n\t\"textures\": {\n\t\t\"all\": \"minecraft:missingno\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/broken_item.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/broken_item\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/chip/advanced.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/chip/advanced\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/chip/advanced_raw.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/chip/advanced_raw\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/chip/basic.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/chip/basic\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/chip/basic_raw.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/chip/basic_raw\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/chip/fpga.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/chip/fpga\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/chip/fpga_raw.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/chip/fpga_raw\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/disk.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/disk\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/fluid_container.json",
    "content": "{\n\t\"parent\": \"builtin/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/liquids/empty\"\n\t},\n\t\"display\": {\n\t\t\"thirdperson\": {\n\t\t\t\"rotation\": [-90, 0, 0],\n\t\t\t\"translation\": [0, 1, -3],\n\t\t\t\"scale\": [0.55, 0.55, 0.55 ]\n\t\t},\n\t\t\"firstperson\": {\n\t\t\t\"rotation\": [0, -135, 25 ],\n\t\t\t\"translation\": [0, 4, 2 ],\n\t\t\t\"scale\": [1.7, 1.7, 1.7]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/guide_book.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/guide_book\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/hud_glasses.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/hud_glasses\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/item_card.json",
    "content": "{\n\t\"parent\": \"builtin/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/item_card\"\n\t},\n\t\"display\": {\n\t\t\"thirdperson\": {\n\t\t\t\"rotation\": [-90, 0, 0],\n\t\t\t\"translation\": [0, 1, -3],\n\t\t\t\"scale\": [0.55, 0.55, 0.55 ]\n\t\t},\n\t\t\"firstperson\": {\n\t\t\t\"rotation\": [0, -135, 25 ],\n\t\t\t\"translation\": [0, 4, 2 ],\n\t\t\t\"scale\": [1.7, 1.7, 1.7]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/logistics_programmer.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/logistics_programmer\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/active_supplier.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/active_supplier\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/blank.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/blank\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/crafter.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/crafter\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/crafter_mk2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/crafter_mk2\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/crafter_mk3.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/crafter_mk3\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/enchantment_sink.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/enchantment_sink\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/enchantment_sink_mk2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/enchantment_sink_mk2\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/extractor.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/extractor\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/extractor_advanced.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/extractor_advanced\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/extractor_advanced_mk2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/extractor_advanced_mk2\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/extractor_advanced_mk3.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/extractor_advanced_mk3\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/extractor_mk2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/extractor_mk2\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/extractor_mk3.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/extractor_mk3\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/item_sink.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/item_sink\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/item_sink_cc.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/item_sink_cc\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/item_sink_creativetab.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/item_sink_creativetab\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/item_sink_mod.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/item_sink_mod\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/item_sink_oredict.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/item_sink_oredict\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/item_sink_polymorphic.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/item_sink_polymorphic\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/passive_supplier.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/passive_supplier\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/provider.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/provider\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/provider_mk2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/provider_mk2\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/quick_sort.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/quick_sort\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/quick_sort_cc.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/quick_sort_cc\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/terminus.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/terminus\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/module/thaumic_aspect_sink.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/module/thaumic_aspect_sink\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/parts/0.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/parts/0\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/parts/1.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/parts/1\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/parts/2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/parts/2\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/parts/3.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/parts/3\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/pipe.json",
    "content": "{\n\t\"parent\": \"logisticspipes:block/pipe\",\n\t\"display\": {\n\t\t\"thirdperson\": {\n\t\t\t\"rotation\": [ 10, -45, 170 ],\n\t\t\t\"translation\": [ 0, 1.5, -2.75 ],\n\t\t\t\"scale\": [ 0.375, 0.375, 0.375 ]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/pipe_controller.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/pipe_controller\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/pipe_manager.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/pipe_manager\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/0.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/0\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/1.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/1\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/10.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/10\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/11.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/11\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/12.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/12\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/13.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/13\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/14.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/14\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/15.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/15\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/16.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/16\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/2.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/2\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/3.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/3\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/4.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/4\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/5.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/5\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/6.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/6\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/7.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/7\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/8.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/8\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/remote_orderer/9.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/remote_orderer/9\"\n\t}\n}"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/sign_creator.0.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/sign_creator.0\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/sign_creator.1.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/sign_creator.1\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/solid_block.json",
    "content": "{\n\t\"parent\": \"logisticspipes:block/solid_block\",\n\t\"display\": {\n\t\t\"thirdperson\": {\n\t\t\t\"rotation\": [ 10, -45, 170 ],\n\t\t\t\"translation\": [ 0, 1.5, -2.75 ],\n\t\t\t\"scale\": [ 0.375, 0.375, 0.375 ]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/sub_multiblock.json",
    "content": "{\n\t\"parent\": \"logisticspipes:block/sub_multiblock\",\n\t\"display\": {\n\t\t\"thirdperson\": {\n\t\t\t\"rotation\": [ 10, -45, 170 ],\n\t\t\t\"translation\": [ 0, 1.5, -2.75 ],\n\t\t\t\"scale\": [ 0.375, 0.375, 0.375 ]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/action_speed.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/action_speed\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/cc_remote_control.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/cc_remote_control\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/crafting_byproduct.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/crafting_byproduct\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/crafting_cleanup.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/crafting_cleanup\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/crafting_monitoring.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/crafting_monitoring\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/disconnection.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/disconnection\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/fluid_crafting.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/fluid_crafting\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/fuzzy.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/fuzzy\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/item_extraction.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/item_extraction\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/item_stack_extraction.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/item_stack_extraction\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/logic_controller.json",
    "content": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"minecraft:missingno\"\n  }\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/module_upgrade.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/module_upgrade\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/opaque.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/opaque\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/pattern.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/pattern\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_eu.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_eu\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_eu_ev.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_eu_ev\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_eu_hv.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_eu_hv\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_eu_lv.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_eu_lv\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_eu_mv.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_eu_mv\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_mj.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_mj\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_supplier_rf.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_supplier_rf\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/power_transportation.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/power_transportation\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/satellite_advanced.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/satellite_advanced\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/sneaky.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/sneaky\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/sneaky_combination.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/sneaky_combination\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/models/item/upgrade/speed.json",
    "content": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"logisticspipes:items/upgrade/speed\"\n\t}\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/_factories.json",
    "content": "{\n  \"conditions\": {\n    \"ore_exists\": \"logisticspipes.recipes.conditions.ConditionOreExists\"\n  },\n  \"ingredients\": {\n    \"part\": \"logisticspipes.recipes.ingredients.IngredientPart\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/block_frame.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"iri\",\n    \"   \",\n    \"w w\"\n  ],\n  \"key\": {\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"w\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"plankWood\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:frame\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/chip/chip_advanced_raw.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"cd\",\n    \"dc\"\n  ],\n  \"key\": {\n    \"c\": {\n      \"item\": \"logisticspipes:chip_basic_raw\"\n    },\n    \"d\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemDiamond\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:chip_advanced_raw\",\n    \"count\": 2\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/chip/chip_basic_raw.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"sg\",\n    \"gs\"\n  ],\n  \"key\": {\n    \"s\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"sand\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotCopper\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:chip_basic_raw\",\n    \"count\": 2\n  },\n  \"conditions\": [\n    {\n      \"type\": \"logisticspipes:ore_exists\",\n      \"ore\": \"ingotCopper\"\n    }\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/chip/chip_basic_raw_nocopper.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"sg\",\n    \"gs\"\n  ],\n  \"key\": {\n    \"s\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"sand\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotGold\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:chip_basic_raw\",\n    \"count\": 2\n  },\n  \"conditions\": [\n    {\n      \"type\": \"logisticspipes:ore_exists\",\n      \"ore\": \"!ingotCopper\"\n    }\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/chip/chip_fpga_raw.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"sds\",\n    \"grg\",\n    \"sls\"\n  ],\n  \"key\": {\n    \"s\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"sand\"\n    },\n    \"d\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemDiamond\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotGold\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"l\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemLapis\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:chip_fpga_raw\",\n    \"count\": 16\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/crafting_table.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \" c \",\n    \"wfw\",\n    \" p \"\n  ],\n  \"key\": {\n    \"c\": {\n      \"item\": \"minecraft:crafting_table\"\n    },\n    \"w\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"plankWood\"\n    },\n    \"f\": {\n      \"item\": \"logisticspipes:frame\"\n    },\n    \"p\": {\n      \"item\": \"minecraft:piston\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:crafting_table\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/crafting_table_fuzzy.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"c\",\n    \"t\"\n  ],\n  \"key\": {\n    \"c\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_basic\"\n    },\n    \"t\": {\n      \"item\": \"logisticspipes:crafting_table\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:crafting_table_fuzzy\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/disk.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"iri\",\n    \"rgr\",\n    \"iri\"\n  ],\n  \"key\": {\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"nuggetGold\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:disk\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/guide_book.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:guide_book\"\n  },\n  \"key\": {\n    \"b\": {\n      \"item\": \"minecraft:book\"\n    },\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_transport_basic\"\n    }\n  },\n  \"pattern\": [\n    \"bp\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/logistics_programmer.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \" a \",\n    \"ifi\",\n    \"gmg\"\n  ],\n  \"key\": {\n    \"a\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_advanced\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"f\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_fpga\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotGold\"\n    },\n    \"m\": {\n      \"item\": \"logisticspipes:module_blank\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:logistics_programmer\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/module_blank.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"r\",\n    \"p\",\n    \"g\"\n  ],\n  \"key\": {\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"p\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"paper\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"nuggetGold\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:module_blank\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_basic.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_basic\"\n  },\n  \"key\": {\n    \"f\": {\n      \"item\": \"logisticspipes:chip_fpga\"\n    },\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_transport_basic\"\n    }\n  },\n  \"pattern\": [\n    \"f\",\n    \"p\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_hs_curve.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_hs_curve\"\n  },\n  \"key\": {\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_hs_line\"\n    }\n  },\n  \"pattern\": [\n    \"ppp\",\n    \"p  \",\n    \"p  \"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_hs_gain.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_hs_gain\"\n  },\n  \"key\": {\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_hs_line\"\n    }\n  },\n  \"pattern\": [\n    \"p \",\n    \"pp\",\n    \" p\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_hs_line.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_hs_line\",\n    \"count\": 3\n  },\n  \"key\": {\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_transport_basic\"\n    }\n  },\n  \"pattern\": [\n    \"ppp\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_hs_s_curve.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_hs_s_curve\"\n  },\n  \"key\": {\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_hs_line\"\n    }\n  },\n  \"pattern\": [\n    \"pp \",\n    \" pp\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_hs_speedup.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_hs_speedup\"\n  },\n  \"key\": {\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_hs_line\"\n    }\n  },\n  \"pattern\": [\n    \"ppp\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_request_table.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_request_table\"\n  },\n  \"key\": {\n    \"c\": {\n      \"item\": \"logisticspipes:chip_advanced\"\n    },\n    \"r\": {\n      \"item\": \"logisticspipes:pipe_request_mk2\"\n    },\n    \"f\": {\n      \"item\": \"logisticspipes:frame\"\n    },\n    \"k\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"chestWood\"\n    },\n    \"p\": {\n      \"item\": \"logisticspipes:pipe_crafting\"\n    }\n  },\n  \"pattern\": [\n    \" c \",\n    \"rfp\",\n    \" k \"\n  ]\n}\n"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe/pipe_transport_basic.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"iri\",\n    \"g g\",\n    \"iri\"\n  ],\n  \"key\": {\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"blockGlass\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_transport_basic\",\n    \"count\": 8\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe_controller.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"gbg\",\n    \"rsl\",\n    \"rrl\"\n  ],\n  \"key\": {\n    \"b\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_basic\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotGold\"\n    },\n    \"s\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"blockGlass\"\n    },\n    \"l\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemLapis\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_controller\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/pipe_manager.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"ibi\",\n    \"rsl\",\n    \"rrl\"\n  ],\n  \"key\": {\n    \"b\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_basic\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"s\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"blockGlass\"\n    },\n    \"l\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemLapis\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:pipe_manager\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/power_junction.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \" c \",\n    \"rfr\",\n    \"ibi\"\n  ],\n  \"key\": {\n    \"c\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_basic\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"f\": {\n      \"item\": \"logisticspipes:frame\"\n    },\n    \"b\": {\n      \"item\": \"minecraft:redstone_block\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:power_junction\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/program_compiler.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"result\": {\n    \"item\": \"logisticspipes:program_compiler\"\n  },\n  \"key\": {\n    \"c\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_basic\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"f\": {\n      \"item\": \"logisticspipes:frame\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"l\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemLapis\"\n    }\n  },\n  \"pattern\": [\n    \" c \",\n    \"rfr\",\n    \"ili\"\n  ]\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/remote_orderer.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"aga\",\n    \"rsl\",\n    \"rrl\"\n  ],\n  \"key\": {\n    \"a\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_advanced\"\n    },\n    \"g\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotGold\"\n    },\n    \"s\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"blockGlass\"\n    },\n    \"l\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"gemLapis\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:remote_orderer\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/security_station.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \" g \",\n    \"rfr\",\n    \"iri\"\n  ],\n  \"key\": {\n    \"g\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_advanced\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"f\": {\n      \"item\": \"logisticspipes:frame\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:security_station\"\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/sign_creator.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"b b\",\n    \" s \",\n    \" a \"\n  ],\n  \"key\": {\n    \"a\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_advanced\"\n    },\n    \"b\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_basic\"\n    },\n    \"s\": {\n      \"item\": \"minecraft:sign\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:sign_creator\",\n    \"data\": 0\n  }\n}"
  },
  {
    "path": "resources/assets/logisticspipes/recipes/statistics_table.json",
    "content": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \" g \",\n    \"rfr\",\n    \" i \"\n  ],\n  \"key\": {\n    \"g\": {\n      \"type\": \"logisticspipes:part\",\n      \"part\": \"chip_advanced\"\n    },\n    \"i\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"ingotIron\"\n    },\n    \"r\": {\n      \"type\": \"forge:ore_dict\",\n      \"ore\": \"dustRedstone\"\n    },\n    \"f\": {\n      \"item\": \"logisticspipes:frame\"\n    }\n  },\n  \"result\": {\n    \"item\": \"logisticspipes:statistics_table\"\n  }\n}"
  },
  {
    "path": "resources/logisticspipes/models/BlockModel_result.obj",
    "content": "g Mesh1 OutSide_N Model\nv 25.000000 75.000000 -100.000000\nv 75.000000 75.000000 -100.000000\nv 75.000000 25.000000 -100.000000\nv 25.000000 25.000000 -100.000000\nvt 0.812500 0.583333\nvt 0.812500 0.416667\nvt 0.937500 0.416667\nvt 0.937500 0.583333\nf 2/1 3/2 4/3\nf 1/4 2/1 4/3\ng Mesh2 OutSide_W Model\nv 0.000000 25.000000 -75.000000\nv 0.000000 25.000000 -25.000000\nv 0.000000 75.000000 -25.000000\nv 0.000000 75.000000 -75.000000\nvt 0.187500 0.416667\nvt 0.187500 0.583333\nvt 0.062500 0.583333\nvt 0.062500 0.416667\nf 6/5 7/6 8/7\nf 5/8 6/5 8/7\ng Mesh4 OutSide_E Model\nv 100.000000 25.000000 -75.000000\nv 100.000000 75.000000 -75.000000\nv 100.000000 75.000000 -25.000000\nv 100.000000 25.000000 -25.000000\nvt 0.687500 0.583333\nvt 0.562500 0.583333\nvt 0.562500 0.416667\nvt 0.687500 0.416667\nf 10/9 11/10 12/11\nf 9/12 10/9 12/11\ng Mesh10 Inside_D Model\nv 25.000000 25.000000 -75.000000\nv 25.000000 25.000000 -25.000000\nv 75.000000 25.000000 -25.000000\nv 75.000000 25.000000 -75.000000\nvt 0.625000 0.000000\nvt 0.750000 0.000000\nvt 0.750000 0.166667\nvt 0.625000 0.166667\nf 14/13 15/14 16/15\nf 13/16 14/13 16/15\ng Mesh0 Block Model\nv 25.000000 75.000000 0.000000\nv 25.000000 25.000000 0.000000\nv 25.000000 25.000000 -25.000000\nv 25.000000 75.000000 -25.000000\nv 0.000000 25.000000 -25.000000\nv 0.000000 75.000000 -25.000000\nv 25.000000 25.000000 -75.000000\nv 0.000000 25.000000 -75.000000\nv 25.000000 0.000000 -25.000000\nv 25.000000 0.000000 -75.000000\nv 75.000000 25.000000 -25.000000\nv 75.000000 0.000000 -25.000000\nv 75.000000 25.000000 0.000000\nv 100.000000 0.000000 0.000000\nv 0.000000 0.000000 0.000000\nv 0.000000 100.000000 0.000000\nv 75.000000 75.000000 0.000000\nv 100.000000 100.000000 0.000000\nv 100.000000 75.000000 -25.000000\nv 100.000000 25.000000 -25.000000\nv 100.000000 0.000000 -100.000000\nv 100.000000 25.000000 -75.000000\nv 75.000000 25.000000 -75.000000\nv 75.000000 0.000000 -75.000000\nv 75.000000 25.000000 -100.000000\nv 25.000000 25.000000 -100.000000\nv 75.000000 75.000000 -75.000000\nv 75.000000 75.000000 -100.000000\nv 100.000000 75.000000 -75.000000\nv 100.000000 100.000000 -100.000000\nv 0.000000 0.000000 -100.000000\nv 25.000000 75.000000 -100.000000\nv 0.000000 100.000000 -100.000000\nv 0.000000 75.000000 -75.000000\nv 25.000000 75.000000 -75.000000\nv 75.000000 75.000000 -25.000000\nvt 0.625000 0.916667\nvt 0.687500 0.916667\nvt 0.687500 0.750000\nvt 0.562500 0.916667\nvt 0.625000 0.750000\nvt 0.625000 0.666667\nvt 0.500000 0.666667\nvt 0.500000 0.916667\nvt 0.500000 1.000000\nvt 0.625000 1.000000\nvt 0.875000 0.916667\nvt 0.875000 1.000000\nvt 1.000000 1.000000\nvt 0.750000 0.750000\nvt 0.750000 0.666667\nvt 0.312500 0.416667\nvt 0.500000 0.333333\nvt 0.437500 0.416667\nvt 0.250000 0.333333\nvt 0.312500 0.583333\nvt 0.250000 0.666667\nvt 0.437500 0.583333\nvt 0.562500 0.583333\nvt 0.562500 0.416667\nvt 0.750000 0.333333\nvt 0.687500 0.416667\nvt 0.875000 0.750000\nvt 0.875000 0.666667\nvt 0.750000 0.916667\nvt 0.750000 1.000000\nvt 1.000000 0.750000\nvt 0.937500 0.750000\nvt 0.812500 0.916667\nvt 0.687500 0.583333\nvt 0.812500 0.583333\nvt 0.812500 0.416667\nvt 1.000000 0.333333\nvt 0.937500 0.416667\nvt 0.937500 0.583333\nvt 1.000000 0.666667\nvt 0.000000 0.333333\nvt 0.062500 0.583333\nvt 0.000000 0.666667\nvt 0.062500 0.416667\nvt 0.187500 0.416667\nvt 0.250000 0.000000\nvt 0.312500 0.250000\nvt 0.312500 0.083333\nvt 0.500000 0.000000\nvt 0.437500 0.083333\nvt 0.437500 0.250000\nvt 0.187500 0.583333\nvt 0.250683 0.666667\nvt 0.499317 0.666667\nvt 0.499317 1.000000\nvt 0.562500 0.750000\nvt 0.500000 0.750000\nvt 0.937500 0.916667\nvt 1.000000 0.916667\nvt 0.812500 0.750000\nvt 0.062500 0.916667\nvt 0.187500 0.916667\nvt 0.187500 0.750000\nvt 0.250683 1.000000\nvt 0.000000 0.750000\nvt 0.000000 0.916667\nvt 0.187500 0.666667\nvt 0.062500 0.666667\nvt 0.062500 0.750000\nvt 0.062500 1.000000\nvt 0.187500 1.000000\nvt 0.250000 0.916667\nvt 0.250000 0.750000\nf 18/17 19/18 20/19\nf 19/20 21/17 22/21\nf 23/21 24/22 21/23\nf 19/24 25/25 26/26\nf 27/27 28/28 25/29\nf 19/30 18/31 29/22\nf 18/32 30/33 29/34\nf 30/33 18/32 31/35\nf 18/32 17/36 31/35\nf 31/35 17/36 32/37\nf 32/37 17/36 33/38\nf 32/37 33/38 34/23\nf 30/33 34/23 33/38\nf 30/33 35/39 34/23\nf 35/39 30/33 36/40\nf 37/41 36/40 30/33\nf 38/42 36/40 37/41\nf 27/43 36/44 38/31\nf 27/27 39/45 40/46\nf 23/17 26/26 40/46\nf 39/44 41/43 42/47\nf 43/48 44/43 41/27\nf 39/49 38/27 45/43\nf 38/42 46/31 45/50\nf 46/31 38/42 37/41\nf 37/41 44/51 46/31\nf 41/52 44/51 37/41\nf 47/53 41/52 37/41\nf 41/52 47/53 42/54\nf 42/54 47/53 48/55\nf 47/53 49/56 48/55\nf 47/57 50/58 49/59\nf 50/58 47/57 24/60\nf 24/60 47/57 21/61\nf 47/57 31/35 21/61\nf 47/62 25/63 31/35\nf 25/63 47/62 26/64\nf 37/65 26/64 47/62\nf 40/66 26/64 37/65\nf 30/33 40/66 37/65\nf 40/66 30/33 28/67\nf 28/67 30/33 25/63\nf 30/33 31/35 25/63\nf 32/37 21/61 31/35\nf 21/61 32/37 22/68\nf 49/59 22/68 32/37\nf 50/58 22/68 49/59\nf 32/69 34/70 46/71\nf 46/31 34/23 35/39\nf 45/50 46/31 35/39\nf 46/31 48/55 49/56\nf 48/55 46/31 44/51\nf 51/72 50/73 24/24\nf 23/74 42/75 48/47\nf 52/76 35/30 36/45\nf 27/18 29/45 33/30\nf 29/34 30/33 33/38\nf 51/77 43/78 52/79\nf 17/21 18/17 20/19\nf 20/72 19/20 22/21\nf 19/73 23/21 21/23\nf 23/17 19/24 26/26\nf 19/75 27/27 25/29\nf 27/21 19/30 29/22\nf 39/30 27/43 38/31\nf 28/28 27/27 40/46\nf 39/45 23/17 40/46\nf 23/56 39/44 42/47\nf 39/74 43/48 41/27\nf 43/76 39/49 45/43\nf 49/80 32/69 46/71\nf 23/20 51/72 24/24\nf 51/48 23/74 48/47\nf 27/49 52/76 36/45\nf 52/19 27/18 33/30\nf 22/81 50/82 51/77\nf 33/83 17/84 20/85\nf 20/85 22/81 51/77\nf 51/77 48/86 44/87\nf 43/78 45/88 35/89\nf 51/77 44/87 43/78\nf 51/77 52/79 20/85\nf 43/78 35/89 52/79\nf 52/79 33/83 20/85\ng Mesh8 Inside_S Model\nv 75.000000 25.000000 -25.000000\nv 25.000000 25.000000 -25.000000\nv 25.000000 75.000000 -25.000000\nv 75.000000 75.000000 -25.000000\nvt 0.750000 0.166667\nvt 0.750000 0.333333\nvt 0.625000 0.333333\nvt 0.625000 0.166667\nf 54/90 55/91 56/92\nf 53/93 54/90 56/92\ng Mesh7 Inside_W Model\nv 25.000000 25.000000 -25.000000\nv 25.000000 25.000000 -75.000000\nv 25.000000 75.000000 -75.000000\nv 25.000000 75.000000 -25.000000\nvt 0.625000 0.166667\nvt 0.625000 0.333333\nvt 0.500000 0.333333\nvt 0.500000 0.166667\nf 58/94 59/95 60/96\nf 57/97 58/94 60/96\ng Mesh6 Inside_N Model\nv 25.000000 75.000000 -75.000000\nv 25.000000 25.000000 -75.000000\nv 75.000000 25.000000 -75.000000\nv 75.000000 75.000000 -75.000000\nvt 0.500000 0.000000\nvt 0.625000 0.000000\nvt 0.625000 0.166667\nvt 0.500000 0.166667\nf 62/98 63/99 64/100\nf 61/101 62/98 64/100\ng Mesh5 OutSide_S Model\nv 75.000000 25.000000 0.000000\nv 75.000000 75.000000 0.000000\nv 25.000000 75.000000 0.000000\nv 25.000000 25.000000 0.000000\nvt 0.437500 0.583333\nvt 0.312500 0.583333\nvt 0.312500 0.416667\nvt 0.437500 0.416667\nf 66/102 67/103 68/104\nf 65/105 66/102 68/104\ng Mesh9 Inside_E Model\nv 75.000000 75.000000 -25.000000\nv 75.000000 75.000000 -75.000000\nv 75.000000 25.000000 -75.000000\nv 75.000000 25.000000 -25.000000\nvt 0.750000 0.333333\nvt 0.750000 0.166667\nvt 0.875000 0.166667\nvt 0.875000 0.333333\nf 70/106 71/107 72/108\nf 69/109 70/106 72/108\ng Mesh3 OutSide_D Model\nv 25.000000 0.000000 -75.000000\nv 75.000000 0.000000 -75.000000\nv 75.000000 0.000000 -25.000000\nv 25.000000 0.000000 -25.000000\nvt 0.312500 0.250000\nvt 0.312500 0.083333\nvt 0.437500 0.083333\nvt 0.437500 0.250000\nf 74/110 75/111 76/112\nf 73/113 74/110 76/112\n"
  },
  {
    "path": "resources/logisticspipes/models/HSTube-Gain_result.obj",
    "content": "g Mesh7 Mount_L_U MountG1 Model\nv 25.000000 82.703506 -52.990284\nv 20.000000 77.719604 -53.391289\nv 0.000000 77.719604 -53.391289\nv 0.000000 82.703506 -52.990284\nv 20.000000 77.238411 -47.410690\nv 25.000000 82.222305 -47.009686\nv 25.000000 82.623306 -51.993584\nv 0.000000 77.238411 -47.410690\nv 0.000000 82.222305 -47.009686\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.870000 0.190000\nvt 0.700000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.000000\nvt 0.650000 0.130000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.190000\nvt 0.930000 0.210000\nvt 0.650000 0.190000\nf 2/1 3/2 4/3\nf 2/4 5/5 7/6\nf 5/2 8/1 3/7\nf 9/8 8/9 5/10\nf 4/4 3/11 8/8\nf 7/12 4/3 9/13\nf 1/14 2/1 4/3\nf 5/5 6/15 7/6\nf 7/6 1/13 2/4\nf 2/11 5/2 3/7\nf 6/16 9/8 5/10\nf 9/5 4/4 8/8\nf 4/3 7/12 1/14\nf 7/12 9/13 6/17\ng Mesh12 Mount_L_D1 MountG2 Model\nv -0.000000 117.778061 -353.381958\nv -0.000000 122.762062 -352.980957\nv 20.000000 122.762062 -352.980957\nv 25.000000 117.778061 -353.381958\nv -0.000000 117.297050 -347.400970\nv -0.000000 122.280052 -346.999969\nv 25.000000 117.297050 -347.400970\nv 20.000000 122.280052 -346.999969\nv 25.000000 117.698059 -352.384979\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.190000\nvt 0.860000 0.120000\nvt 0.930000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.870000 -0.000000\nvt 0.930000 0.050000\nvt 0.650000 0.180000\nvt 0.650000 0.120000\nvt 0.700000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.050000\nvt 0.860000 -0.000000\nvt 0.650000 0.190000\nf 10/18 11/19 12/20\nf 15/21 11/22 10/23\nf 17/24 15/25 14/22\nf 18/26 16/18 17/27\nf 18/28 16/29 14/22\nf 15/25 17/24 12/30\nf 13/31 10/18 12/20\nf 14/32 15/21 10/23\nf 16/29 17/24 14/22\nf 12/33 13/34 18/26\nf 18/26 17/27 12/33\nf 10/21 13/35 18/28\nf 18/28 14/22 10/21\nf 11/34 15/25 12/30\ng Mesh19 Mount_U_R1 MountG2 Model\nv 80.000000 200.000061 -347.890961\nv 75.000000 200.000061 -347.890961\nv 75.000000 177.353058 -347.890961\nv 80.000000 172.353058 -347.890961\nv 80.000000 200.000061 -353.890961\nv 75.000000 200.000061 -353.890961\nv 80.000000 172.834061 -353.890961\nv 75.000000 177.834061 -353.890961\nvt 0.930000 -0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.190000\nvt 0.860000 0.110000\nvt 0.930000 0.110000\nvt 0.860000 0.120000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.650000 0.190000\nvt 0.930000 0.020000\nvt 0.860000 0.100000\nvt 0.860000 0.020000\nvt 0.930000 0.100000\nvt 0.700000 0.000000\nvt 0.860000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.070000\nf 19/36 20/37 21/38\nf 24/39 20/40 19/41\nf 23/42 25/43 26/44\nf 19/39 22/45 25/43\nf 21/46 25/47 22/48\nf 26/49 25/47 21/46\nf 26/44 21/50 20/51\nf 22/52 19/36 21/38\nf 23/53 24/39 19/41\nf 24/54 23/42 26/44\nf 23/42 19/39 25/43\nf 24/54 26/44 20/51\ng Mesh6 Mount_L_D MountG1 Model\nv 0.000000 22.663509 -52.892895\nv 0.000000 27.647408 -52.491898\nv 20.000000 27.647408 -52.491898\nv 25.000000 22.663509 -52.892895\nv 0.000000 22.182308 -46.912296\nv 0.000000 27.166208 -46.511295\nv 25.000000 22.182308 -46.912296\nv 20.000000 27.166208 -46.511295\nv 25.000000 22.583307 -51.896194\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.190000\nvt 0.860000 0.120000\nvt 0.930000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.870000 -0.000000\nvt 0.930000 0.050000\nvt 0.650000 0.180000\nvt 0.650000 0.120000\nvt 0.700000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.050000\nvt 0.860000 -0.000000\nvt 0.650000 0.190000\nf 27/55 28/56 29/57\nf 32/58 28/59 27/60\nf 34/61 32/62 31/59\nf 35/63 33/55 34/64\nf 35/65 33/66 31/59\nf 32/62 34/61 29/67\nf 30/68 27/55 29/57\nf 31/69 32/58 27/60\nf 33/66 34/61 31/59\nf 29/70 30/71 35/63\nf 35/63 34/64 29/70\nf 27/58 30/72 35/65\nf 35/65 31/59 27/58\nf 28/71 32/62 29/67\ng Mesh5 Mount_R_D MountG1 Model\nv 100.000000 22.182308 -46.912296\nv 100.000000 27.166208 -46.511295\nv 80.000000 27.166208 -46.511295\nv 75.000000 22.182308 -46.912296\nv 100.000000 22.663509 -52.892895\nv 100.000000 27.647408 -52.491898\nv 75.000000 22.663509 -52.892895\nv 80.000000 27.647408 -52.491898\nv 75.000000 22.262508 -47.908997\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.190000\nvt 0.860000 0.190000\nvt 0.860000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.870000 -0.000000\nvt 0.930000 0.050000\nvt 0.650000 0.180000\nvt 0.650000 0.120000\nvt 0.700000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.120000\nvt 0.860000 0.050000\nvt 0.860000 -0.000000\nvt 0.650000 0.190000\nf 36/73 37/74 38/75\nf 40/76 41/77 37/78\nf 43/79 41/80 40/78\nf 44/81 42/73 43/82\nf 44/83 42/84 40/78\nf 41/80 43/79 38/85\nf 39/86 36/73 38/75\nf 36/87 40/76 37/78\nf 42/84 43/79 40/78\nf 38/88 39/89 44/81\nf 44/81 43/82 38/88\nf 36/77 39/90 44/83\nf 44/83 40/78 36/77\nf 37/89 41/80 38/85\ng Mesh10 Mount_D_R MountG1 Model\nv 80.000000 0.000009 -52.500000\nv 75.000000 0.000009 -52.500000\nv 75.000000 22.647507 -52.499996\nv 80.000000 27.647507 -52.499996\nv 80.000000 0.000008 -46.500000\nv 75.000000 0.000008 -46.500000\nv 80.000000 27.165907 -46.499996\nv 75.000000 22.165907 -46.499996\nvt 0.930000 -0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.190000\nvt 0.860000 0.110000\nvt 0.930000 0.110000\nvt 0.860000 0.120000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.650000 0.190000\nvt 0.930000 0.020000\nvt 0.860000 0.100000\nvt 0.860000 0.020000\nvt 0.930000 0.100000\nvt 0.700000 0.000000\nvt 0.860000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.070000\nf 45/91 46/92 47/93\nf 50/94 46/95 45/96\nf 49/97 51/98 52/99\nf 45/94 48/100 51/98\nf 47/101 51/102 48/103\nf 52/104 51/102 47/101\nf 52/99 47/105 46/106\nf 48/107 45/91 47/93\nf 49/108 50/94 45/96\nf 50/109 49/97 52/99\nf 49/97 45/94 51/98\nf 50/109 52/99 46/106\ng Mesh16 Mount_D_R1 MountG2 Model\nv 80.000000 100.000061 -353.390961\nv 75.000000 100.000061 -353.390961\nv 75.000000 117.794060 -353.390961\nv 80.000000 122.794060 -353.390961\nv 80.000000 100.000053 -347.390961\nv 75.000000 100.000053 -347.390961\nv 80.000000 122.317055 -347.390961\nv 75.000000 117.312050 -347.390961\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.010000\nvt 0.930000 0.010000\nvt 0.930000 0.060000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nvt 0.860000 0.080000\nvt 0.650000 0.120000\nvt 0.860000 0.190000\nvt 0.860000 -0.000000\nvt 0.930000 0.210000\nvt 0.860000 0.060000\nvt 0.930000 0.080000\nvt 0.650000 0.190000\nvt 0.700000 0.000000\nf 53/110 54/111 55/112\nf 58/113 54/114 53/115\nf 60/116 58/117 57/118\nf 59/119 56/120 55/121\nf 59/122 57/118 53/123\nf 60/124 55/117 54/116\nf 56/125 53/110 55/112\nf 57/126 58/113 53/115\nf 59/122 60/116 57/118\nf 60/127 59/119 55/121\nf 56/128 59/122 53/123\nf 58/129 60/124 54/116\ng Mesh0 Lane Model\nv 70.000000 110.200027 -169.599991\nv 75.000000 110.200027 -169.599991\nv 75.000000 103.175026 -153.649979\nv 70.000000 103.175026 -153.649979\nv 70.000000 117.525032 -184.949982\nv 75.000000 117.525032 -184.949982\nv 70.000000 125.000031 -199.999985\nv 75.000000 125.000031 -199.999985\nv 70.000000 132.475037 -215.049988\nv 75.000000 132.475037 -215.049988\nv 70.000000 139.800034 -230.399979\nv 75.000000 139.800034 -230.399979\nv 70.000000 146.825043 -246.349976\nv 75.000000 146.825043 -246.349976\nv 70.000000 153.400040 -263.199982\nv 75.000000 153.400040 -263.199982\nv 70.000000 159.375046 -281.249969\nv 75.000000 159.375046 -281.249969\nv 70.000000 164.600052 -300.799957\nv 75.000000 164.600052 -300.799957\nv 70.000000 168.925049 -322.149963\nv 75.000000 168.925049 -322.149963\nv 70.000000 172.200058 -345.599976\nv 75.000000 172.200058 -345.599976\nv 70.000000 174.275055 -371.449982\nv 75.000000 174.275055 -371.449982\nv 70.000000 175.000061 -399.999969\nv 75.000000 175.000061 -399.999969\nv 70.000000 180.000061 -399.999969\nv 70.000000 96.600021 -136.799988\nv 70.000000 90.625023 -118.749985\nv 70.000000 85.400017 -99.199982\nv 70.000000 81.075012 -77.849983\nv 70.000000 77.800011 -54.399990\nv 70.000000 75.725006 -28.549988\nv 70.000000 75.000000 0.000012\nv 70.000000 80.000000 0.000013\nv 70.000000 80.725006 -28.549986\nv 70.000000 82.800011 -54.399986\nv 70.000000 86.075012 -77.849983\nv 70.000000 90.400017 -99.199982\nv 70.000000 95.625023 -118.749985\nv 70.000000 101.600021 -136.799988\nv 70.000000 108.175026 -153.649979\nv 70.000000 115.200027 -169.599991\nv 70.000000 122.525032 -184.949982\nv 70.000000 130.000031 -199.999985\nv 70.000000 137.475037 -215.049988\nv 70.000000 144.800034 -230.399963\nv 70.000000 151.825043 -246.349976\nv 70.000000 158.400040 -263.199982\nv 70.000000 164.375046 -281.249969\nv 70.000000 169.600052 -300.799957\nv 70.000000 173.925049 -322.149963\nv 70.000000 177.200058 -345.599976\nv 70.000000 179.275055 -371.449982\nv 75.000000 180.000061 -399.999969\nv 80.000000 175.000061 -399.999969\nv 80.000000 170.000061 -399.999969\nv 75.000000 170.000061 -399.999969\nv 75.000000 179.275055 -371.449982\nv 75.000000 177.200058 -345.599976\nv 75.000000 173.925049 -322.149963\nv 75.000000 169.600052 -300.799957\nv 75.000000 164.375046 -281.249969\nv 75.000000 158.400040 -263.199982\nv 75.000000 151.825043 -246.349976\nv 75.000000 144.800034 -230.399963\nv 75.000000 137.475037 -215.049988\nv 75.000000 130.000031 -199.999985\nv 75.000000 122.525032 -184.949982\nv 75.000000 115.200027 -169.599991\nv 75.000000 108.175026 -153.649979\nv 75.000000 101.600021 -136.799988\nv 75.000000 95.625023 -118.749985\nv 75.000000 90.400017 -99.199982\nv 75.000000 86.075012 -77.849983\nv 75.000000 82.800011 -54.399986\nv 75.000000 80.725006 -28.549986\nv 75.000000 80.000000 0.000013\nv 75.000000 75.000000 0.000012\nv 75.000000 70.000000 0.000011\nv 80.000000 70.000000 0.000011\nv 80.000000 75.000000 0.000012\nv 75.000000 75.725006 -28.549988\nv 75.000000 77.800011 -54.399990\nv 75.000000 81.075012 -77.849983\nv 75.000000 85.400017 -99.199982\nv 75.000000 90.625023 -118.749985\nv 75.000000 96.600021 -136.799988\nv 75.000000 169.275055 -371.449982\nv 75.000000 167.200058 -345.599976\nv 75.000000 163.925049 -322.149963\nv 75.000000 159.600052 -300.799957\nv 75.000000 154.375046 -281.249969\nv 75.000000 148.400040 -263.199982\nv 75.000000 141.825043 -246.349976\nv 75.000000 134.800034 -230.399979\nv 75.000000 127.475037 -215.049988\nv 75.000000 120.000031 -199.999985\nv 75.000000 112.525032 -184.949982\nv 75.000000 105.200027 -169.599991\nv 75.000000 98.175026 -153.649979\nv 75.000000 91.600021 -136.799988\nv 75.000000 85.625023 -118.749985\nv 75.000000 80.400017 -99.199982\nv 75.000000 76.075012 -77.849983\nv 75.000000 72.800011 -54.399990\nv 75.000000 70.725006 -28.549988\nv 80.000000 169.275055 -371.449982\nv 80.000000 167.200058 -345.599976\nv 80.000000 163.925049 -322.149963\nv 80.000000 159.600052 -300.799957\nv 80.000000 154.375046 -281.249969\nv 80.000000 148.400040 -263.199982\nv 80.000000 141.825043 -246.349976\nv 80.000000 134.800034 -230.399979\nv 80.000000 127.475037 -215.049988\nv 80.000000 120.000031 -199.999985\nv 80.000000 112.525032 -184.949982\nv 80.000000 105.200027 -169.599991\nv 80.000000 98.175026 -153.649979\nv 80.000000 91.600021 -136.799988\nv 80.000000 85.625023 -118.749985\nv 80.000000 80.400017 -99.199982\nv 80.000000 76.075012 -77.849983\nv 80.000000 72.800011 -54.399990\nv 80.000000 70.725006 -28.549988\nv 80.000000 174.275055 -371.449982\nv 80.000000 172.200058 -345.599976\nv 80.000000 168.925049 -322.149963\nv 80.000000 164.600052 -300.799957\nv 80.000000 159.375046 -281.249969\nv 80.000000 153.400040 -263.199982\nv 80.000000 146.825043 -246.349976\nv 80.000000 139.800034 -230.399979\nv 80.000000 132.475037 -215.049988\nv 80.000000 125.000031 -199.999985\nv 80.000000 117.525032 -184.949982\nv 80.000000 110.200027 -169.599991\nv 80.000000 103.175026 -153.649979\nv 80.000000 96.600021 -136.799988\nv 80.000000 90.625023 -118.749985\nv 80.000000 85.400017 -99.199982\nv 80.000000 81.075012 -77.849983\nv 80.000000 77.800011 -54.399990\nv 80.000000 75.725006 -28.549988\nvt 0.400000 1.000000\nvt 0.000000 1.000000\nvt -0.000000 0.950000\nvt -0.000000 0.580000\nvt 0.400000 0.580000\nvt 0.400000 0.630000\nvt 0.700000 1.000000\nvt 0.750000 0.950000\nvt 0.700000 0.950000\nvt 0.000000 0.480000\nvt 0.400000 0.480000\nvt 0.400000 0.530000\nvt -0.000000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.900000\nvt 0.800000 0.530000\nvt 0.650000 1.000000\nvt 0.800000 0.630000\nvt -0.000000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.360000\nvt -0.000000 0.680000\nvt 0.400000 0.680000\nvt 0.400000 0.730000\nvt 0.800000 0.360000\nvt 0.000000 0.630000\nvt 0.000000 0.410000\nvt 0.400000 0.410000\nvt -0.000000 0.780000\nvt 0.400000 0.780000\nvt 0.800000 0.410000\nvt 0.800000 0.480000\nvt -0.000000 0.900000\nvt 0.400000 0.950000\nvt 0.800000 0.580000\nvt 0.000000 0.530000\nvt 0.000000 0.360000\nvt 0.000000 0.730000\nvt 0.800000 0.260000\nvt 0.400000 0.260000\nvt -0.000000 0.260000\nvt 0.650000 0.950000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nvt 0.800000 0.310000\nf 62/130 63/131 64/132\nf 66/130 62/131 61/132\nf 68/130 66/131 65/132\nf 70/130 68/131 67/132\nf 72/130 70/131 69/132\nf 74/130 72/131 71/132\nf 76/130 74/131 73/132\nf 78/130 76/131 75/132\nf 80/130 78/131 77/132\nf 82/130 80/131 79/132\nf 84/130 82/131 81/132\nf 86/130 84/131 83/132\nf 85/133 87/134 88/135\nf 117/136 118/137 88/138\nf 121/139 117/140 89/141\nf 122/142 121/143 116/144\nf 123/142 122/143 115/144\nf 124/142 123/143 114/144\nf 125/142 124/143 113/144\nf 126/142 125/143 112/144\nf 127/142 126/143 111/144\nf 128/142 127/143 110/144\nf 129/142 128/143 109/144\nf 130/142 129/143 108/144\nf 131/142 130/143 107/144\nf 132/142 131/143 106/144\nf 133/142 132/143 105/144\nf 134/142 133/143 104/144\nf 135/142 134/143 103/144\nf 136/142 135/143 102/144\nf 137/142 136/143 101/144\nf 138/142 137/143 100/144\nf 139/142 138/143 99/144\nf 98/145 97/141 140/140\nf 140/136 97/146 141/138\nf 145/147 141/135 96/134\nf 146/130 145/131 95/132\nf 147/130 146/131 94/132\nf 148/130 147/131 93/132\nf 149/130 148/131 92/132\nf 150/130 149/131 91/132\nf 63/130 150/131 90/132\nf 151/148 120/149 119/150\nf 152/151 151/152 170/153\nf 153/151 152/152 171/153\nf 154/151 153/152 172/153\nf 155/151 154/152 173/153\nf 156/151 155/152 174/153\nf 157/151 156/152 175/153\nf 158/151 157/152 176/153\nf 159/151 158/152 177/153\nf 160/151 159/152 178/153\nf 161/151 160/152 179/153\nf 162/151 161/152 180/153\nf 163/151 162/152 181/153\nf 164/151 163/152 182/153\nf 165/151 164/152 183/153\nf 166/151 165/152 184/153\nf 167/151 166/152 185/153\nf 168/151 167/152 186/153\nf 169/151 168/152 187/153\nf 188/154 143/150 142/149\nf 84/155 86/135 151/152\nf 121/139 189/156 118/157\nf 122/142 190/158 189/159\nf 123/142 191/158 190/159\nf 124/142 192/158 191/159\nf 125/142 193/158 192/159\nf 126/142 194/158 193/159\nf 127/142 195/158 194/159\nf 128/142 196/158 195/159\nf 129/142 197/158 196/159\nf 130/142 198/158 197/159\nf 131/142 199/158 198/159\nf 132/142 200/158 199/159\nf 133/142 201/158 200/159\nf 134/142 202/158 201/159\nf 135/142 203/158 202/159\nf 136/142 204/158 203/159\nf 137/142 205/158 204/159\nf 138/142 206/158 205/159\nf 139/142 207/158 206/159\nf 207/160 139/161 140/140\nf 114/162 115/144 83/163\nf 79/163 77/132 112/162\nf 77/163 75/132 111/162\nf 73/163 71/132 109/162\nf 95/164 96/134 97/141\nf 94/163 95/132 98/162\nf 75/163 73/132 110/162\nf 93/163 94/132 99/162\nf 71/163 69/132 108/162\nf 92/163 93/132 100/162\nf 107/162 108/144 69/163\nf 115/162 116/144 85/163\nf 91/163 92/132 101/162\nf 102/162 103/144 90/163\nf 81/163 79/132 113/162\nf 103/162 104/144 64/163\nf 104/162 105/144 61/163\nf 105/162 106/144 65/163\nf 67/163 65/132 106/162\nf 87/134 85/133 116/165\nf 189/156 170/166 119/150\nf 179/153 198/159 199/158\nf 180/153 199/159 200/158\nf 190/158 171/167 170/153\nf 177/153 196/159 197/158\nf 181/153 200/159 201/158\nf 165/152 166/151 148/155\nf 191/158 172/167 171/153\nf 202/158 183/167 182/153\nf 183/153 202/159 203/158\nf 68/155 70/135 159/152\nf 192/158 173/167 172/153\nf 176/153 195/159 196/158\nf 205/158 186/167 185/153\nf 167/152 168/151 146/155\nf 193/158 174/167 173/153\nf 206/158 187/167 186/153\nf 207/158 188/167 187/153\nf 169/168 142/169 141/149\nf 174/153 193/159 194/158\nf 144/157 143/150 188/154\nf 175/153 194/159 195/158\nf 184/153 203/159 204/158\nf 154/152 155/151 78/155\nf 157/152 158/151 72/155\nf 168/152 169/151 145/155\nf 149/155 150/135 164/152\nf 166/152 167/151 147/155\nf 156/152 157/151 74/155\nf 120/149 151/148 86/170\nf 82/155 84/135 152/152\nf 155/152 156/151 76/155\nf 178/153 197/159 198/158\nf 153/152 154/151 80/155\nf 150/155 63/135 163/152\nf 63/155 62/135 162/152\nf 62/155 66/135 161/152\nf 160/152 161/151 66/155\nf 158/152 159/151 70/155\nf 61/163 62/130 64/132\nf 65/163 66/130 61/132\nf 67/163 68/130 65/132\nf 69/163 70/130 67/132\nf 71/163 72/130 69/132\nf 73/163 74/130 71/132\nf 75/163 76/130 73/132\nf 77/163 78/130 75/132\nf 79/163 80/130 77/132\nf 81/163 82/130 79/132\nf 83/163 84/130 81/132\nf 85/163 86/130 83/132\nf 86/155 85/133 88/135\nf 88/138 87/171 89/146\nf 119/172 120/173 88/138\nf 88/138 118/137 119/172\nf 88/138 89/146 117/136\nf 116/165 121/139 89/141\nf 115/162 122/142 116/144\nf 114/162 123/142 115/144\nf 113/162 124/142 114/144\nf 112/162 125/142 113/144\nf 111/162 126/142 112/144\nf 110/162 127/142 111/144\nf 109/162 128/142 110/144\nf 108/162 129/142 109/144\nf 107/162 130/142 108/144\nf 106/162 131/142 107/144\nf 105/162 132/142 106/144\nf 104/162 133/142 105/144\nf 103/162 134/142 104/144\nf 102/162 135/142 103/144\nf 101/162 136/142 102/144\nf 100/162 137/142 101/144\nf 99/162 138/142 100/144\nf 98/162 139/142 99/144\nf 139/161 98/145 140/140\nf 141/138 144/137 140/136\nf 141/138 142/173 143/172\nf 97/146 96/171 141/138\nf 141/138 143/172 144/137\nf 95/164 145/147 96/134\nf 94/163 146/130 95/132\nf 93/163 147/130 94/132\nf 92/163 148/130 93/132\nf 91/163 149/130 92/132\nf 90/163 150/130 91/132\nf 64/163 63/130 90/132\nf 170/166 151/148 119/150\nf 171/167 152/151 170/153\nf 172/167 153/151 171/153\nf 173/167 154/151 172/153\nf 174/167 155/151 173/153\nf 175/167 156/151 174/153\nf 176/167 157/151 175/153\nf 177/167 158/151 176/153\nf 178/167 159/151 177/153\nf 179/167 160/151 178/153\nf 180/167 161/151 179/153\nf 181/167 162/151 180/153\nf 182/167 163/151 181/153\nf 183/167 164/151 182/153\nf 184/167 165/151 183/153\nf 185/167 166/151 184/153\nf 186/167 167/151 185/153\nf 187/167 168/151 186/153\nf 188/167 169/151 187/153\nf 169/174 188/154 142/149\nf 152/151 84/155 151/152\nf 117/140 121/139 118/157\nf 121/143 122/142 189/159\nf 122/143 123/142 190/159\nf 123/143 124/142 191/159\nf 124/143 125/142 192/159\nf 125/143 126/142 193/159\nf 126/143 127/142 194/159\nf 127/143 128/142 195/159\nf 128/143 129/142 196/159\nf 129/143 130/142 197/159\nf 130/143 131/142 198/159\nf 131/143 132/142 199/159\nf 132/143 133/142 200/159\nf 133/143 134/142 201/159\nf 134/143 135/142 202/159\nf 135/143 136/142 203/159\nf 136/143 137/142 204/159\nf 137/143 138/142 205/159\nf 138/143 139/142 206/159\nf 144/157 207/160 140/140\nf 81/132 114/162 83/163\nf 113/144 79/163 112/162\nf 112/144 77/163 111/162\nf 110/144 73/163 109/162\nf 98/145 95/164 97/141\nf 99/144 94/163 98/162\nf 111/144 75/163 110/162\nf 100/144 93/163 99/162\nf 109/144 71/163 108/162\nf 101/144 92/163 100/162\nf 67/132 107/162 69/163\nf 83/132 115/162 85/163\nf 102/144 91/163 101/162\nf 91/132 102/162 90/163\nf 114/144 81/163 113/162\nf 90/132 103/162 64/163\nf 64/132 104/162 61/163\nf 61/132 105/162 65/163\nf 107/144 67/163 106/162\nf 89/141 87/134 116/165\nf 118/157 189/156 119/150\nf 180/167 179/153 199/158\nf 181/167 180/153 200/158\nf 189/159 190/158 170/153\nf 178/167 177/153 197/158\nf 182/167 181/153 201/158\nf 149/135 165/152 148/155\nf 190/159 191/158 171/153\nf 201/159 202/158 182/153\nf 184/167 183/153 203/158\nf 160/151 68/155 159/152\nf 191/159 192/158 172/153\nf 177/167 176/153 196/158\nf 204/159 205/158 185/153\nf 147/135 167/152 146/155\nf 192/159 193/158 173/153\nf 205/159 206/158 186/153\nf 206/159 207/158 187/153\nf 145/174 169/168 141/149\nf 175/167 174/153 194/158\nf 207/160 144/157 188/154\nf 176/167 175/153 195/158\nf 185/167 184/153 204/158\nf 80/135 154/152 78/155\nf 74/135 157/152 72/155\nf 146/135 168/152 145/155\nf 165/151 149/155 164/152\nf 148/135 166/152 147/155\nf 76/135 156/152 74/155\nf 88/169 120/149 86/170\nf 153/151 82/155 152/152\nf 78/135 155/152 76/155\nf 179/167 178/153 198/158\nf 82/135 153/152 80/155\nf 164/151 150/155 163/152\nf 163/151 63/155 162/152\nf 162/151 62/155 161/152\nf 68/135 160/152 66/155\nf 72/135 158/152 70/155\ng Mesh14 Mount_R_U1 MountG2 Model\nv 75.000000 177.336060 -347.497955\nv 80.000000 172.353058 -347.898956\nv 100.000000 172.353058 -347.898956\nv 100.000000 177.336060 -347.497955\nv 80.000000 172.834061 -353.879974\nv 75.000000 177.818054 -353.478973\nv 75.000000 177.417068 -348.494965\nv 100.000000 172.834061 -353.879974\nv 100.000000 177.818054 -353.478973\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.870000 0.190000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.700000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.000000\nvt 0.650000 0.130000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.190000\nvt 0.930000 0.210000\nvt 0.650000 0.190000\nf 209/175 210/176 211/177\nf 214/178 209/179 212/180\nf 212/176 215/175 210/181\nf 216/182 215/183 212/184\nf 211/179 210/185 215/182\nf 214/186 211/177 216/187\nf 208/188 209/175 211/177\nf 209/179 214/178 208/187\nf 214/178 212/180 213/189\nf 209/185 212/176 210/181\nf 213/190 216/182 212/184\nf 216/180 211/179 215/182\nf 211/177 214/186 208/188\nf 214/186 216/187 213/191\ng Mesh4 Mount_R_U MountG1 Model\nv 75.000000 82.222305 -47.009686\nv 80.000000 77.238411 -47.410690\nv 100.000000 77.238411 -47.410690\nv 100.000000 82.222305 -47.009686\nv 80.000000 77.719604 -53.391289\nv 75.000000 82.703506 -52.990284\nv 75.000000 82.302505 -48.006386\nv 100.000000 77.719604 -53.391289\nv 100.000000 82.703506 -52.990284\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.870000 0.190000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.700000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.000000\nvt 0.650000 0.130000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.190000\nvt 0.930000 0.210000\nvt 0.650000 0.190000\nf 218/192 219/193 220/194\nf 223/195 218/196 221/197\nf 221/193 224/192 219/198\nf 225/199 224/200 221/201\nf 219/202 224/199 225/197\nf 223/203 220/194 225/204\nf 217/205 218/192 220/194\nf 218/196 223/195 217/204\nf 223/195 221/197 222/206\nf 218/202 221/193 219/198\nf 222/207 225/199 221/201\nf 220/196 219/202 225/197\nf 220/194 223/203 217/205\nf 223/203 225/204 222/208\ng Mesh9 Mount_U_R MountG1 Model\nv 80.000000 100.000008 -46.999985\nv 75.000000 100.000008 -46.999985\nv 75.000000 82.206009 -46.999985\nv 80.000000 77.206009 -46.999989\nv 80.000000 100.000008 -52.999985\nv 75.000000 100.000008 -52.999985\nv 80.000000 77.682709 -52.999989\nv 75.000000 82.687607 -52.999985\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.010000\nvt 0.930000 0.010000\nvt 0.930000 0.060000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nvt 0.860000 0.080000\nvt 0.650000 0.120000\nvt 0.860000 0.190000\nvt 0.860000 -0.000000\nvt 0.930000 0.210000\nvt 0.860000 0.060000\nvt 0.930000 0.080000\nvt 0.650000 0.190000\nvt 0.700000 0.000000\nf 226/209 227/210 228/211\nf 231/212 227/213 226/214\nf 233/215 231/216 230/217\nf 232/218 229/219 228/220\nf 232/221 230/217 226/222\nf 233/223 228/216 227/215\nf 229/224 226/209 228/211\nf 230/225 231/212 226/214\nf 232/221 233/215 230/217\nf 233/226 232/218 228/220\nf 229/227 232/221 226/222\nf 231/228 233/223 227/215\ng Mesh13 Mount_L_U1 MountG2 Model\nv 25.000000 177.818054 -353.478973\nv 20.000000 172.834061 -353.879974\nv 0.000000 172.834061 -353.879974\nv 0.000000 177.818054 -353.478973\nv 20.000000 172.353058 -347.898956\nv 25.000000 177.336060 -347.497955\nv 25.000000 177.737061 -352.481964\nv 0.000000 172.353058 -347.898956\nv 0.000000 177.336060 -347.497955\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.870000 0.190000\nvt 0.700000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.000000\nvt 0.650000 0.130000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.190000\nvt 0.930000 0.210000\nvt 0.650000 0.190000\nf 235/229 236/230 237/231\nf 235/232 238/233 240/234\nf 238/230 241/229 236/235\nf 242/236 241/237 238/238\nf 236/239 241/236 242/233\nf 240/240 237/231 242/241\nf 234/242 235/229 237/231\nf 238/233 239/243 240/234\nf 240/234 234/241 235/232\nf 235/239 238/230 236/235\nf 239/244 242/236 238/238\nf 237/232 236/239 242/233\nf 237/231 240/240 234/242\nf 240/240 242/241 239/245\ng Mesh15 Mount_R_D1 MountG2 Model\nv 100.000000 117.297050 -347.400970\nv 100.000000 122.280052 -346.999969\nv 80.000000 122.280052 -346.999969\nv 75.000000 117.297050 -347.400970\nv 100.000000 117.778061 -353.381958\nv 100.000000 122.762062 -352.980957\nv 75.000000 117.778061 -353.381958\nv 80.000000 122.762062 -352.980957\nv 75.000000 117.377052 -348.397980\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.190000\nvt 0.860000 0.190000\nvt 0.860000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.870000 -0.000000\nvt 0.930000 0.050000\nvt 0.650000 0.180000\nvt 0.650000 0.120000\nvt 0.700000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.120000\nvt 0.860000 0.050000\nvt 0.860000 -0.000000\nvt 0.650000 0.190000\nf 243/246 244/247 245/248\nf 247/249 248/250 244/251\nf 250/252 248/253 247/251\nf 251/254 249/246 250/255\nf 251/256 249/257 247/251\nf 248/253 250/252 245/258\nf 246/259 243/246 245/248\nf 243/260 247/249 244/251\nf 249/257 250/252 247/251\nf 245/261 246/262 251/254\nf 251/254 250/255 245/261\nf 243/250 246/263 251/256\nf 251/256 247/251 243/250\nf 244/262 248/253 245/258\ng Mesh1 Lane Model\nv 30.000000 110.200027 -169.599991\nv 25.000000 110.200027 -169.599991\nv 25.000000 103.175026 -153.649979\nv 30.000000 103.175026 -153.649979\nv 30.000000 117.525032 -184.949982\nv 25.000000 117.525032 -184.949982\nv 30.000000 125.000031 -199.999985\nv 25.000000 125.000031 -199.999985\nv 30.000000 132.475037 -215.049988\nv 25.000000 132.475037 -215.049988\nv 30.000000 139.800034 -230.399979\nv 25.000000 139.800034 -230.399979\nv 30.000000 146.825043 -246.349976\nv 25.000000 146.825043 -246.349976\nv 30.000000 153.400040 -263.199982\nv 25.000000 153.400040 -263.199982\nv 30.000000 159.375046 -281.249969\nv 25.000000 159.375046 -281.249969\nv 30.000000 164.600052 -300.799957\nv 25.000000 164.600052 -300.799957\nv 30.000000 168.925049 -322.149963\nv 25.000000 168.925049 -322.149963\nv 30.000000 172.200058 -345.599976\nv 25.000000 172.200058 -345.599976\nv 30.000000 174.275055 -371.449982\nv 25.000000 174.275055 -371.449982\nv 30.000000 175.000061 -399.999969\nv 25.000000 175.000061 -399.999969\nv 30.000000 180.000061 -399.999969\nv 30.000000 96.600021 -136.799988\nv 30.000000 90.625023 -118.749985\nv 30.000000 85.400017 -99.199982\nv 30.000000 81.075012 -77.849983\nv 30.000000 77.800011 -54.399990\nv 30.000000 75.725006 -28.549988\nv 30.000000 75.000000 0.000012\nv 30.000000 80.000000 0.000013\nv 30.000000 80.725006 -28.549986\nv 30.000000 82.800011 -54.399986\nv 30.000000 86.075012 -77.849983\nv 30.000000 90.400017 -99.199982\nv 30.000000 95.625023 -118.749985\nv 30.000000 101.600021 -136.799988\nv 30.000000 108.175026 -153.649979\nv 30.000000 115.200027 -169.599991\nv 30.000000 122.525032 -184.949982\nv 30.000000 130.000031 -199.999985\nv 30.000000 137.475037 -215.049988\nv 30.000000 144.800034 -230.399963\nv 30.000000 151.825043 -246.349976\nv 30.000000 158.400040 -263.199982\nv 30.000000 164.375046 -281.249969\nv 30.000000 169.600052 -300.799957\nv 30.000000 173.925049 -322.149963\nv 30.000000 177.200058 -345.599976\nv 30.000000 179.275055 -371.449982\nv 25.000000 180.000061 -399.999969\nv 20.000000 175.000061 -399.999969\nv 20.000000 170.000061 -399.999969\nv 25.000000 170.000061 -399.999969\nv 25.000000 179.275055 -371.449982\nv 25.000000 177.200058 -345.599976\nv 25.000000 173.925049 -322.149963\nv 25.000000 169.600052 -300.799957\nv 25.000000 164.375046 -281.249969\nv 25.000000 158.400040 -263.199982\nv 25.000000 151.825043 -246.349976\nv 25.000000 144.800034 -230.399963\nv 25.000000 137.475037 -215.049988\nv 25.000000 130.000031 -199.999985\nv 25.000000 122.525032 -184.949982\nv 25.000000 115.200027 -169.599991\nv 25.000000 108.175026 -153.649979\nv 25.000000 101.600021 -136.799988\nv 25.000000 95.625023 -118.749985\nv 25.000000 90.400017 -99.199982\nv 25.000000 86.075012 -77.849983\nv 25.000000 82.800011 -54.399986\nv 25.000000 80.725006 -28.549986\nv 25.000000 80.000000 0.000013\nv 25.000000 75.000000 0.000012\nv 25.000000 70.000000 0.000011\nv 20.000000 70.000000 0.000011\nv 20.000000 75.000000 0.000012\nv 25.000000 75.725006 -28.549988\nv 25.000000 77.800011 -54.399990\nv 25.000000 81.075012 -77.849983\nv 25.000000 85.400017 -99.199982\nv 25.000000 90.625023 -118.749985\nv 25.000000 96.600021 -136.799988\nv 25.000000 169.275055 -371.449982\nv 25.000000 167.200058 -345.599976\nv 25.000000 163.925049 -322.149963\nv 25.000000 159.600052 -300.799957\nv 25.000000 154.375046 -281.249969\nv 25.000000 148.400040 -263.199982\nv 25.000000 141.825043 -246.349976\nv 25.000000 134.800034 -230.399979\nv 25.000000 127.475037 -215.049988\nv 25.000000 120.000031 -199.999985\nv 25.000000 112.525032 -184.949982\nv 25.000000 105.200027 -169.599991\nv 25.000000 98.175026 -153.649979\nv 25.000000 91.600021 -136.799988\nv 25.000000 85.625023 -118.749985\nv 25.000000 80.400017 -99.199982\nv 25.000000 76.075012 -77.849983\nv 25.000000 72.800011 -54.399990\nv 25.000000 70.725006 -28.549988\nv 20.000000 169.275055 -371.449982\nv 20.000000 167.200058 -345.599976\nv 20.000000 163.925049 -322.149963\nv 20.000000 159.600052 -300.799957\nv 20.000000 154.375046 -281.249969\nv 20.000000 148.400040 -263.199982\nv 20.000000 141.825043 -246.349976\nv 20.000000 134.800034 -230.399979\nv 20.000000 127.475037 -215.049988\nv 20.000000 120.000031 -199.999985\nv 20.000000 112.525032 -184.949982\nv 20.000000 105.200027 -169.599991\nv 20.000000 98.175026 -153.649979\nv 20.000000 91.600021 -136.799988\nv 20.000000 85.625023 -118.749985\nv 20.000000 80.400017 -99.199982\nv 20.000000 76.075012 -77.849983\nv 20.000000 72.800011 -54.399990\nv 20.000000 70.725006 -28.549988\nv 20.000000 174.275055 -371.449982\nv 20.000000 172.200058 -345.599976\nv 20.000000 168.925049 -322.149963\nv 20.000000 164.600052 -300.799957\nv 20.000000 159.375046 -281.249969\nv 20.000000 153.400040 -263.199982\nv 20.000000 146.825043 -246.349976\nv 20.000000 139.800034 -230.399979\nv 20.000000 132.475037 -215.049988\nv 20.000000 125.000031 -199.999985\nv 20.000000 117.525032 -184.949982\nv 20.000000 110.200027 -169.599991\nv 20.000000 103.175026 -153.649979\nv 20.000000 96.600021 -136.799988\nv 20.000000 90.625023 -118.749985\nv 20.000000 85.400017 -99.199982\nv 20.000000 81.075012 -77.849983\nv 20.000000 77.800011 -54.399990\nv 20.000000 75.725006 -28.549988\nvt 0.400000 1.000000\nvt 0.000000 1.000000\nvt -0.000000 0.950000\nvt -0.000000 0.580000\nvt 0.400000 0.580000\nvt 0.400000 0.630000\nvt 0.700000 1.000000\nvt 0.750000 0.950000\nvt 0.700000 0.950000\nvt 0.000000 0.480000\nvt 0.400000 0.480000\nvt 0.400000 0.530000\nvt -0.000000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.900000\nvt 0.800000 0.530000\nvt 0.650000 1.000000\nvt 0.800000 0.630000\nvt -0.000000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.360000\nvt -0.000000 0.680000\nvt 0.400000 0.680000\nvt 0.400000 0.730000\nvt 0.800000 0.360000\nvt 0.000000 0.630000\nvt 0.000000 0.410000\nvt 0.400000 0.410000\nvt -0.000000 0.780000\nvt 0.400000 0.780000\nvt 0.800000 0.410000\nvt 0.800000 0.480000\nvt -0.000000 0.900000\nvt 0.400000 0.950000\nvt 0.800000 0.580000\nvt 0.000000 0.530000\nvt 0.000000 0.360000\nvt 0.000000 0.730000\nvt 0.800000 0.260000\nvt 0.400000 0.260000\nvt -0.000000 0.260000\nvt 0.650000 0.950000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nvt 0.800000 0.310000\nf 253/264 254/265 255/266\nf 257/264 253/265 252/266\nf 259/264 257/265 256/266\nf 261/264 259/265 258/266\nf 263/264 261/265 260/266\nf 265/264 263/265 262/266\nf 267/264 265/265 264/266\nf 269/264 267/265 266/266\nf 271/264 269/265 268/266\nf 273/264 271/265 270/266\nf 275/264 273/265 272/266\nf 277/264 275/265 274/266\nf 276/267 278/268 279/269\nf 308/270 309/271 279/272\nf 312/273 308/274 280/275\nf 313/276 312/277 307/278\nf 314/276 313/277 306/278\nf 315/276 314/277 305/278\nf 316/276 315/277 304/278\nf 317/276 316/277 303/278\nf 318/276 317/277 302/278\nf 319/276 318/277 301/278\nf 320/276 319/277 300/278\nf 321/276 320/277 299/278\nf 322/276 321/277 298/278\nf 323/276 322/277 297/278\nf 324/276 323/277 296/278\nf 325/276 324/277 295/278\nf 326/276 325/277 294/278\nf 327/276 326/277 293/278\nf 328/276 327/277 292/278\nf 329/276 328/277 291/278\nf 330/276 329/277 290/278\nf 289/279 288/275 331/274\nf 331/270 288/280 332/272\nf 336/281 332/269 287/268\nf 337/264 336/265 286/266\nf 338/264 337/265 285/266\nf 339/264 338/265 284/266\nf 340/264 339/265 283/266\nf 341/264 340/265 282/266\nf 254/264 341/265 281/266\nf 342/282 311/283 310/284\nf 343/285 342/286 361/287\nf 344/285 343/286 362/287\nf 345/285 344/286 363/287\nf 346/285 345/286 364/287\nf 347/285 346/286 365/287\nf 348/285 347/286 366/287\nf 349/285 348/286 367/287\nf 350/285 349/286 368/287\nf 351/285 350/286 369/287\nf 352/285 351/286 370/287\nf 353/285 352/286 371/287\nf 354/285 353/286 372/287\nf 355/285 354/286 373/287\nf 356/285 355/286 374/287\nf 357/285 356/286 375/287\nf 358/285 357/286 376/287\nf 359/285 358/286 377/287\nf 360/285 359/286 378/287\nf 379/288 334/284 333/283\nf 275/289 277/269 342/286\nf 312/273 380/290 309/291\nf 313/276 381/292 380/293\nf 314/276 382/292 381/293\nf 315/276 383/292 382/293\nf 316/276 384/292 383/293\nf 317/276 385/292 384/293\nf 318/276 386/292 385/293\nf 319/276 387/292 386/293\nf 320/276 388/292 387/293\nf 321/276 389/292 388/293\nf 322/276 390/292 389/293\nf 323/276 391/292 390/293\nf 324/276 392/292 391/293\nf 325/276 393/292 392/293\nf 326/276 394/292 393/293\nf 327/276 395/292 394/293\nf 328/276 396/292 395/293\nf 329/276 397/292 396/293\nf 330/276 398/292 397/293\nf 398/294 330/295 331/274\nf 305/296 306/278 274/297\nf 270/297 268/266 303/296\nf 268/297 266/266 302/296\nf 264/297 262/266 300/296\nf 286/298 287/268 288/275\nf 285/297 286/266 289/296\nf 266/297 264/266 301/296\nf 284/297 285/266 290/296\nf 262/297 260/266 299/296\nf 283/297 284/266 291/296\nf 298/296 299/278 260/297\nf 306/296 307/278 276/297\nf 282/297 283/266 292/296\nf 293/296 294/278 281/297\nf 272/297 270/266 304/296\nf 294/296 295/278 255/297\nf 295/296 296/278 252/297\nf 296/296 297/278 256/297\nf 258/297 256/266 297/296\nf 278/268 276/267 307/299\nf 380/290 361/300 310/284\nf 370/287 389/293 390/292\nf 371/287 390/293 391/292\nf 381/292 362/301 361/287\nf 368/287 387/293 388/292\nf 372/287 391/293 392/292\nf 356/286 357/285 339/289\nf 382/292 363/301 362/287\nf 393/292 374/301 373/287\nf 374/287 393/293 394/292\nf 259/289 261/269 350/286\nf 383/292 364/301 363/287\nf 367/287 386/293 387/292\nf 396/292 377/301 376/287\nf 358/286 359/285 337/289\nf 384/292 365/301 364/287\nf 397/292 378/301 377/287\nf 398/292 379/301 378/287\nf 360/302 333/303 332/283\nf 365/287 384/293 385/292\nf 335/291 334/284 379/288\nf 366/287 385/293 386/292\nf 375/287 394/293 395/292\nf 345/286 346/285 269/289\nf 348/286 349/285 263/289\nf 359/286 360/285 336/289\nf 340/289 341/269 355/286\nf 357/286 358/285 338/289\nf 347/286 348/285 265/289\nf 311/283 342/282 277/304\nf 273/289 275/269 343/286\nf 346/286 347/285 267/289\nf 369/287 388/293 389/292\nf 344/286 345/285 271/289\nf 341/289 254/269 354/286\nf 254/289 253/269 353/286\nf 253/289 257/269 352/286\nf 351/286 352/285 257/289\nf 349/286 350/285 261/289\nf 252/297 253/264 255/266\nf 256/297 257/264 252/266\nf 258/297 259/264 256/266\nf 260/297 261/264 258/266\nf 262/297 263/264 260/266\nf 264/297 265/264 262/266\nf 266/297 267/264 264/266\nf 268/297 269/264 266/266\nf 270/297 271/264 268/266\nf 272/297 273/264 270/266\nf 274/297 275/264 272/266\nf 276/297 277/264 274/266\nf 277/289 276/267 279/269\nf 279/272 278/305 280/280\nf 310/306 311/307 279/272\nf 279/272 309/271 310/306\nf 279/272 280/280 308/270\nf 307/299 312/273 280/275\nf 306/296 313/276 307/278\nf 305/296 314/276 306/278\nf 304/296 315/276 305/278\nf 303/296 316/276 304/278\nf 302/296 317/276 303/278\nf 301/296 318/276 302/278\nf 300/296 319/276 301/278\nf 299/296 320/276 300/278\nf 298/296 321/276 299/278\nf 297/296 322/276 298/278\nf 296/296 323/276 297/278\nf 295/296 324/276 296/278\nf 294/296 325/276 295/278\nf 293/296 326/276 294/278\nf 292/296 327/276 293/278\nf 291/296 328/276 292/278\nf 290/296 329/276 291/278\nf 289/296 330/276 290/278\nf 330/295 289/279 331/274\nf 332/272 335/271 331/270\nf 332/272 333/307 334/306\nf 288/280 287/305 332/272\nf 332/272 334/306 335/271\nf 286/298 336/281 287/268\nf 285/297 337/264 286/266\nf 284/297 338/264 285/266\nf 283/297 339/264 284/266\nf 282/297 340/264 283/266\nf 281/297 341/264 282/266\nf 255/297 254/264 281/266\nf 361/300 342/282 310/284\nf 362/301 343/285 361/287\nf 363/301 344/285 362/287\nf 364/301 345/285 363/287\nf 365/301 346/285 364/287\nf 366/301 347/285 365/287\nf 367/301 348/285 366/287\nf 368/301 349/285 367/287\nf 369/301 350/285 368/287\nf 370/301 351/285 369/287\nf 371/301 352/285 370/287\nf 372/301 353/285 371/287\nf 373/301 354/285 372/287\nf 374/301 355/285 373/287\nf 375/301 356/285 374/287\nf 376/301 357/285 375/287\nf 377/301 358/285 376/287\nf 378/301 359/285 377/287\nf 379/301 360/285 378/287\nf 360/308 379/288 333/283\nf 343/285 275/289 342/286\nf 308/274 312/273 309/291\nf 312/277 313/276 380/293\nf 313/277 314/276 381/293\nf 314/277 315/276 382/293\nf 315/277 316/276 383/293\nf 316/277 317/276 384/293\nf 317/277 318/276 385/293\nf 318/277 319/276 386/293\nf 319/277 320/276 387/293\nf 320/277 321/276 388/293\nf 321/277 322/276 389/293\nf 322/277 323/276 390/293\nf 323/277 324/276 391/293\nf 324/277 325/276 392/293\nf 325/277 326/276 393/293\nf 326/277 327/276 394/293\nf 327/277 328/276 395/293\nf 328/277 329/276 396/293\nf 329/277 330/276 397/293\nf 335/291 398/294 331/274\nf 272/266 305/296 274/297\nf 304/278 270/297 303/296\nf 303/278 268/297 302/296\nf 301/278 264/297 300/296\nf 289/279 286/298 288/275\nf 290/278 285/297 289/296\nf 302/278 266/297 301/296\nf 291/278 284/297 290/296\nf 300/278 262/297 299/296\nf 292/278 283/297 291/296\nf 258/266 298/296 260/297\nf 274/266 306/296 276/297\nf 293/278 282/297 292/296\nf 282/266 293/296 281/297\nf 305/278 272/297 304/296\nf 281/266 294/296 255/297\nf 255/266 295/296 252/297\nf 252/266 296/296 256/297\nf 298/278 258/297 297/296\nf 280/275 278/268 307/299\nf 309/291 380/290 310/284\nf 371/301 370/287 390/292\nf 372/301 371/287 391/292\nf 380/293 381/292 361/287\nf 369/301 368/287 388/292\nf 373/301 372/287 392/292\nf 340/269 356/286 339/289\nf 381/293 382/292 362/287\nf 392/293 393/292 373/287\nf 375/301 374/287 394/292\nf 351/285 259/289 350/286\nf 382/293 383/292 363/287\nf 368/301 367/287 387/292\nf 395/293 396/292 376/287\nf 338/269 358/286 337/289\nf 383/293 384/292 364/287\nf 396/293 397/292 377/287\nf 397/293 398/292 378/287\nf 336/308 360/302 332/283\nf 366/301 365/287 385/292\nf 398/294 335/291 379/288\nf 367/301 366/287 386/292\nf 376/301 375/287 395/292\nf 271/269 345/286 269/289\nf 265/269 348/286 263/289\nf 337/269 359/286 336/289\nf 356/285 340/289 355/286\nf 339/269 357/286 338/289\nf 267/269 347/286 265/289\nf 279/303 311/283 277/304\nf 344/285 273/289 343/286\nf 269/269 346/286 267/289\nf 370/301 369/287 389/292\nf 273/269 344/286 271/289\nf 355/285 341/289 354/286\nf 354/285 254/289 353/286\nf 353/285 253/289 352/286\nf 259/269 351/286 257/289\nf 263/269 349/286 261/289\ng Mesh2 Lane Model\nv 29.999977 89.800034 -230.399994\nv 24.999977 89.800034 -230.399994\nv 24.999977 96.825020 -246.350006\nv 29.999977 96.825020 -246.350006\nv 29.999969 82.475029 -215.049988\nv 24.999969 82.475029 -215.049988\nv 29.999969 75.000031 -199.999985\nv 24.999969 75.000031 -199.999985\nv 29.999969 67.525024 -184.949982\nv 24.999969 67.525024 -184.949982\nv 29.999962 60.200027 -169.599991\nv 24.999962 60.200027 -169.599991\nv 29.999962 53.175049 -153.649979\nv 24.999962 53.175049 -153.649979\nv 29.999962 46.600052 -136.799988\nv 24.999962 46.600052 -136.799988\nv 29.999954 40.625046 -118.749969\nv 24.999954 40.625046 -118.750000\nv 29.999954 35.400040 -99.199982\nv 24.999954 35.400040 -99.199982\nv 29.999954 31.075043 -77.849976\nv 24.999954 31.075043 -77.849976\nv 29.999947 27.800064 -54.399963\nv 24.999947 27.800064 -54.399963\nv 29.999947 25.725067 -28.549957\nv 24.999947 25.725067 -28.549957\nv 29.999939 25.000061 0.000031\nv 24.999939 25.000061 0.000031\nv 29.999939 20.000061 0.000031\nv 29.999977 103.400024 -263.200012\nv 29.999985 109.375023 -281.250000\nv 29.999985 114.600014 -300.799988\nv 29.999985 118.925018 -322.149994\nv 29.999992 122.200005 -345.600006\nv 29.999992 124.275009 -371.450012\nv 30.000000 125.000000 -400.000000\nv 30.000000 120.000000 -400.000000\nv 29.999992 119.275009 -371.450012\nv 29.999992 117.200005 -345.600006\nv 29.999985 113.925018 -322.149994\nv 29.999985 109.600014 -300.799988\nv 29.999985 104.375023 -281.250000\nv 29.999977 98.400024 -263.200012\nv 29.999977 91.825020 -246.350006\nv 29.999977 84.800034 -230.399979\nv 29.999969 77.475029 -215.049988\nv 29.999969 70.000031 -199.999985\nv 29.999969 62.525024 -184.949982\nv 29.999962 55.200027 -169.599991\nv 29.999962 48.175049 -153.649979\nv 29.999962 41.600052 -136.799988\nv 29.999954 35.625046 -118.749969\nv 29.999954 30.400040 -99.199982\nv 29.999954 26.075043 -77.849976\nv 29.999947 22.800064 -54.399963\nv 29.999947 20.725067 -28.549957\nv 24.999939 20.000061 0.000031\nv 19.999939 25.000061 0.000031\nv 19.999939 30.000061 0.000031\nv 24.999939 30.000061 0.000031\nv 24.999947 20.725067 -28.549957\nv 24.999947 22.800064 -54.399963\nv 24.999954 26.075043 -77.849976\nv 24.999954 30.400040 -99.199982\nv 24.999954 35.625046 -118.749969\nv 24.999962 41.600052 -136.799988\nv 24.999962 48.175049 -153.649979\nv 24.999962 55.200027 -169.599991\nv 24.999969 62.525024 -184.949982\nv 24.999969 70.000031 -199.999985\nv 24.999969 77.475029 -215.049988\nv 24.999977 84.800034 -230.399994\nv 24.999977 91.825020 -246.350006\nv 24.999977 98.400024 -263.200012\nv 24.999985 104.375023 -281.250000\nv 24.999985 109.600014 -300.799988\nv 24.999985 113.925018 -322.149994\nv 24.999992 117.200005 -345.600006\nv 24.999992 119.275009 -371.450012\nv 25.000000 120.000000 -400.000000\nv 25.000000 125.000000 -400.000000\nv 25.000000 130.000000 -400.000000\nv 20.000000 130.000000 -400.000000\nv 20.000000 125.000000 -400.000000\nv 24.999992 124.275009 -371.450012\nv 24.999992 122.200005 -345.600006\nv 24.999985 118.925018 -322.149994\nv 24.999985 114.600014 -300.799988\nv 24.999985 109.375023 -281.250000\nv 24.999977 103.400024 -263.200012\nv 24.999947 30.725067 -28.549957\nv 24.999947 32.800064 -54.399963\nv 24.999954 36.075043 -77.849976\nv 24.999954 40.400040 -99.200012\nv 24.999954 45.625046 -118.750000\nv 24.999962 51.600052 -136.799988\nv 24.999962 58.175049 -153.649979\nv 24.999962 65.200027 -169.599991\nv 24.999969 72.525040 -184.949982\nv 24.999969 80.000031 -199.999985\nv 24.999969 87.475029 -215.050003\nv 24.999977 94.800034 -230.399994\nv 24.999977 101.825020 -246.350006\nv 24.999977 108.400024 -263.200012\nv 24.999985 114.375023 -281.250000\nv 24.999985 119.600014 -300.799988\nv 24.999985 123.925018 -322.149994\nv 24.999992 127.200005 -345.600006\nv 24.999992 129.275009 -371.450012\nv 19.999947 30.725067 -28.549957\nv 19.999947 32.800064 -54.399994\nv 19.999954 36.075043 -77.850006\nv 19.999954 40.400040 -99.200012\nv 19.999954 45.625046 -118.750000\nv 19.999962 51.600052 -136.799988\nv 19.999962 58.175049 -153.649979\nv 19.999962 65.200027 -169.599991\nv 19.999969 72.525040 -184.949982\nv 19.999969 80.000031 -200.000000\nv 19.999969 87.475029 -215.050003\nv 19.999977 94.800034 -230.399994\nv 19.999977 101.825020 -246.350006\nv 19.999977 108.400024 -263.200012\nv 19.999985 114.375023 -281.250000\nv 19.999985 119.600014 -300.799988\nv 19.999985 123.925018 -322.149994\nv 19.999992 127.200005 -345.600006\nv 19.999992 129.275009 -371.450012\nv 19.999947 25.725067 -28.549957\nv 19.999947 27.800064 -54.399963\nv 19.999954 31.075043 -77.849976\nv 19.999954 35.400040 -99.200012\nv 19.999954 40.625046 -118.750000\nv 19.999962 46.600052 -136.799988\nv 19.999962 53.175049 -153.649979\nv 19.999962 60.200027 -169.599991\nv 19.999969 67.525024 -184.949982\nv 19.999969 75.000031 -199.999985\nv 19.999969 82.475029 -215.050003\nv 19.999977 89.800034 -230.399994\nv 19.999977 96.825020 -246.350006\nv 19.999977 103.400024 -263.200012\nv 19.999985 109.375023 -281.250000\nv 19.999985 114.600014 -300.799988\nv 19.999985 118.925018 -322.149994\nv 19.999992 122.200005 -345.600006\nv 19.999992 124.275009 -371.450012\nvt 0.400000 1.000000\nvt 0.000000 1.000000\nvt -0.000000 0.950000\nvt 0.400000 0.950000\nvt -0.000000 0.580000\nvt 0.400000 0.580000\nvt 0.400000 0.630000\nvt 0.700000 1.000000\nvt 0.750000 0.950000\nvt 0.700000 0.950000\nvt 0.000000 0.530000\nvt 0.000000 0.480000\nvt 0.400000 0.480000\nvt -0.000000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.900000\nvt -0.000000 0.900000\nvt 0.800000 0.530000\nvt 0.400000 0.530000\nvt 0.650000 1.000000\nvt 0.800000 0.630000\nvt -0.000000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.360000\nvt -0.000000 0.680000\nvt 0.400000 0.680000\nvt 0.400000 0.730000\nvt -0.000000 0.730000\nvt 0.800000 0.360000\nvt 0.000000 0.630000\nvt 0.000000 0.410000\nvt 0.400000 0.410000\nvt -0.000000 0.780000\nvt 0.400000 0.780000\nvt 0.800000 0.410000\nvt 0.800000 0.480000\nvt 0.800000 0.580000\nvt 0.000000 0.360000\nvt 0.800000 0.260000\nvt 0.400000 0.260000\nvt -0.000000 0.260000\nvt 0.650000 0.950000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nvt 0.800000 0.310000\nf 400/309 401/310 402/311\nf 403/312 404/309 400/310\nf 406/309 404/310 403/311\nf 408/309 406/310 405/311\nf 409/312 410/309 408/310\nf 412/309 410/310 409/311\nf 414/309 412/310 411/311\nf 416/309 414/310 413/311\nf 418/309 416/310 415/311\nf 420/309 418/310 417/311\nf 421/312 422/309 420/310\nf 424/309 422/310 421/311\nf 423/313 425/314 426/315\nf 455/316 456/317 426/318\nf 454/319 459/320 455/321\nf 460/322 459/323 454/324\nf 461/322 460/323 453/324\nf 462/322 461/323 452/324\nf 463/322 462/323 451/324\nf 464/322 463/323 450/324\nf 465/322 464/323 449/324\nf 466/322 465/323 448/324\nf 467/322 466/323 447/324\nf 468/322 467/323 446/324\nf 469/322 468/323 445/324\nf 443/325 470/322 469/323\nf 442/325 471/322 470/323\nf 472/322 471/323 442/324\nf 473/322 472/323 441/324\nf 474/322 473/323 440/324\nf 475/322 474/323 439/324\nf 476/322 475/323 438/324\nf 477/322 476/323 437/324\nf 436/326 435/327 478/321\nf 478/316 435/328 479/318\nf 483/329 479/315 434/314\nf 484/309 483/310 433/311\nf 431/312 485/309 484/310\nf 486/309 485/310 431/311\nf 487/309 486/310 430/311\nf 428/312 488/309 487/310\nf 401/309 488/310 428/311\nf 489/330 458/331 457/332\nf 490/333 489/334 508/335\nf 491/333 490/334 509/335\nf 492/333 491/334 510/335\nf 493/333 492/334 511/335\nf 513/336 494/333 493/334\nf 495/333 494/334 513/335\nf 496/333 495/334 514/335\nf 516/336 497/333 496/334\nf 498/333 497/334 516/335\nf 499/333 498/334 517/335\nf 519/336 500/333 499/334\nf 501/333 500/334 519/335\nf 502/333 501/334 520/335\nf 522/336 503/333 502/334\nf 504/333 503/334 522/335\nf 505/333 504/334 523/335\nf 525/336 506/333 505/334\nf 507/333 506/334 525/335\nf 526/337 481/332 480/331\nf 422/338 424/315 489/334\nf 459/320 527/339 456/340\nf 460/322 528/341 527/342\nf 461/322 529/341 528/342\nf 462/322 530/341 529/342\nf 463/322 531/341 530/342\nf 464/322 532/341 531/342\nf 465/322 533/341 532/342\nf 466/322 534/341 533/342\nf 467/322 535/341 534/342\nf 468/322 536/341 535/342\nf 469/322 537/341 536/342\nf 470/322 538/341 537/342\nf 471/322 539/341 538/342\nf 472/322 540/341 539/342\nf 473/322 541/341 540/342\nf 474/322 542/341 541/342\nf 475/322 543/341 542/342\nf 476/322 544/341 543/342\nf 477/322 545/341 544/342\nf 545/343 477/344 478/321\nf 452/325 453/324 421/312\nf 417/312 415/311 450/325\nf 415/312 413/311 449/325\nf 411/312 409/311 447/325\nf 433/345 434/314 435/327\nf 432/312 433/311 436/325\nf 413/312 411/311 448/325\nf 431/312 432/311 437/325\nf 409/312 407/311 446/325\nf 430/312 431/311 438/325\nf 445/325 446/324 407/312\nf 453/325 454/324 423/312\nf 429/312 430/311 439/325\nf 440/325 441/324 428/312\nf 419/312 417/311 451/325\nf 441/325 442/324 402/312\nf 442/325 443/324 399/312\nf 443/325 444/324 403/312\nf 405/312 403/311 444/325\nf 425/314 423/313 454/319\nf 527/339 508/346 457/332\nf 517/335 536/342 537/341\nf 518/335 537/342 538/341\nf 528/341 509/336 508/335\nf 515/335 534/342 535/341\nf 519/335 538/342 539/341\nf 503/334 504/333 486/338\nf 529/341 510/336 509/335\nf 540/341 521/336 520/335\nf 521/335 540/342 541/341\nf 406/338 408/315 497/334\nf 530/341 511/336 510/335\nf 514/335 533/342 534/341\nf 543/341 524/336 523/335\nf 505/334 506/333 484/338\nf 531/341 512/336 511/335\nf 544/341 525/336 524/335\nf 545/341 526/336 525/335\nf 507/347 480/348 479/331\nf 512/335 531/342 532/341\nf 482/340 481/332 526/337\nf 513/335 532/342 533/341\nf 522/335 541/342 542/341\nf 492/334 493/333 416/338\nf 495/334 496/333 410/338\nf 506/334 507/333 483/338\nf 487/338 488/315 502/334\nf 504/334 505/333 485/338\nf 494/334 495/333 412/338\nf 458/331 489/330 424/349\nf 420/338 422/315 490/334\nf 493/334 494/333 414/338\nf 516/335 535/342 536/341\nf 491/334 492/333 418/338\nf 488/338 401/315 501/334\nf 401/338 400/315 500/334\nf 400/338 404/315 499/334\nf 498/334 499/333 404/338\nf 496/334 497/333 408/338\nf 399/312 400/309 402/311\nf 399/311 403/312 400/310\nf 405/312 406/309 403/311\nf 407/312 408/309 405/311\nf 407/311 409/312 408/310\nf 411/312 412/309 409/311\nf 413/312 414/309 411/311\nf 415/312 416/309 413/311\nf 417/312 418/309 415/311\nf 419/312 420/309 417/311\nf 419/311 421/312 420/310\nf 423/312 424/309 421/311\nf 424/338 423/313 426/315\nf 426/318 425/350 427/328\nf 457/351 458/352 426/318\nf 426/318 456/317 457/351\nf 426/318 427/328 455/316\nf 427/327 454/319 455/321\nf 453/325 460/322 454/324\nf 452/325 461/322 453/324\nf 451/325 462/322 452/324\nf 450/325 463/322 451/324\nf 449/325 464/322 450/324\nf 448/325 465/322 449/324\nf 447/325 466/322 448/324\nf 446/325 467/322 447/324\nf 445/325 468/322 446/324\nf 444/325 469/322 445/324\nf 444/324 443/325 469/323\nf 443/324 442/325 470/323\nf 441/325 472/322 442/324\nf 440/325 473/322 441/324\nf 439/325 474/322 440/324\nf 438/325 475/322 439/324\nf 437/325 476/322 438/324\nf 436/325 477/322 437/324\nf 477/344 436/326 478/321\nf 479/318 482/317 478/316\nf 479/318 480/352 481/351\nf 435/328 434/350 479/318\nf 479/318 481/351 482/317\nf 433/345 483/329 434/314\nf 432/312 484/309 433/311\nf 432/311 431/312 484/310\nf 430/312 486/309 431/311\nf 429/312 487/309 430/311\nf 429/311 428/312 487/310\nf 402/312 401/309 428/311\nf 508/346 489/330 457/332\nf 509/336 490/333 508/335\nf 510/336 491/333 509/335\nf 511/336 492/333 510/335\nf 512/336 493/333 511/335\nf 512/335 513/336 493/334\nf 514/336 495/333 513/335\nf 515/336 496/333 514/335\nf 515/335 516/336 496/334\nf 517/336 498/333 516/335\nf 518/336 499/333 517/335\nf 518/335 519/336 499/334\nf 520/336 501/333 519/335\nf 521/336 502/333 520/335\nf 521/335 522/336 502/334\nf 523/336 504/333 522/335\nf 524/336 505/333 523/335\nf 524/335 525/336 505/334\nf 526/336 507/333 525/335\nf 507/353 526/337 480/331\nf 490/333 422/338 489/334\nf 455/321 459/320 456/340\nf 459/323 460/322 527/342\nf 460/323 461/322 528/342\nf 461/323 462/322 529/342\nf 462/323 463/322 530/342\nf 463/323 464/322 531/342\nf 464/323 465/322 532/342\nf 465/323 466/322 533/342\nf 466/323 467/322 534/342\nf 467/323 468/322 535/342\nf 468/323 469/322 536/342\nf 469/323 470/322 537/342\nf 470/323 471/322 538/342\nf 471/323 472/322 539/342\nf 472/323 473/322 540/342\nf 473/323 474/322 541/342\nf 474/323 475/322 542/342\nf 475/323 476/322 543/342\nf 476/323 477/322 544/342\nf 482/340 545/343 478/321\nf 419/311 452/325 421/312\nf 451/324 417/312 450/325\nf 450/324 415/312 449/325\nf 448/324 411/312 447/325\nf 436/326 433/345 435/327\nf 437/324 432/312 436/325\nf 449/324 413/312 448/325\nf 438/324 431/312 437/325\nf 447/324 409/312 446/325\nf 439/324 430/312 438/325\nf 405/311 445/325 407/312\nf 421/311 453/325 423/312\nf 440/324 429/312 439/325\nf 429/311 440/325 428/312\nf 452/324 419/312 451/325\nf 428/311 441/325 402/312\nf 402/311 442/325 399/312\nf 399/311 443/325 403/312\nf 445/324 405/312 444/325\nf 427/327 425/314 454/319\nf 456/340 527/339 457/332\nf 518/336 517/335 537/341\nf 519/336 518/335 538/341\nf 527/342 528/341 508/335\nf 516/336 515/335 535/341\nf 520/336 519/335 539/341\nf 487/315 503/334 486/338\nf 528/342 529/341 509/335\nf 539/342 540/341 520/335\nf 522/336 521/335 541/341\nf 498/333 406/338 497/334\nf 529/342 530/341 510/335\nf 515/336 514/335 534/341\nf 542/342 543/341 523/335\nf 485/315 505/334 484/338\nf 530/342 531/341 511/335\nf 543/342 544/341 524/335\nf 544/342 545/341 525/335\nf 483/353 507/347 479/331\nf 513/336 512/335 532/341\nf 545/343 482/340 526/337\nf 514/336 513/335 533/341\nf 523/336 522/335 542/341\nf 418/315 492/334 416/338\nf 412/315 495/334 410/338\nf 484/315 506/334 483/338\nf 503/333 487/338 502/334\nf 486/315 504/334 485/338\nf 414/315 494/334 412/338\nf 426/348 458/331 424/349\nf 491/333 420/338 490/334\nf 416/315 493/334 414/338\nf 517/336 516/335 536/341\nf 420/315 491/334 418/338\nf 502/333 488/338 501/334\nf 501/333 401/338 500/334\nf 500/333 400/338 499/334\nf 406/315 498/334 404/338\nf 410/315 496/334 408/338\ng Mesh3 Lane Model\nv 69.999977 89.800034 -230.399963\nv 74.999977 89.800034 -230.399963\nv 74.999977 96.825020 -246.349976\nv 69.999977 96.825020 -246.349976\nv 69.999969 82.475029 -215.049973\nv 74.999969 82.475029 -215.049973\nv 69.999969 75.000031 -199.999969\nv 74.999969 75.000031 -199.999969\nv 69.999969 67.525024 -184.949966\nv 74.999969 67.525024 -184.949966\nv 69.999962 60.200027 -169.599976\nv 74.999962 60.200027 -169.599976\nv 69.999962 53.175049 -153.649963\nv 74.999962 53.175049 -153.649963\nv 69.999962 46.600052 -136.799957\nv 74.999962 46.600052 -136.799957\nv 69.999954 40.625046 -118.749969\nv 74.999954 40.625046 -118.749969\nv 69.999954 35.400040 -99.199982\nv 74.999954 35.400040 -99.199982\nv 69.999954 31.075043 -77.849976\nv 74.999954 31.075043 -77.849976\nv 69.999947 27.800064 -54.399963\nv 74.999947 27.800064 -54.399963\nv 69.999947 25.725067 -28.549957\nv 74.999947 25.725067 -28.549957\nv 69.999939 25.000061 0.000031\nv 74.999939 25.000061 0.000031\nv 69.999939 20.000061 0.000031\nv 69.999977 103.400024 -263.199951\nv 69.999985 109.375023 -281.249969\nv 69.999985 114.600014 -300.799988\nv 69.999985 118.925018 -322.149963\nv 69.999992 122.200005 -345.599976\nv 69.999992 124.275009 -371.449982\nv 70.000000 125.000000 -399.999969\nv 70.000000 120.000000 -399.999969\nv 69.999992 119.275009 -371.449982\nv 69.999992 117.200005 -345.599976\nv 69.999985 113.925018 -322.149963\nv 69.999985 109.600014 -300.799988\nv 69.999985 104.375023 -281.249969\nv 69.999977 98.400024 -263.199951\nv 69.999977 91.825020 -246.349976\nv 69.999977 84.800034 -230.399963\nv 69.999969 77.475029 -215.049973\nv 69.999969 70.000031 -199.999969\nv 69.999969 62.525024 -184.949966\nv 69.999962 55.200027 -169.599976\nv 69.999962 48.175049 -153.649963\nv 69.999962 41.600052 -136.799957\nv 69.999954 35.625046 -118.749969\nv 69.999954 30.400040 -99.199982\nv 69.999954 26.075043 -77.849976\nv 69.999947 22.800064 -54.399963\nv 69.999947 20.725067 -28.549957\nv 74.999939 20.000061 0.000031\nv 79.999939 25.000061 0.000031\nv 79.999939 30.000061 0.000031\nv 74.999939 30.000061 0.000031\nv 74.999947 20.725067 -28.549957\nv 74.999947 22.800064 -54.399963\nv 74.999954 26.075043 -77.849976\nv 74.999954 30.400040 -99.199982\nv 74.999954 35.625046 -118.749969\nv 74.999962 41.600052 -136.799957\nv 74.999962 48.175049 -153.649963\nv 74.999962 55.200027 -169.599976\nv 74.999969 62.525024 -184.949966\nv 74.999969 70.000031 -199.999969\nv 74.999969 77.475029 -215.049973\nv 74.999977 84.800034 -230.399963\nv 74.999977 91.825020 -246.349976\nv 74.999977 98.400024 -263.199951\nv 74.999985 104.375023 -281.249969\nv 74.999985 109.600014 -300.799988\nv 74.999985 113.925018 -322.149963\nv 74.999992 117.200005 -345.599976\nv 74.999992 119.275009 -371.449982\nv 75.000000 120.000000 -399.999969\nv 75.000000 125.000000 -399.999969\nv 75.000000 130.000000 -399.999969\nv 80.000000 130.000000 -399.999969\nv 80.000000 125.000000 -399.999969\nv 74.999992 124.275009 -371.449982\nv 74.999992 122.200005 -345.599976\nv 74.999985 118.925018 -322.149963\nv 74.999985 114.600014 -300.799988\nv 74.999985 109.375023 -281.249969\nv 74.999977 103.400024 -263.199951\nv 74.999947 30.725067 -28.549957\nv 74.999947 32.800064 -54.399963\nv 74.999954 36.075043 -77.849976\nv 74.999954 40.400040 -99.199982\nv 74.999954 45.625046 -118.749969\nv 74.999962 51.600052 -136.799957\nv 74.999962 58.175049 -153.649963\nv 74.999962 65.200027 -169.599976\nv 74.999969 72.525040 -184.949966\nv 74.999969 80.000031 -199.999969\nv 74.999969 87.475029 -215.049973\nv 74.999977 94.800034 -230.399963\nv 74.999977 101.825020 -246.349976\nv 74.999977 108.400024 -263.199951\nv 74.999985 114.375023 -281.249969\nv 74.999985 119.600014 -300.799988\nv 74.999985 123.925018 -322.149963\nv 74.999992 127.200005 -345.599976\nv 74.999992 129.275009 -371.449982\nv 79.999947 30.725067 -28.549957\nv 79.999947 32.800064 -54.399963\nv 79.999954 36.075043 -77.849976\nv 79.999954 40.400040 -99.199982\nv 79.999954 45.625046 -118.749969\nv 79.999962 51.600052 -136.799957\nv 79.999962 58.175049 -153.649963\nv 79.999962 65.200027 -169.599976\nv 79.999969 72.525040 -184.949966\nv 79.999969 80.000031 -199.999969\nv 79.999969 87.475029 -215.049973\nv 79.999977 94.800034 -230.399963\nv 79.999977 101.825020 -246.349976\nv 79.999977 108.400024 -263.199951\nv 79.999985 114.375023 -281.249969\nv 79.999985 119.600014 -300.799988\nv 79.999985 123.925018 -322.149963\nv 79.999992 127.200005 -345.599976\nv 79.999992 129.275009 -371.449982\nv 79.999947 25.725067 -28.549957\nv 79.999947 27.800064 -54.399963\nv 79.999954 31.075043 -77.849976\nv 79.999954 35.400040 -99.199982\nv 79.999954 40.625046 -118.749969\nv 79.999962 46.600052 -136.799957\nv 79.999962 53.175049 -153.649963\nv 79.999962 60.200027 -169.599976\nv 79.999969 67.525024 -184.949966\nv 79.999969 75.000031 -199.999969\nv 79.999969 82.475029 -215.049973\nv 79.999977 89.800034 -230.399963\nv 79.999977 96.825020 -246.349976\nv 79.999977 103.400024 -263.199951\nv 79.999985 109.375023 -281.249969\nv 79.999985 114.600014 -300.799988\nv 79.999985 118.925018 -322.149963\nv 79.999992 122.200005 -345.599976\nv 79.999992 124.275009 -371.449982\nvt 0.400000 1.000000\nvt 0.000000 1.000000\nvt -0.000000 0.950000\nvt 0.000000 0.630000\nvt -0.000000 0.580000\nvt 0.400000 0.580000\nvt 0.700000 1.000000\nvt 0.750000 0.950000\nvt 0.700000 0.950000\nvt 0.000000 0.480000\nvt 0.400000 0.480000\nvt 0.400000 0.530000\nvt -0.000000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.900000\nvt -0.000000 0.900000\nvt 0.800000 0.530000\nvt 0.650000 1.000000\nvt 0.800000 0.630000\nvt 0.400000 0.630000\nvt -0.000000 0.360000\nvt -0.000000 0.310000\nvt 0.400000 0.310000\nvt -0.000000 0.680000\nvt 0.400000 0.680000\nvt 0.400000 0.730000\nvt 0.800000 0.360000\nvt 0.400000 0.360000\nvt 0.000000 0.410000\nvt 0.400000 0.410000\nvt -0.000000 0.780000\nvt 0.400000 0.780000\nvt 0.800000 0.410000\nvt 0.800000 0.480000\nvt 0.400000 0.950000\nvt 0.800000 0.580000\nvt 0.000000 0.530000\nvt 0.000000 0.730000\nvt 0.800000 0.260000\nvt 0.400000 0.260000\nvt -0.000000 0.260000\nvt 0.650000 0.950000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nvt 0.800000 0.310000\nf 547/354 548/355 549/356\nf 551/354 547/355 546/356\nf 553/354 551/355 550/356\nf 555/354 553/355 552/356\nf 557/354 555/355 554/356\nf 559/354 557/355 556/356\nf 561/354 559/355 558/356\nf 563/354 561/355 560/356\nf 565/354 563/355 562/356\nf 567/354 565/355 564/356\nf 569/354 567/355 566/356\nf 571/354 569/355 568/356\nf 571/357 570/358 572/359\nf 602/360 603/361 573/362\nf 606/363 602/364 574/365\nf 607/366 606/367 601/368\nf 599/369 608/366 607/367\nf 609/366 608/367 599/368\nf 610/366 609/367 598/368\nf 596/369 611/366 610/367\nf 612/366 611/367 596/368\nf 613/366 612/367 595/368\nf 593/369 614/366 613/367\nf 615/366 614/367 593/368\nf 616/366 615/367 592/368\nf 590/369 617/366 616/367\nf 618/366 617/367 590/368\nf 619/366 618/367 589/368\nf 620/366 619/367 588/368\nf 621/366 620/367 587/368\nf 622/366 621/367 586/368\nf 584/369 623/366 622/367\nf 624/366 623/367 584/368\nf 583/370 582/365 625/364\nf 625/360 582/371 626/362\nf 630/372 626/373 581/359\nf 631/354 630/355 580/356\nf 632/354 631/355 579/356\nf 633/354 632/355 578/356\nf 634/354 633/355 577/356\nf 635/354 634/355 576/356\nf 548/354 635/355 575/356\nf 655/374 636/375 605/376\nf 637/377 636/378 655/379\nf 638/377 637/378 656/379\nf 639/377 638/378 657/379\nf 640/377 639/378 658/379\nf 641/377 640/378 659/379\nf 642/377 641/378 660/379\nf 643/377 642/378 661/379\nf 644/377 643/378 662/379\nf 645/377 644/378 663/379\nf 646/377 645/378 664/379\nf 647/377 646/378 665/379\nf 648/377 647/378 666/379\nf 649/377 648/378 667/379\nf 650/377 649/378 668/379\nf 651/377 650/378 669/379\nf 652/377 651/378 670/379\nf 653/377 652/378 671/379\nf 654/377 653/378 672/379\nf 673/380 628/381 627/376\nf 569/357 571/373 636/378\nf 606/363 674/382 603/383\nf 607/366 675/384 674/385\nf 608/366 676/384 675/385\nf 609/366 677/384 676/385\nf 610/366 678/384 677/385\nf 611/366 679/384 678/385\nf 612/366 680/384 679/385\nf 613/366 681/384 680/385\nf 614/366 682/384 681/385\nf 615/366 683/384 682/385\nf 616/366 684/384 683/385\nf 617/366 685/384 684/385\nf 618/366 686/384 685/385\nf 619/366 687/384 686/385\nf 620/366 688/384 687/385\nf 621/366 689/384 688/385\nf 622/366 690/384 689/385\nf 623/366 691/384 690/385\nf 624/366 692/384 691/385\nf 692/386 624/387 625/364\nf 599/369 600/368 568/388\nf 564/388 562/356 597/369\nf 562/388 560/356 596/369\nf 558/388 556/356 594/369\nf 580/389 581/359 582/365\nf 579/388 580/356 583/369\nf 560/388 558/356 595/369\nf 578/388 579/356 584/369\nf 556/388 554/356 593/369\nf 577/388 578/356 585/369\nf 592/369 593/368 554/388\nf 600/369 601/368 570/388\nf 576/388 577/356 586/369\nf 587/369 588/368 575/388\nf 566/388 564/356 598/369\nf 588/369 589/368 549/388\nf 589/369 590/368 546/388\nf 590/369 591/368 550/388\nf 552/388 550/356 591/369\nf 572/359 570/358 601/390\nf 674/382 655/374 604/381\nf 664/379 683/385 684/384\nf 665/379 684/385 685/384\nf 675/384 656/391 655/379\nf 662/379 681/385 682/384\nf 666/379 685/385 686/384\nf 650/378 651/377 633/357\nf 676/384 657/391 656/379\nf 687/384 668/391 667/379\nf 668/379 687/385 688/384\nf 553/357 555/373 644/378\nf 677/384 658/391 657/379\nf 661/379 680/385 681/384\nf 690/384 671/391 670/379\nf 652/378 653/377 631/357\nf 678/384 659/391 658/379\nf 691/384 672/391 671/379\nf 692/384 673/391 672/379\nf 654/392 627/393 626/376\nf 659/379 678/385 679/384\nf 629/383 628/381 673/380\nf 660/379 679/385 680/384\nf 669/379 688/385 689/384\nf 639/378 640/377 563/357\nf 642/378 643/377 557/357\nf 653/378 654/377 630/357\nf 634/357 635/373 649/378\nf 651/378 652/377 632/357\nf 641/378 642/377 559/357\nf 605/376 636/375 571/394\nf 567/357 569/373 637/378\nf 640/378 641/377 561/357\nf 663/379 682/385 683/384\nf 638/378 639/377 565/357\nf 635/357 548/373 648/378\nf 548/357 547/373 647/378\nf 547/357 551/373 646/378\nf 645/378 646/377 551/357\nf 643/378 644/377 555/357\nf 546/388 547/354 549/356\nf 550/388 551/354 546/356\nf 552/388 553/354 550/356\nf 554/388 555/354 552/356\nf 556/388 557/354 554/356\nf 558/388 559/354 556/356\nf 560/388 561/354 558/356\nf 562/388 563/354 560/356\nf 564/388 565/354 562/356\nf 566/388 567/354 564/356\nf 568/388 569/354 566/356\nf 570/388 571/354 568/356\nf 573/373 571/357 572/359\nf 573/362 572/395 574/371\nf 604/396 605/397 573/362\nf 573/362 603/361 604/396\nf 573/362 574/371 602/360\nf 601/390 606/363 574/365\nf 600/369 607/366 601/368\nf 600/368 599/369 607/367\nf 598/369 609/366 599/368\nf 597/369 610/366 598/368\nf 597/368 596/369 610/367\nf 595/369 612/366 596/368\nf 594/369 613/366 595/368\nf 594/368 593/369 613/367\nf 592/369 615/366 593/368\nf 591/369 616/366 592/368\nf 591/368 590/369 616/367\nf 589/369 618/366 590/368\nf 588/369 619/366 589/368\nf 587/369 620/366 588/368\nf 586/369 621/366 587/368\nf 585/369 622/366 586/368\nf 585/368 584/369 622/367\nf 583/369 624/366 584/368\nf 624/387 583/370 625/364\nf 626/362 629/361 625/360\nf 626/362 627/397 628/396\nf 582/371 581/395 626/362\nf 626/362 628/396 629/361\nf 580/389 630/372 581/359\nf 579/388 631/354 580/356\nf 578/388 632/354 579/356\nf 577/388 633/354 578/356\nf 576/388 634/354 577/356\nf 575/388 635/354 576/356\nf 549/388 548/354 575/356\nf 604/381 655/374 605/376\nf 656/391 637/377 655/379\nf 657/391 638/377 656/379\nf 658/391 639/377 657/379\nf 659/391 640/377 658/379\nf 660/391 641/377 659/379\nf 661/391 642/377 660/379\nf 662/391 643/377 661/379\nf 663/391 644/377 662/379\nf 664/391 645/377 663/379\nf 665/391 646/377 664/379\nf 666/391 647/377 665/379\nf 667/391 648/377 666/379\nf 668/391 649/377 667/379\nf 669/391 650/377 668/379\nf 670/391 651/377 669/379\nf 671/391 652/377 670/379\nf 672/391 653/377 671/379\nf 673/391 654/377 672/379\nf 654/398 673/380 627/376\nf 637/377 569/357 636/378\nf 602/364 606/363 603/383\nf 606/367 607/366 674/385\nf 607/367 608/366 675/385\nf 608/367 609/366 676/385\nf 609/367 610/366 677/385\nf 610/367 611/366 678/385\nf 611/367 612/366 679/385\nf 612/367 613/366 680/385\nf 613/367 614/366 681/385\nf 614/367 615/366 682/385\nf 615/367 616/366 683/385\nf 616/367 617/366 684/385\nf 617/367 618/366 685/385\nf 618/367 619/366 686/385\nf 619/367 620/366 687/385\nf 620/367 621/366 688/385\nf 621/367 622/366 689/385\nf 622/367 623/366 690/385\nf 623/367 624/366 691/385\nf 629/383 692/386 625/364\nf 566/356 599/369 568/388\nf 598/368 564/388 597/369\nf 597/368 562/388 596/369\nf 595/368 558/388 594/369\nf 583/370 580/389 582/365\nf 584/368 579/388 583/369\nf 596/368 560/388 595/369\nf 585/368 578/388 584/369\nf 594/368 556/388 593/369\nf 586/368 577/388 585/369\nf 552/356 592/369 554/388\nf 568/356 600/369 570/388\nf 587/368 576/388 586/369\nf 576/356 587/369 575/388\nf 599/368 566/388 598/369\nf 575/356 588/369 549/388\nf 549/356 589/369 546/388\nf 546/356 590/369 550/388\nf 592/368 552/388 591/369\nf 574/365 572/359 601/390\nf 603/383 674/382 604/381\nf 665/391 664/379 684/384\nf 666/391 665/379 685/384\nf 674/385 675/384 655/379\nf 663/391 662/379 682/384\nf 667/391 666/379 686/384\nf 634/373 650/378 633/357\nf 675/385 676/384 656/379\nf 686/385 687/384 667/379\nf 669/391 668/379 688/384\nf 645/377 553/357 644/378\nf 676/385 677/384 657/379\nf 662/391 661/379 681/384\nf 689/385 690/384 670/379\nf 632/373 652/378 631/357\nf 677/385 678/384 658/379\nf 690/385 691/384 671/379\nf 691/385 692/384 672/379\nf 630/398 654/392 626/376\nf 660/391 659/379 679/384\nf 692/386 629/383 673/380\nf 661/391 660/379 680/384\nf 670/391 669/379 689/384\nf 565/373 639/378 563/357\nf 559/373 642/378 557/357\nf 631/373 653/378 630/357\nf 650/377 634/357 649/378\nf 633/373 651/378 632/357\nf 561/373 641/378 559/357\nf 573/393 605/376 571/394\nf 638/377 567/357 637/378\nf 563/373 640/378 561/357\nf 664/391 663/379 683/384\nf 567/373 638/378 565/357\nf 649/377 635/357 648/378\nf 648/377 548/357 647/378\nf 647/377 547/357 646/378\nf 553/373 645/378 551/357\nf 557/373 643/378 555/357\ng Mesh11 Mount_D_L MountG1 Model\nv 20.000000 0.000009 -52.500000\nv 25.000000 0.000009 -52.500000\nv 25.000000 22.647507 -52.499996\nv 20.000000 27.647507 -52.499996\nv 20.000000 0.000008 -46.500000\nv 25.000000 0.000008 -46.500000\nv 20.000000 27.165907 -46.499996\nv 25.000000 22.165907 -46.499996\nvt 0.930000 -0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.190000\nvt 0.860000 0.110000\nvt 0.930000 0.110000\nvt 0.860000 0.120000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.650000 0.190000\nvt 0.930000 0.020000\nvt 0.860000 0.100000\nvt 0.860000 0.020000\nvt 0.930000 0.100000\nvt 0.700000 0.000000\nvt 0.860000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.070000\nf 693/399 694/400 695/401\nf 698/402 694/403 693/404\nf 697/405 699/406 700/407\nf 693/402 696/408 699/406\nf 695/409 699/410 696/411\nf 700/412 699/410 695/409\nf 700/407 695/413 694/414\nf 696/415 693/399 695/401\nf 697/416 698/402 693/404\nf 698/417 697/405 700/407\nf 697/405 693/402 699/406\nf 698/417 700/407 694/414\ng Mesh18 Mount_U_L1 MountG2 Model\nv 20.000000 200.000061 -347.890961\nv 25.000000 200.000061 -347.890961\nv 25.000000 177.353058 -347.890961\nv 20.000000 172.353058 -347.890961\nv 20.000000 200.000061 -353.890961\nv 25.000000 200.000061 -353.890961\nv 20.000000 172.834061 -353.890961\nv 25.000000 177.834061 -353.890961\nvt 0.930000 -0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.190000\nvt 0.860000 0.110000\nvt 0.930000 0.110000\nvt 0.860000 0.120000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.650000 0.190000\nvt 0.930000 0.020000\nvt 0.860000 0.100000\nvt 0.860000 0.020000\nvt 0.930000 0.100000\nvt 0.700000 0.000000\nvt 0.860000 0.000000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.070000\nf 701/418 702/419 703/420\nf 706/421 702/422 701/423\nf 705/424 707/425 708/426\nf 701/421 704/427 707/425\nf 703/428 707/429 704/430\nf 708/431 707/429 703/428\nf 708/426 703/432 702/433\nf 704/434 701/418 703/420\nf 705/435 706/421 701/423\nf 706/436 705/424 708/426\nf 705/424 701/421 707/425\nf 706/436 708/426 702/433\ng Mesh8 Mount_U_L MountG1 Model\nv 20.000000 100.000008 -46.999985\nv 25.000000 100.000008 -46.999985\nv 25.000000 82.206009 -46.999985\nv 20.000000 77.206009 -46.999989\nv 20.000000 100.000008 -52.999985\nv 25.000000 100.000008 -52.999985\nv 20.000000 77.682709 -52.999989\nv 25.000000 82.687607 -52.999985\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.010000\nvt 0.930000 0.010000\nvt 0.930000 0.060000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nvt 0.860000 0.080000\nvt 0.650000 0.120000\nvt 0.860000 0.190000\nvt 0.860000 -0.000000\nvt 0.930000 0.210000\nvt 0.860000 0.060000\nvt 0.930000 0.080000\nvt 0.650000 0.190000\nvt 0.700000 0.000000\nf 709/437 710/438 711/439\nf 714/440 710/441 709/442\nf 716/443 714/444 713/445\nf 715/446 712/447 711/448\nf 715/449 713/445 709/450\nf 716/451 711/444 710/443\nf 712/452 709/437 711/439\nf 713/453 714/440 709/442\nf 715/449 716/443 713/445\nf 716/454 715/446 711/448\nf 712/455 715/449 709/450\nf 714/456 716/451 710/443\ng Mesh17 Mount_D_L1 MountG2 Model\nv 20.000000 100.000061 -353.390961\nv 25.000000 100.000061 -353.390961\nv 25.000000 117.794060 -353.390961\nv 20.000000 122.794060 -353.390961\nv 20.000000 100.000053 -347.390961\nv 25.000000 100.000053 -347.390961\nv 20.000000 122.317055 -347.390961\nv 25.000000 117.312050 -347.390961\nvt 0.930000 -0.000000\nvt 0.980000 -0.000000\nvt 0.980000 0.160000\nvt 0.860000 0.010000\nvt 0.930000 0.010000\nvt 0.930000 0.060000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nvt 0.860000 0.080000\nvt 0.650000 0.120000\nvt 0.860000 0.190000\nvt 0.860000 -0.000000\nvt 0.930000 0.210000\nvt 0.860000 0.060000\nvt 0.930000 0.080000\nvt 0.650000 0.190000\nvt 0.700000 0.000000\nf 717/457 718/458 719/459\nf 722/460 718/461 717/462\nf 724/463 722/464 721/465\nf 723/466 720/467 719/468\nf 723/469 721/465 717/470\nf 724/471 719/464 718/463\nf 720/472 717/457 719/459\nf 721/473 722/460 717/462\nf 723/469 724/463 721/465\nf 724/474 723/466 719/468\nf 720/475 723/469 717/470\nf 722/476 724/471 718/463\n"
  },
  {
    "path": "resources/logisticspipes/models/HSTube-Line_result.obj",
    "content": "g Mesh11 Mount_D_W Model\nv 20.000000 0.000008 -46.500000\nv 25.000000 0.000008 -46.500000\nv 25.000000 20.000008 -46.499996\nv 20.000000 25.000008 -46.499996\nv 20.000000 0.000009 -52.500000\nv 25.000000 0.000009 -52.500000\nv 20.000000 25.000008 -52.499996\nv 25.000000 20.000008 -52.499996\nv 20.000000 25.000008 -47.499996\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.860000 0.180000\nvt 0.930000 0.180000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.860000 0.100000\nvt 0.700000 -0.000000\nf 1/1 2/2 3/3\nf 6/4 2/5 1/6\nf 8/7 6/8 5/9\nf 9/10 7/11 8/12\nf 9/13 7/14 5/15\nf 6/3 8/2 3/4\nf 4/16 1/1 3/3\nf 5/9 6/4 1/6\nf 7/17 8/7 5/9\nf 3/18 4/10 9/10\nf 9/10 8/12 3/18\nf 1/1 4/16 9/13\nf 9/13 5/15 1/1\nf 2/19 6/3 3/4\ng Mesh5 Mount_E_D Model\nv 100.000000 20.000008 -46.499996\nv 100.000000 25.000008 -46.499996\nv 80.000000 25.000008 -46.499996\nv 75.000000 20.000008 -46.499996\nv 100.000000 20.000008 -52.499996\nv 100.000000 25.000008 -52.499996\nv 75.000000 20.000008 -52.499996\nv 80.000000 25.000008 -52.499996\nv 75.000000 20.000008 -47.499996\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.860000 0.180000\nvt 0.930000 0.180000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.860000 0.100000\nvt 0.700000 -0.000000\nf 10/20 11/21 12/22\nf 15/23 11/24 10/25\nf 17/26 15/27 14/28\nf 18/29 16/30 17/31\nf 18/32 16/33 14/34\nf 15/22 17/21 12/23\nf 13/35 10/20 12/22\nf 14/28 15/23 10/25\nf 16/36 17/26 14/28\nf 12/37 13/29 18/29\nf 18/29 17/31 12/37\nf 10/20 13/35 18/32\nf 18/32 14/34 10/20\nf 11/38 15/22 12/23\ng Mesh2 Side Model\nv 80.000000 70.000000 0.000011\nv 75.000000 70.000000 0.000011\nv 75.000000 70.000015 -99.999992\nv 80.000000 70.000015 -99.999992\nv 80.000000 75.000000 0.000012\nv 75.000000 80.000000 0.000013\nv 70.000000 80.000000 0.000013\nv 70.000000 75.000000 0.000012\nv 75.000000 75.000000 0.000012\nv 80.000000 75.000015 -99.999985\nv 75.000000 75.000015 -99.999985\nv 70.000000 75.000015 -99.999985\nv 70.000000 80.000015 -99.999985\nv 75.000000 80.000015 -99.999985\nvt -0.000000 0.680000\nvt 1.000000 0.680000\nvt 1.000000 0.730000\nvt 0.640000 0.000000\nvt 0.640000 0.060000\nvt 0.590000 0.050000\nvt 1.000000 0.780000\nvt 0.000000 0.780000\nvt 0.000000 0.730000\nvt 0.600000 0.100000\nvt 1.000000 0.630000\nvt 1.000000 1.000000\nvt 0.000000 1.000000\nvt 0.000000 0.950000\nvt 1.000000 0.950000\nvt 0.000000 0.900000\nvt -0.000000 0.850000\nvt 1.000000 0.850000\nvt 0.540000 0.100000\nvt 0.540000 0.050000\nvt 0.590000 0.000000\nvt 0.000000 0.630000\nvt 1.000000 0.900000\nf 20/39 21/40 22/41\nf 19/42 23/43 27/44\nf 28/45 23/46 19/47\nf 28/43 29/44 32/48\nf 29/49 21/40 20/39\nf 29/50 27/51 26/52\nf 30/53 26/52 25/54\nf 25/54 24/55 32/56\nf 23/46 28/45 32/56\nf 19/47 20/39 22/41\nf 25/57 26/58 27/44\nf 27/44 20/59 19/42\nf 27/44 23/43 24/48\nf 24/48 25/57 27/44\nf 22/41 28/45 19/47\nf 29/44 28/43 22/42\nf 30/58 31/57 32/48\nf 22/42 21/59 29/44\nf 29/44 30/58 32/48\nf 27/60 29/49 20/39\nf 30/53 29/50 26/52\nf 31/61 30/53 25/54\nf 31/61 25/54 32/56\nf 24/55 23/46 32/56\ng Mesh7 Mount_W_U Model\nv 25.000000 80.000008 -52.499989\nv 20.000000 75.000008 -52.499989\nv 0.000000 75.000008 -52.499989\nv 0.000000 80.000008 -52.499989\nv 20.000000 75.000008 -46.499989\nv 25.000000 80.000008 -46.499989\nv 25.000000 80.000008 -51.499989\nv 0.000000 75.000008 -46.499989\nv 0.000000 80.000008 -46.499989\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.930000 0.080000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.700000 -0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.110000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nvt 0.650000 0.190000\nvt 0.650000 0.120000\nvt 0.870000 0.080000\nvt 0.930000 0.210000\nvt 0.860000 0.110000\nvt 0.860000 0.190000\nf 34/62 35/63 36/64\nf 39/65 34/66 37/67\nf 37/68 40/62 35/63\nf 41/69 40/70 37/71\nf 35/72 40/73 41/74\nf 39/74 36/75 41/76\nf 33/76 34/62 36/64\nf 34/66 39/65 33/69\nf 39/65 37/67 38/77\nf 34/66 37/68 35/63\nf 38/78 41/69 37/71\nf 36/79 35/72 41/74\nf 36/75 39/74 33/80\nf 39/74 41/76 38/64\ng Mesh10 Mount_D_E Model\nv 80.000000 0.000009 -52.500000\nv 75.000000 0.000009 -52.500000\nv 75.000000 20.000008 -52.499996\nv 80.000000 25.000008 -52.499996\nv 80.000000 0.000008 -46.500000\nv 75.000000 0.000008 -46.500000\nv 80.000000 25.000008 -46.499996\nv 75.000000 20.000008 -46.499996\nv 80.000000 25.000008 -51.499996\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.860000 0.180000\nvt 0.930000 0.180000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.860000 0.100000\nvt 0.700000 -0.000000\nf 42/81 43/82 44/83\nf 47/84 43/85 42/86\nf 49/87 47/88 46/89\nf 50/90 48/91 49/92\nf 50/93 48/94 46/95\nf 47/83 49/82 44/84\nf 45/96 42/81 44/83\nf 46/89 47/84 42/86\nf 48/97 49/87 46/89\nf 44/98 45/90 50/90\nf 50/90 49/92 44/98\nf 42/81 45/96 50/93\nf 50/93 46/95 42/81\nf 43/99 47/83 44/84\ng Mesh9 Mount_U_E Model\nv 80.000000 100.000008 -46.499985\nv 75.000000 100.000008 -46.499985\nv 75.000000 80.000008 -46.499989\nv 80.000000 75.000008 -46.499989\nv 80.000000 100.000008 -52.499985\nv 75.000000 100.000008 -52.499985\nv 80.000000 75.000008 -52.499989\nv 75.000000 80.000008 -52.499989\nv 80.000000 75.000008 -47.499989\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.860000 0.180000\nvt 0.930000 0.180000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.860000 0.100000\nvt 0.700000 -0.000000\nf 51/100 52/101 53/102\nf 56/103 52/104 51/105\nf 58/106 56/107 55/108\nf 59/109 57/110 58/111\nf 59/112 57/113 55/114\nf 56/102 58/101 53/103\nf 54/115 51/100 53/102\nf 55/108 56/103 51/105\nf 57/116 58/106 55/108\nf 53/117 54/109 59/109\nf 59/109 58/111 53/117\nf 51/100 54/115 59/112\nf 59/112 55/114 51/100\nf 52/118 56/102 53/103\ng Mesh4 Mount_E_U Model\nv 75.000000 80.000008 -46.499989\nv 80.000000 75.000008 -46.499989\nv 100.000000 75.000008 -46.499989\nv 100.000000 80.000008 -46.499989\nv 80.000000 75.000008 -52.499989\nv 75.000000 80.000008 -52.499989\nv 75.000000 80.000008 -47.499989\nv 100.000000 75.000008 -52.499989\nv 100.000000 80.000008 -52.499989\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.930000 0.080000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.700000 -0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.110000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nvt 0.650000 0.190000\nvt 0.650000 0.120000\nvt 0.870000 0.080000\nvt 0.930000 0.210000\nvt 0.860000 0.110000\nvt 0.860000 0.190000\nf 61/119 62/120 63/121\nf 66/122 61/123 64/124\nf 64/125 67/119 62/120\nf 68/126 67/127 64/128\nf 62/129 67/130 68/131\nf 66/131 63/132 68/133\nf 60/133 61/119 63/121\nf 61/123 66/122 60/126\nf 66/122 64/124 65/134\nf 61/123 64/125 62/120\nf 65/135 68/126 64/128\nf 63/136 62/129 68/131\nf 63/132 66/131 60/137\nf 66/131 68/133 65/121\ng Mesh8 Mount_U_W Model\nv 20.000000 100.000008 -52.499985\nv 25.000000 100.000008 -52.499985\nv 25.000000 80.000008 -52.499989\nv 20.000000 75.000008 -52.499989\nv 20.000000 100.000008 -46.499985\nv 25.000000 100.000008 -46.499985\nv 20.000000 75.000008 -46.499989\nv 25.000000 80.000008 -46.499989\nv 20.000000 75.000008 -51.499989\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.860000 0.180000\nvt 0.930000 0.180000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.700000 -0.000000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.860000 0.100000\nf 69/138 70/139 71/140\nf 74/141 70/142 69/143\nf 76/144 74/145 73/146\nf 77/147 75/148 76/149\nf 77/150 75/151 73/152\nf 70/153 74/140 76/139\nf 72/154 69/138 71/140\nf 73/146 74/141 69/143\nf 75/155 76/144 73/146\nf 71/156 72/147 77/147\nf 77/147 76/149 71/156\nf 69/138 72/154 77/150\nf 77/150 73/152 69/138\nf 71/141 70/153 76/139\ng Mesh6 Mount_W_D Model\nv 0.000000 20.000008 -52.499996\nv 0.000000 25.000008 -52.499996\nv 20.000000 25.000008 -52.499996\nv 25.000000 20.000008 -52.499996\nv 0.000000 20.000008 -46.499996\nv 0.000000 25.000008 -46.499996\nv 25.000000 20.000008 -46.499996\nv 20.000000 25.000008 -46.499996\nv 25.000000 20.000008 -51.499996\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 -0.000000\nvt 0.860000 0.080000\nvt 0.930000 0.080000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.860000 0.180000\nvt 0.930000 0.180000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.860000 0.100000\nvt 0.700000 -0.000000\nf 78/157 79/158 80/159\nf 83/160 79/161 78/162\nf 85/163 83/164 82/165\nf 86/166 84/167 85/168\nf 86/169 84/170 82/171\nf 83/159 85/158 80/160\nf 81/172 78/157 80/159\nf 82/165 83/160 78/162\nf 84/173 85/163 82/165\nf 80/174 81/166 86/166\nf 86/166 85/168 80/174\nf 78/157 81/172 86/169\nf 86/169 82/171 78/157\nf 79/175 83/159 80/160\ng Mesh3 Side Model\nv 20.000000 70.000000 0.000011\nv 25.000000 70.000000 0.000011\nv 25.000000 70.000015 -99.999992\nv 20.000000 70.000015 -99.999992\nv 20.000000 75.000000 0.000012\nv 25.000000 80.000000 0.000013\nv 30.000000 80.000000 0.000013\nv 30.000000 75.000000 0.000012\nv 25.000000 75.000000 0.000012\nv 20.000000 75.000015 -99.999985\nv 25.000000 75.000015 -99.999985\nv 30.000000 75.000015 -99.999985\nv 30.000000 80.000015 -99.999985\nv 25.000000 80.000015 -99.999985\nvt -0.000000 0.680000\nvt 1.000000 0.680000\nvt 1.000000 0.730000\nvt 0.640000 0.000000\nvt 0.640000 0.060000\nvt 0.590000 0.050000\nvt 1.000000 0.780000\nvt 0.000000 0.780000\nvt 0.000000 0.730000\nvt 0.600000 0.100000\nvt 1.000000 0.630000\nvt 1.000000 1.000000\nvt 0.000000 1.000000\nvt 0.000000 0.950000\nvt 1.000000 0.950000\nvt 0.000000 0.900000\nvt -0.000000 0.850000\nvt 1.000000 0.850000\nvt 0.540000 0.100000\nvt 0.540000 0.050000\nvt 0.590000 0.000000\nvt 0.000000 0.630000\nvt 1.000000 0.900000\nf 88/176 89/177 90/178\nf 87/179 91/180 95/181\nf 96/182 91/183 87/184\nf 96/180 97/181 100/185\nf 97/186 89/177 88/176\nf 97/187 95/188 94/189\nf 98/190 94/189 93/191\nf 93/191 92/192 100/193\nf 91/183 96/182 100/193\nf 87/184 88/176 90/178\nf 93/194 94/195 95/181\nf 95/181 88/196 87/179\nf 95/181 91/180 92/185\nf 92/185 93/194 95/181\nf 90/178 96/182 87/184\nf 97/181 96/180 90/179\nf 98/195 99/194 100/185\nf 90/179 89/196 97/181\nf 97/181 98/195 100/185\nf 95/197 97/186 88/176\nf 98/190 97/187 94/189\nf 99/198 98/190 93/191\nf 99/198 93/191 100/193\nf 92/192 91/183 100/193\ng Mesh1 Side Model\nv 80.000000 30.000000 -0.000011\nv 75.000000 30.000000 -0.000011\nv 75.000000 30.000015 -100.000008\nv 80.000000 30.000015 -100.000008\nv 80.000000 25.000000 -0.000012\nv 75.000000 20.000000 -0.000013\nv 70.000000 20.000000 -0.000013\nv 70.000000 25.000000 -0.000012\nv 75.000000 25.000000 -0.000012\nv 80.000000 25.000015 -100.000015\nv 75.000000 25.000015 -100.000015\nv 70.000000 25.000015 -100.000015\nv 70.000000 20.000015 -100.000015\nv 75.000000 20.000015 -100.000015\nvt -0.000000 0.680000\nvt 1.000000 0.680000\nvt 1.000000 0.730000\nvt 0.640000 0.000000\nvt 0.640000 0.060000\nvt 0.590000 0.050000\nvt 1.000000 0.780000\nvt 0.000000 0.780000\nvt 0.600000 0.100000\nvt 0.000000 0.630000\nvt 1.000000 1.000000\nvt 0.000000 1.000000\nvt 0.000000 0.950000\nvt 1.000000 0.950000\nvt 0.000000 0.900000\nvt -0.000000 0.850000\nvt 1.000000 0.850000\nvt 0.000000 0.730000\nvt 0.540000 0.100000\nvt 0.540000 0.050000\nvt 0.590000 0.000000\nvt 1.000000 0.630000\nvt 1.000000 0.900000\nf 102/199 103/200 104/201\nf 101/202 105/203 109/204\nf 104/201 110/205 105/206\nf 110/203 111/204 114/207\nf 103/200 102/199 109/208\nf 111/209 109/210 108/211\nf 112/212 108/211 107/213\nf 107/213 106/214 114/215\nf 105/206 110/205 114/215\nf 101/216 102/199 104/201\nf 107/217 108/218 109/204\nf 109/204 102/219 101/202\nf 109/204 105/203 106/207\nf 106/207 107/217 109/204\nf 101/216 104/201 105/206\nf 111/204 110/203 104/202\nf 112/218 113/217 114/207\nf 104/202 103/219 111/204\nf 111/204 112/218 114/207\nf 111/220 103/200 109/208\nf 112/212 111/209 108/211\nf 113/221 112/212 107/213\nf 113/221 107/213 114/215\nf 106/214 105/206 114/215\ng Mesh0 Side Model\nv 20.000000 30.000000 -0.000011\nv 25.000000 30.000000 -0.000011\nv 25.000000 30.000015 -100.000008\nv 20.000000 30.000015 -100.000008\nv 20.000000 25.000000 -0.000012\nv 25.000000 20.000000 -0.000013\nv 30.000000 20.000000 -0.000013\nv 30.000000 25.000000 -0.000012\nv 25.000000 25.000000 -0.000012\nv 20.000000 25.000015 -100.000015\nv 25.000000 25.000015 -100.000015\nv 30.000000 25.000015 -100.000015\nv 30.000000 20.000015 -100.000015\nv 25.000000 20.000015 -100.000015\nvt -0.000000 0.680000\nvt 1.000000 0.680000\nvt 1.000000 0.730000\nvt 0.640000 0.000000\nvt 0.640000 0.060000\nvt 0.590000 0.050000\nvt 1.000000 0.780000\nvt 0.000000 0.780000\nvt 0.600000 0.100000\nvt 0.000000 0.630000\nvt 1.000000 1.000000\nvt 0.000000 1.000000\nvt 0.000000 0.950000\nvt 1.000000 0.950000\nvt 0.000000 0.900000\nvt -0.000000 0.850000\nvt 1.000000 0.850000\nvt 0.000000 0.730000\nvt 0.540000 0.100000\nvt 0.540000 0.050000\nvt 0.590000 0.000000\nvt 1.000000 0.630000\nvt 1.000000 0.900000\nf 116/222 117/223 118/224\nf 115/225 119/226 123/227\nf 118/224 124/228 119/229\nf 124/226 125/227 128/230\nf 117/223 116/222 123/231\nf 125/232 123/233 122/234\nf 126/235 122/234 121/236\nf 121/236 120/237 128/238\nf 119/229 124/228 128/238\nf 115/239 116/222 118/224\nf 121/240 122/241 123/227\nf 123/227 116/242 115/225\nf 123/227 119/226 120/230\nf 120/230 121/240 123/227\nf 115/239 118/224 119/229\nf 125/227 124/226 118/225\nf 126/241 127/240 128/230\nf 118/225 117/242 125/227\nf 125/227 126/241 128/230\nf 125/243 117/223 123/231\nf 126/235 125/232 122/234\nf 127/244 126/235 121/236\nf 127/244 121/236 128/238\nf 120/237 119/229 128/238\n"
  },
  {
    "path": "resources/logisticspipes/models/HSTube-Speedup_result.obj",
    "content": "g Mesh19 Mount_U_R1 Mount_G_2 Model\nv 80.000000 100.000038 -246.999985\nv 75.000000 100.000038 -246.999985\nv 75.000000 80.000038 -246.999985\nv 80.000000 75.000038 -246.999985\nv 80.000000 100.000038 -252.999985\nv 75.000000 100.000038 -252.999985\nv 80.000000 75.000038 -252.999985\nv 75.000000 80.000038 -252.999985\nv 80.000000 75.000038 -247.999985\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 1/1 2/2 3/3\nf 6/4 2/5 1/6\nf 8/7 6/8 5/9\nf 9/10 7/4 8/9\nf 9/11 7/12 5/6\nf 6/13 8/14 3/3\nf 4/15 1/1 3/3\nf 5/16 6/4 1/6\nf 7/17 8/7 5/9\nf 3/13 4/5 9/10\nf 9/10 8/9 3/13\nf 1/1 4/15 9/11\nf 9/11 5/6 1/1\nf 2/2 6/13 3/3\ng Mesh22 Mount_U_L2 Mount_G_3 Model\nv 20.000000 100.000061 -352.999969\nv 25.000000 100.000061 -352.999969\nv 25.000000 80.000061 -353.000000\nv 20.000000 75.000061 -353.000000\nv 20.000000 100.000053 -346.999969\nv 25.000000 100.000053 -346.999969\nv 20.000000 75.000053 -347.000000\nv 25.000000 80.000053 -347.000000\nv 20.000000 75.000061 -352.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 10/18 11/19 12/20\nf 15/21 11/22 10/23\nf 17/24 15/25 14/26\nf 18/27 16/21 17/26\nf 18/28 16/29 14/23\nf 11/19 15/30 17/31\nf 13/32 10/18 12/20\nf 14/33 15/21 10/23\nf 16/34 17/24 14/26\nf 12/30 13/22 18/27\nf 18/27 17/26 12/30\nf 10/18 13/32 18/28\nf 18/28 14/23 10/18\nf 12/20 11/19 17/31\ng Mesh27 Mount_U_R2 Mount_G_3 Model\nv 80.000000 100.000053 -346.999969\nv 75.000000 100.000053 -346.999969\nv 75.000000 80.000053 -347.000000\nv 80.000000 75.000053 -347.000000\nv 80.000000 100.000061 -352.999969\nv 75.000000 100.000061 -352.999969\nv 80.000000 75.000061 -353.000000\nv 75.000000 80.000061 -353.000000\nv 80.000000 75.000053 -348.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 19/35 20/36 21/37\nf 24/38 20/39 19/40\nf 26/41 24/42 23/43\nf 27/44 25/38 26/43\nf 27/45 25/46 23/40\nf 24/47 26/48 21/37\nf 22/49 19/35 21/37\nf 23/50 24/38 19/40\nf 25/51 26/41 23/43\nf 21/47 22/39 27/44\nf 27/44 26/43 21/47\nf 19/35 22/49 27/45\nf 27/45 23/40 19/35\nf 20/36 24/47 21/37\ng Mesh12 Mount_D_R1 Mount_G_2 Model\nv 80.000000 0.000041 -253.000000\nv 75.000000 0.000041 -253.000000\nv 75.000000 20.000042 -253.000000\nv 80.000000 25.000042 -253.000000\nv 80.000000 0.000040 -247.000000\nv 75.000000 0.000040 -247.000000\nv 80.000000 25.000040 -247.000000\nv 75.000000 20.000040 -247.000000\nv 80.000000 25.000042 -252.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 28/52 29/53 30/54\nf 33/55 29/56 28/57\nf 35/58 33/59 32/60\nf 36/61 34/55 35/60\nf 36/62 34/63 32/57\nf 33/64 35/65 30/54\nf 31/66 28/52 30/54\nf 32/67 33/55 28/57\nf 34/68 35/58 32/60\nf 30/64 31/56 36/61\nf 36/61 35/60 30/64\nf 28/52 31/66 36/62\nf 36/62 32/57 28/52\nf 29/53 33/64 30/54\ng Mesh26 Mount_R_U2 Mount_G_3 Model\nv 75.000000 80.000053 -347.000000\nv 80.000000 75.000053 -347.000000\nv 100.000000 75.000053 -347.000000\nv 100.000000 80.000053 -347.000000\nv 80.000000 75.000061 -353.000000\nv 75.000000 80.000061 -353.000000\nv 75.000000 80.000053 -348.000000\nv 100.000000 75.000061 -353.000000\nv 100.000000 80.000061 -353.000000\nvt 0.922727 0.270270\nvt 0.959091 0.270270\nvt 0.959091 0.405405\nvt 0.975000 0.081081\nvt 0.959091 0.081081\nvt 0.963636 0.378378\nvt 0.922727 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.975000 0.594595\nvt 0.911364 0.432432\nvt 0.911364 0.405405\nvt 0.975000 0.378378\nvt 0.975000 0.648649\nvt 0.911364 0.594595\nf 38/69 39/70 40/71\nf 38/72 41/73 43/74\nf 41/70 44/73 39/75\nf 45/72 44/76 41/77\nf 40/78 39/79 44/80\nf 43/81 40/79 45/71\nf 37/82 38/69 40/71\nf 41/73 42/78 43/74\nf 43/74 37/83 38/72\nf 38/69 41/70 39/75\nf 42/84 45/72 41/77\nf 45/83 40/78 44/80\nf 40/79 43/81 37/85\nf 43/81 45/71 42/82\ng Mesh7 Mount_L_D Mount_G_1 Model\nv 0.000000 20.000025 -153.000000\nv 0.000000 25.000025 -153.000000\nv 20.000000 25.000025 -153.000000\nv 25.000000 20.000025 -153.000000\nv 0.000000 20.000025 -147.000000\nv 0.000000 25.000025 -147.000000\nv 25.000000 20.000025 -147.000000\nv 20.000000 25.000025 -147.000000\nv 25.000000 20.000025 -152.000000\nvt 0.975000 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.959091 0.405405\nvt 0.975000 0.405405\nvt 0.920455 0.270270\nvt 0.959091 0.270270\nvt 0.972727 0.270270\nvt 0.959091 0.081081\nvt 0.959091 0.432432\nvt 0.911364 0.594595\nvt 0.922727 0.081081\nvt 0.975000 0.648649\nvt 0.975000 0.594595\nvt 0.911364 0.405405\nvt 0.975000 0.270270\nvt 0.922727 0.270270\nf 46/86 47/87 48/88\nf 51/89 47/90 46/91\nf 53/92 51/93 50/90\nf 54/94 52/93 53/95\nf 54/96 52/89 50/97\nf 51/98 53/95 48/93\nf 49/99 46/86 48/88\nf 50/100 51/89 46/91\nf 52/101 53/92 50/90\nf 48/86 49/102 54/94\nf 54/94 53/95 48/86\nf 46/101 49/90 54/96\nf 54/96 50/97 46/101\nf 47/103 51/98 48/93\ng Mesh17 Mount_L_U1 Mount_G_2 Model\nv 25.000000 80.000038 -252.999985\nv 20.000000 75.000038 -252.999985\nv 0.000000 75.000038 -252.999985\nv 0.000000 80.000038 -252.999985\nv 20.000000 75.000038 -246.999985\nv 25.000000 80.000038 -246.999985\nv 25.000000 80.000038 -251.999985\nv 0.000000 75.000038 -246.999985\nv 0.000000 80.000038 -246.999985\nvt 0.922727 0.270270\nvt 0.959091 0.270270\nvt 0.959091 0.405405\nvt 0.963636 0.378378\nvt 0.975000 0.081081\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.975000 0.594595\nvt 0.975000 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.405405\nvt 0.959091 0.378378\nvt 0.975000 0.648649\nvt 0.911364 0.594595\nf 56/104 57/105 58/106\nf 61/107 56/108 59/109\nf 59/105 62/109 57/110\nf 63/108 62/111 59/112\nf 57/113 62/114 63/115\nf 61/116 58/113 63/106\nf 55/117 56/104 58/106\nf 56/108 61/107 55/115\nf 61/107 59/109 60/118\nf 56/104 59/105 57/110\nf 60/119 63/108 59/112\nf 58/118 57/113 63/115\nf 58/113 61/116 55/120\nf 61/116 63/106 60/117\ng Mesh9 Mount_L_U Mount_G_1 Model\nv 25.000000 80.000023 -152.999985\nv 20.000000 75.000023 -152.999985\nv 0.000000 75.000023 -152.999985\nv 0.000000 80.000023 -152.999985\nv 20.000000 75.000023 -146.999985\nv 25.000000 80.000023 -146.999985\nv 25.000000 80.000023 -151.999985\nv 0.000000 75.000023 -146.999985\nv 0.000000 80.000023 -146.999985\nvt 0.922727 0.270270\nvt 0.959091 0.270270\nvt 0.959091 0.405405\nvt 0.963636 0.378378\nvt 0.975000 0.081081\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.975000 0.594595\nvt 0.975000 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.405405\nvt 0.959091 0.378378\nvt 0.975000 0.648649\nvt 0.911364 0.594595\nf 65/121 66/122 67/123\nf 70/124 65/125 68/126\nf 68/122 71/126 66/127\nf 72/125 71/128 68/129\nf 66/130 71/131 72/132\nf 70/133 67/130 72/123\nf 64/134 65/121 67/123\nf 65/125 70/124 64/132\nf 70/124 68/126 69/135\nf 65/121 68/122 66/127\nf 69/136 72/125 68/129\nf 67/135 66/130 72/132\nf 67/130 70/133 64/137\nf 70/133 72/123 69/134\ng Mesh23 Mount_L_D2 Mount_G_3 Model\nv 0.000000 20.000057 -353.000000\nv 0.000000 25.000057 -353.000000\nv 20.000000 25.000057 -353.000000\nv 25.000000 20.000057 -353.000000\nv 0.000000 20.000057 -347.000000\nv 0.000000 25.000057 -347.000000\nv 25.000000 20.000057 -347.000000\nv 20.000000 25.000057 -347.000000\nv 25.000000 20.000057 -352.000000\nvt 0.975000 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.959091 0.405405\nvt 0.975000 0.405405\nvt 0.920455 0.270270\nvt 0.959091 0.270270\nvt 0.972727 0.270270\nvt 0.959091 0.081081\nvt 0.959091 0.432432\nvt 0.911364 0.594595\nvt 0.922727 0.081081\nvt 0.975000 0.648649\nvt 0.975000 0.594595\nvt 0.911364 0.405405\nvt 0.975000 0.270270\nvt 0.922727 0.270270\nf 73/138 74/139 75/140\nf 78/141 74/142 73/143\nf 80/144 78/145 77/142\nf 81/146 79/145 80/147\nf 81/148 79/141 77/149\nf 78/150 80/147 75/145\nf 76/151 73/138 75/140\nf 77/152 78/141 73/143\nf 79/153 80/144 77/142\nf 75/138 76/154 81/146\nf 81/146 80/147 75/138\nf 73/153 76/142 81/148\nf 81/148 77/149 73/153\nf 74/155 78/150 75/145\ng Mesh11 Mount_U_R Mount_G_1 Model\nv 80.000000 100.000023 -146.999985\nv 75.000000 100.000023 -146.999985\nv 75.000000 80.000023 -146.999985\nv 80.000000 75.000023 -146.999985\nv 80.000000 100.000023 -152.999985\nv 75.000000 100.000023 -152.999985\nv 80.000000 75.000023 -152.999985\nv 75.000000 80.000023 -152.999985\nv 80.000000 75.000023 -147.999985\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 82/156 83/157 84/158\nf 87/159 83/160 82/161\nf 89/162 87/163 86/164\nf 90/165 88/159 89/164\nf 90/166 88/167 86/161\nf 87/168 89/169 84/158\nf 85/170 82/156 84/158\nf 86/171 87/159 82/161\nf 88/172 89/162 86/164\nf 84/168 85/160 90/165\nf 90/165 89/164 84/168\nf 82/156 85/170 90/166\nf 90/166 86/161 82/156\nf 83/157 87/168 84/158\ng Mesh8 Mount_R_D Mount_G_1 Model\nv 100.000000 20.000025 -147.000000\nv 100.000000 25.000025 -147.000000\nv 80.000000 25.000025 -147.000000\nv 75.000000 20.000025 -147.000000\nv 100.000000 20.000025 -153.000000\nv 100.000000 25.000025 -153.000000\nv 75.000000 20.000025 -153.000000\nv 80.000000 25.000025 -153.000000\nv 75.000000 20.000025 -148.000000\nvt 0.975000 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.959091 0.405405\nvt 0.975000 0.405405\nvt 0.920455 0.270270\nvt 0.959091 0.270270\nvt 0.972727 0.270270\nvt 0.959091 0.081081\nvt 0.959091 0.432432\nvt 0.911364 0.594595\nvt 0.922727 0.081081\nvt 0.975000 0.648649\nvt 0.975000 0.594595\nvt 0.911364 0.405405\nvt 0.975000 0.270270\nvt 0.922727 0.270270\nf 91/173 92/174 93/175\nf 96/176 92/177 91/178\nf 98/179 96/180 95/177\nf 99/181 97/180 98/182\nf 99/183 97/176 95/184\nf 96/185 98/182 93/180\nf 94/186 91/173 93/175\nf 95/187 96/176 91/178\nf 97/188 98/179 95/177\nf 93/173 94/189 99/181\nf 99/181 98/182 93/173\nf 91/188 94/177 99/183\nf 99/183 95/184 91/188\nf 92/190 96/185 93/180\ng Mesh24 Mount_R_D2 Mount_G_3 Model\nv 100.000000 20.000057 -347.000000\nv 100.000000 25.000057 -347.000000\nv 80.000000 25.000057 -347.000000\nv 75.000000 20.000057 -347.000000\nv 100.000000 20.000057 -353.000000\nv 100.000000 25.000057 -353.000000\nv 75.000000 20.000057 -353.000000\nv 80.000000 25.000057 -353.000000\nv 75.000000 20.000057 -348.000000\nvt 0.975000 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.959091 0.405405\nvt 0.975000 0.405405\nvt 0.920455 0.270270\nvt 0.959091 0.270270\nvt 0.972727 0.270270\nvt 0.959091 0.081081\nvt 0.959091 0.432432\nvt 0.911364 0.594595\nvt 0.922727 0.081081\nvt 0.975000 0.648649\nvt 0.975000 0.594595\nvt 0.911364 0.405405\nvt 0.975000 0.270270\nvt 0.922727 0.270270\nf 100/191 101/192 102/193\nf 105/194 101/195 100/196\nf 107/197 105/198 104/195\nf 108/199 106/198 107/200\nf 108/201 106/194 104/202\nf 105/203 107/200 102/198\nf 103/204 100/191 102/193\nf 104/205 105/194 100/196\nf 106/206 107/197 104/195\nf 102/191 103/207 108/199\nf 108/199 107/200 102/191\nf 100/206 103/195 108/201\nf 108/201 104/202 100/206\nf 101/208 105/203 102/198\ng Mesh25 Mount_L_U2 Mount_G_3 Model\nv 25.000000 80.000061 -353.000000\nv 20.000000 75.000061 -353.000000\nv 0.000000 75.000061 -353.000000\nv 0.000000 80.000061 -353.000000\nv 20.000000 75.000053 -347.000000\nv 25.000000 80.000053 -347.000000\nv 25.000000 80.000061 -352.000000\nv 0.000000 75.000053 -347.000000\nv 0.000000 80.000053 -347.000000\nvt 0.922727 0.270270\nvt 0.959091 0.270270\nvt 0.959091 0.405405\nvt 0.975000 0.081081\nvt 0.959091 0.081081\nvt 0.963636 0.378378\nvt 0.922727 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.975000 0.594595\nvt 0.975000 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.405405\nvt 0.959091 0.378378\nvt 0.975000 0.648649\nvt 0.911364 0.594595\nf 110/209 111/210 112/211\nf 110/212 113/213 115/214\nf 113/210 116/213 111/215\nf 117/212 116/216 113/217\nf 111/218 116/219 117/220\nf 115/221 112/218 117/211\nf 109/222 110/209 112/211\nf 113/213 114/223 115/214\nf 115/214 109/220 110/212\nf 110/209 113/210 111/215\nf 114/224 117/212 113/217\nf 112/223 111/218 117/220\nf 112/218 115/221 109/225\nf 115/221 117/211 114/222\ng Mesh5 Mount_D_L Mount_G_1 Model\nv 20.000000 0.000024 -147.000000\nv 25.000000 0.000024 -147.000000\nv 25.000000 20.000025 -147.000000\nv 20.000000 25.000025 -147.000000\nv 20.000000 0.000025 -153.000000\nv 25.000000 0.000025 -153.000000\nv 20.000000 25.000025 -153.000000\nv 25.000000 20.000025 -153.000000\nv 20.000000 25.000025 -148.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 118/226 119/227 120/228\nf 123/229 119/230 118/231\nf 125/232 123/233 122/234\nf 126/235 124/229 125/234\nf 126/236 124/237 122/231\nf 123/238 125/239 120/228\nf 121/240 118/226 120/228\nf 122/241 123/229 118/231\nf 124/242 125/232 122/234\nf 120/238 121/230 126/235\nf 126/235 125/234 120/238\nf 118/226 121/240 126/236\nf 126/236 122/231 118/226\nf 119/227 123/238 120/228\ng Mesh20 Mount_D_R2 Mount_G_3 Model\nv 80.000000 0.000058 -353.000000\nv 75.000000 0.000058 -353.000000\nv 75.000000 20.000057 -353.000000\nv 80.000000 25.000057 -353.000000\nv 80.000000 0.000057 -347.000000\nv 75.000000 0.000057 -347.000000\nv 80.000000 25.000057 -347.000000\nv 75.000000 20.000057 -347.000000\nv 80.000000 25.000057 -352.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 127/243 128/244 129/245\nf 132/246 128/247 127/248\nf 134/249 132/250 131/251\nf 135/252 133/246 134/251\nf 135/253 133/254 131/248\nf 132/255 134/256 129/245\nf 130/257 127/243 129/245\nf 131/258 132/246 127/248\nf 133/259 134/249 131/251\nf 129/255 130/247 135/252\nf 135/252 134/251 129/255\nf 127/243 130/257 135/253\nf 135/253 131/248 127/243\nf 128/244 132/255 129/245\ng Mesh18 Mount_R_U1 Mount_G_2 Model\nv 75.000000 80.000038 -246.999985\nv 80.000000 75.000038 -246.999985\nv 100.000000 75.000038 -246.999985\nv 100.000000 80.000038 -246.999985\nv 80.000000 75.000038 -252.999985\nv 75.000000 80.000038 -252.999985\nv 75.000000 80.000038 -247.999985\nv 100.000000 75.000038 -252.999985\nv 100.000000 80.000038 -252.999985\nvt 0.922727 0.270270\nvt 0.959091 0.270270\nvt 0.959091 0.405405\nvt 0.963636 0.378378\nvt 0.975000 0.081081\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.975000 0.594595\nvt 0.975000 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.405405\nvt 0.959091 0.378378\nvt 0.975000 0.648649\nvt 0.911364 0.594595\nf 137/260 138/261 139/262\nf 142/263 137/264 140/265\nf 140/261 143/265 138/266\nf 144/264 143/267 140/268\nf 138/269 143/270 144/271\nf 142/272 139/269 144/262\nf 136/273 137/260 139/262\nf 137/264 142/263 136/271\nf 142/263 140/265 141/274\nf 137/260 140/261 138/266\nf 141/275 144/264 140/268\nf 139/274 138/269 144/271\nf 139/269 142/272 136/276\nf 142/272 144/262 141/273\ng Mesh10 Mount_R_U Mount_G_1 Model\nv 75.000000 80.000023 -146.999985\nv 80.000000 75.000023 -146.999985\nv 100.000000 75.000023 -146.999985\nv 100.000000 80.000023 -146.999985\nv 80.000000 75.000023 -152.999985\nv 75.000000 80.000023 -152.999985\nv 75.000000 80.000023 -147.999985\nv 100.000000 75.000023 -152.999985\nv 100.000000 80.000023 -152.999985\nvt 0.922727 0.270270\nvt 0.959091 0.270270\nvt 0.959091 0.405405\nvt 0.963636 0.378378\nvt 0.975000 0.081081\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.975000 0.594595\nvt 0.975000 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.405405\nvt 0.959091 0.378378\nvt 0.975000 0.648649\nvt 0.911364 0.594595\nf 146/277 147/278 148/279\nf 151/280 146/281 149/282\nf 149/278 152/282 147/283\nf 153/281 152/284 149/285\nf 147/286 152/287 153/288\nf 151/289 148/286 153/279\nf 145/290 146/277 148/279\nf 146/281 151/280 145/288\nf 151/280 149/282 150/291\nf 146/277 149/278 147/283\nf 150/292 153/281 149/285\nf 148/291 147/286 153/288\nf 148/286 151/289 145/293\nf 151/289 153/279 150/290\ng Mesh0 Side_U_L Side Model\nv 31.250000 75.000015 -81.250000\nv 30.000000 75.000069 -400.000000\nv 30.000000 80.000069 -400.000000\nv 31.250000 81.250000 -81.250000\nv 25.000000 75.000069 -400.000000\nv 25.000000 75.000015 -81.250000\nv 25.000000 80.000069 -400.000000\nv 20.000000 75.000069 -400.000000\nv 20.000000 70.000069 -400.000000\nv 25.000000 70.000069 -400.000000\nv 18.750000 68.750000 -81.250000\nv 18.750000 75.000015 -81.250000\nv 25.000000 81.250000 -81.250000\nv 25.000000 68.750000 -81.250000\nvt 0.000000 0.864865\nvt 0.000000 0.729730\nvt 0.909091 0.729730\nvt 0.909091 0.864865\nvt 0.909091 1.000000\nvt 0.975000 0.837838\nvt 0.975000 0.972973\nvt 0.963636 0.972973\nvt 0.986364 0.837838\nvt 0.975000 0.702703\nvt 0.909091 0.405405\nvt -0.000000 0.405405\nvt 0.000000 0.270270\nvt 0.909091 0.594595\nvt -0.000000 0.594595\nvt 0.909091 0.135135\nvt 0.909091 0.270270\nvt 0.000000 0.135135\nvt 0.000000 0.000000\nvt 0.000000 1.000000\nvt 0.963636 0.837838\nvt 0.986364 0.702703\nvt 0.909091 0.000000\nf 155/294 156/295 157/296\nf 155/294 154/297 159/298\nf 158/299 160/300 156/301\nf 160/300 158/299 161/302\nf 161/302 158/299 163/303\nf 165/304 161/305 162/306\nf 161/305 165/304 166/307\nf 156/295 160/308 166/307\nf 167/309 164/310 162/306\nf 167/309 163/311 158/312\nf 154/297 155/294 157/296\nf 158/313 155/294 159/298\nf 155/314 158/299 156/301\nf 162/315 161/302 163/303\nf 164/310 165/304 162/306\nf 160/308 161/305 166/307\nf 157/296 156/295 166/307\nf 163/311 167/309 162/306\nf 159/316 167/309 158/312\ng Mesh6 Mount_U_L Mount_G_1 Model\nv 20.000000 100.000023 -152.999985\nv 25.000000 100.000023 -152.999985\nv 25.000000 80.000023 -152.999985\nv 20.000000 75.000023 -152.999985\nv 20.000000 100.000023 -146.999985\nv 25.000000 100.000023 -146.999985\nv 20.000000 75.000023 -146.999985\nv 25.000000 80.000023 -146.999985\nv 20.000000 75.000023 -151.999985\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 168/317 169/318 170/319\nf 173/320 169/321 168/322\nf 175/323 173/324 172/325\nf 176/326 174/320 175/325\nf 176/327 174/328 172/322\nf 173/329 175/330 170/319\nf 171/331 168/317 170/319\nf 172/332 173/320 168/322\nf 174/333 175/323 172/325\nf 170/329 171/321 176/326\nf 176/326 175/325 170/329\nf 168/317 171/331 176/327\nf 176/327 172/322 168/317\nf 169/318 173/329 170/319\ng Mesh21 Mount_D_L2 Mount_G_3 Model\nv 20.000000 0.000057 -347.000000\nv 25.000000 0.000057 -347.000000\nv 25.000000 20.000057 -347.000000\nv 20.000000 25.000057 -347.000000\nv 20.000000 0.000058 -353.000000\nv 25.000000 0.000058 -353.000000\nv 20.000000 25.000057 -353.000000\nv 25.000000 20.000057 -353.000000\nv 20.000000 25.000057 -348.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 177/334 178/335 179/336\nf 182/337 178/338 177/339\nf 184/340 182/341 181/342\nf 185/343 183/337 184/342\nf 185/344 183/345 181/339\nf 182/346 184/347 179/336\nf 180/348 177/334 179/336\nf 181/349 182/337 177/339\nf 183/350 184/340 181/342\nf 179/346 180/338 185/343\nf 185/343 184/342 179/346\nf 177/334 180/348 185/344\nf 185/344 181/339 177/334\nf 178/335 182/346 179/336\ng Mesh13 Mount_D_L1 Mount_G_2 Model\nv 20.000000 0.000040 -247.000000\nv 25.000000 0.000040 -247.000000\nv 25.000000 20.000040 -247.000000\nv 20.000000 25.000040 -247.000000\nv 20.000000 0.000041 -253.000000\nv 25.000000 0.000041 -253.000000\nv 20.000000 25.000042 -253.000000\nv 25.000000 20.000042 -253.000000\nv 20.000000 25.000040 -248.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 186/351 187/352 188/353\nf 191/354 187/355 186/356\nf 193/357 191/358 190/359\nf 194/360 192/354 193/359\nf 194/361 192/362 190/356\nf 191/363 193/364 188/353\nf 189/365 186/351 188/353\nf 190/366 191/354 186/356\nf 192/367 193/357 190/359\nf 188/363 189/355 194/360\nf 194/360 193/359 188/363\nf 186/351 189/365 194/361\nf 194/361 190/356 186/351\nf 187/352 191/363 188/353\ng Mesh14 Mount_U_L1 Mount_G_2 Model\nv 20.000000 100.000038 -252.999985\nv 25.000000 100.000038 -252.999985\nv 25.000000 80.000038 -252.999985\nv 20.000000 75.000038 -252.999985\nv 20.000000 100.000038 -246.999985\nv 25.000000 100.000038 -246.999985\nv 20.000000 75.000038 -246.999985\nv 25.000000 80.000038 -246.999985\nv 20.000000 75.000038 -251.999985\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 195/368 196/369 197/370\nf 200/371 196/372 195/373\nf 202/374 200/375 199/376\nf 203/377 201/371 202/376\nf 203/378 201/379 199/373\nf 200/380 202/381 197/370\nf 198/382 195/368 197/370\nf 199/383 200/371 195/373\nf 201/384 202/374 199/376\nf 197/380 198/372 203/377\nf 203/377 202/376 197/380\nf 195/368 198/382 203/378\nf 203/378 199/373 195/368\nf 196/369 200/380 197/370\ng Mesh16 Mount_R_D1 Mount_G_2 Model\nv 100.000000 20.000040 -247.000000\nv 100.000000 25.000040 -247.000000\nv 80.000000 25.000040 -247.000000\nv 75.000000 20.000040 -247.000000\nv 100.000000 20.000042 -253.000000\nv 100.000000 25.000042 -253.000000\nv 75.000000 20.000042 -253.000000\nv 80.000000 25.000042 -253.000000\nv 75.000000 20.000040 -248.000000\nvt 0.975000 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.975000 0.594595\nvt 0.959091 0.594595\nvt 0.959091 0.405405\nvt 0.920455 0.270270\nvt 0.959091 0.270270\nvt 0.972727 0.270270\nvt 0.959091 0.081081\nvt 0.959091 0.432432\nvt 0.911364 0.594595\nvt 0.922727 0.081081\nvt 0.975000 0.648649\nvt 0.975000 0.405405\nvt 0.911364 0.405405\nvt 0.975000 0.270270\nvt 0.922727 0.270270\nf 204/385 205/386 206/387\nf 208/388 209/389 205/390\nf 211/391 209/392 208/390\nf 212/393 210/392 211/394\nf 212/395 210/389 208/396\nf 209/397 211/394 206/392\nf 207/398 204/385 206/387\nf 204/399 208/388 205/390\nf 210/400 211/391 208/390\nf 206/385 207/401 212/393\nf 212/393 211/394 206/385\nf 204/400 207/390 212/395\nf 212/395 208/396 204/400\nf 205/402 209/397 206/392\ng Mesh4 Mount_D_R Mount_G_1 Model\nv 80.000000 0.000025 -153.000000\nv 75.000000 0.000025 -153.000000\nv 75.000000 20.000025 -153.000000\nv 80.000000 25.000025 -153.000000\nv 80.000000 0.000024 -147.000000\nv 75.000000 0.000024 -147.000000\nv 80.000000 25.000025 -147.000000\nv 75.000000 20.000025 -147.000000\nv 80.000000 25.000025 -152.000000\nvt 0.959091 0.405405\nvt 0.959091 0.270270\nvt 0.922727 0.270270\nvt 0.975000 0.378378\nvt 0.959091 0.378378\nvt 0.959091 0.594595\nvt 0.986364 0.513514\nvt 0.986364 0.081081\nvt 0.975000 0.081081\nvt 0.961364 0.378378\nvt 0.911364 0.432432\nvt 0.911364 0.594595\nvt 0.959091 0.081081\nvt 0.922727 0.081081\nvt 0.911364 0.405405\nvt 0.975000 0.594595\nvt 0.975000 0.648649\nf 213/403 214/404 215/405\nf 218/406 214/407 213/408\nf 220/409 218/410 217/411\nf 221/412 219/406 220/411\nf 221/413 219/414 217/408\nf 218/415 220/416 215/405\nf 216/417 213/403 215/405\nf 217/418 218/406 213/408\nf 219/419 220/409 217/411\nf 215/415 216/407 221/412\nf 221/412 220/411 215/415\nf 213/403 216/417 221/413\nf 221/413 217/408 213/403\nf 214/404 218/415 215/405\ng Mesh15 Mount_L_D1 Mount_G_2 Model\nv 0.000000 20.000042 -253.000000\nv 0.000000 25.000042 -253.000000\nv 20.000000 25.000042 -253.000000\nv 25.000000 20.000042 -253.000000\nv 0.000000 20.000040 -247.000000\nv 0.000000 25.000040 -247.000000\nv 25.000000 20.000040 -247.000000\nv 20.000000 25.000040 -247.000000\nv 25.000000 20.000042 -252.000000\nvt 0.975000 0.081081\nvt 0.986364 0.081081\nvt 0.986364 0.513514\nvt 0.959091 0.594595\nvt 0.959091 0.405405\nvt 0.975000 0.405405\nvt 0.920455 0.270270\nvt 0.959091 0.270270\nvt 0.972727 0.270270\nvt 0.959091 0.081081\nvt 0.959091 0.432432\nvt 0.911364 0.594595\nvt 0.922727 0.081081\nvt 0.975000 0.648649\nvt 0.975000 0.594595\nvt 0.911364 0.405405\nvt 0.975000 0.270270\nvt 0.922727 0.270270\nf 222/420 223/421 224/422\nf 227/423 223/424 222/425\nf 229/426 227/427 226/424\nf 230/428 228/427 229/429\nf 230/430 228/423 226/431\nf 227/432 229/429 224/427\nf 225/433 222/420 224/422\nf 226/434 227/423 222/425\nf 228/435 229/426 226/424\nf 224/420 225/436 230/428\nf 230/428 229/429 224/420\nf 222/435 225/424 230/430\nf 230/430 226/431 222/435\nf 223/437 227/432 224/427\ng Mesh1 Side_U_R Side Model\nv 68.750000 75.000015 -81.250000\nv 70.000000 75.000069 -400.000000\nv 70.000000 80.000069 -400.000000\nv 68.750000 81.250000 -81.250000\nv 75.000000 75.000069 -400.000000\nv 75.000000 75.000015 -81.250000\nv 75.000000 80.000069 -400.000000\nv 80.000000 75.000069 -400.000000\nv 80.000000 70.000069 -400.000000\nv 75.000000 70.000069 -400.000000\nv 81.250000 68.750000 -81.250000\nv 81.250000 75.000015 -81.250000\nv 75.000000 81.250000 -81.250000\nv 75.000000 68.750000 -81.250000\nvt 0.000000 0.864865\nvt 0.000000 0.729730\nvt 0.909091 0.729730\nvt 0.909091 0.864865\nvt 0.909091 1.000000\nvt 0.975000 0.837838\nvt 0.975000 0.972973\nvt 0.963636 0.972973\nvt 0.986364 0.837838\nvt 0.975000 0.702703\nvt 0.909091 0.405405\nvt -0.000000 0.405405\nvt 0.000000 0.270270\nvt 0.909091 0.594595\nvt -0.000000 0.594595\nvt 0.909091 0.135135\nvt 0.909091 0.270270\nvt 0.000000 0.135135\nvt 0.000000 0.000000\nvt 0.000000 1.000000\nvt 0.963636 0.837838\nvt 0.986364 0.702703\nvt 0.909091 0.000000\nf 232/438 233/439 234/440\nf 232/438 231/441 236/442\nf 235/443 237/444 233/445\nf 237/444 235/443 238/446\nf 238/446 235/443 240/447\nf 242/448 238/449 239/450\nf 238/449 242/448 243/451\nf 233/439 237/452 243/451\nf 244/453 241/454 239/450\nf 244/453 240/455 235/456\nf 231/441 232/438 234/440\nf 235/457 232/438 236/442\nf 232/458 235/443 233/445\nf 239/459 238/446 240/447\nf 241/454 242/448 239/450\nf 237/452 238/449 243/451\nf 234/440 233/439 243/451\nf 240/455 244/453 239/450\nf 236/460 244/453 235/456\ng Mesh2 Side_D_R Side Model\nv 68.750000 25.000015 -81.250000\nv 70.000000 25.000069 -400.000000\nv 70.000000 20.000069 -400.000000\nv 68.750000 18.750000 -81.250000\nv 75.000000 25.000069 -400.000000\nv 75.000000 25.000015 -81.250000\nv 75.000000 20.000069 -400.000000\nv 80.000000 25.000069 -400.000000\nv 80.000000 30.000069 -400.000000\nv 75.000000 30.000069 -400.000000\nv 81.250000 31.250000 -81.250000\nv 81.250000 25.000015 -81.250000\nv 75.000000 18.750000 -81.250000\nv 75.000000 31.250000 -81.250000\nvt 0.000000 0.864865\nvt 0.000000 0.729730\nvt 0.909091 0.729730\nvt 0.909091 0.864865\nvt 0.909091 1.000000\nvt 0.975000 0.837838\nvt 0.975000 0.972973\nvt 0.963636 0.972973\nvt 0.986364 0.837838\nvt 0.975000 0.702703\nvt 0.909091 0.405405\nvt -0.000000 0.405405\nvt 0.000000 0.270270\nvt 0.909091 0.594595\nvt -0.000000 0.594595\nvt 0.909091 0.135135\nvt 0.909091 0.270270\nvt 0.000000 0.135135\nvt 0.000000 0.000000\nvt 0.000000 1.000000\nvt 0.963636 0.837838\nvt 0.986364 0.702703\nvt 0.909091 0.000000\nf 246/461 247/462 248/463\nf 246/461 245/464 250/465\nf 249/466 251/467 247/468\nf 251/467 249/466 252/469\nf 252/469 249/466 254/470\nf 256/471 252/472 253/473\nf 252/472 256/471 257/474\nf 247/462 251/475 257/474\nf 258/476 255/477 253/473\nf 258/476 254/478 249/479\nf 245/464 246/461 248/463\nf 249/480 246/461 250/465\nf 246/481 249/466 247/468\nf 253/482 252/469 254/470\nf 255/477 256/471 253/473\nf 251/475 252/472 257/474\nf 248/463 247/462 257/474\nf 254/478 258/476 253/473\nf 250/483 258/476 249/479\ng Mesh3 Side_D_L Side Model\nv 31.250000 25.000015 -81.250000\nv 30.000000 25.000069 -400.000000\nv 30.000000 20.000069 -400.000000\nv 31.250000 18.750000 -81.250000\nv 25.000000 25.000069 -400.000000\nv 25.000000 25.000015 -81.250000\nv 25.000000 20.000069 -400.000000\nv 20.000000 25.000069 -400.000000\nv 20.000000 30.000069 -400.000000\nv 25.000000 30.000069 -400.000000\nv 18.750000 31.250000 -81.250000\nv 18.750000 25.000015 -81.250000\nv 25.000000 18.750000 -81.250000\nv 25.000000 31.250000 -81.250000\nvt 0.000000 0.864865\nvt 0.000000 0.729730\nvt 0.909091 0.729730\nvt 0.909091 0.864865\nvt 0.909091 1.000000\nvt 0.975000 0.837838\nvt 0.975000 0.972973\nvt 0.963636 0.972973\nvt 0.986364 0.837838\nvt 0.975000 0.702703\nvt 0.909091 0.405405\nvt -0.000000 0.405405\nvt 0.000000 0.270270\nvt 0.909091 0.594595\nvt -0.000000 0.594595\nvt 0.909091 0.135135\nvt 0.909091 0.270270\nvt 0.000000 0.135135\nvt 0.000000 0.000000\nvt 0.000000 1.000000\nvt 0.963636 0.837838\nvt 0.986364 0.702703\nvt 0.909091 0.000000\nf 260/484 261/485 262/486\nf 260/484 259/487 264/488\nf 263/489 265/490 261/491\nf 265/490 263/489 266/492\nf 266/492 263/489 268/493\nf 270/494 266/495 267/496\nf 266/495 270/494 271/497\nf 261/485 265/498 271/497\nf 272/499 269/500 267/496\nf 272/499 268/501 263/502\nf 259/487 260/484 262/486\nf 263/503 260/484 264/488\nf 260/504 263/489 261/491\nf 267/505 266/492 268/493\nf 269/500 270/494 267/496\nf 265/498 266/495 271/497\nf 262/486 261/485 271/497\nf 268/501 272/499 267/496\nf 264/506 272/499 263/502\n"
  },
  {
    "path": "resources/logisticspipes/models/HSTube-Turn_result.obj",
    "content": "g Mesh3 Lane Model\nv 264.105011 25.018539 -272.647003\nv 264.105011 30.018539 -272.647003\nv 300.000000 30.018539 -275.000000\nv 300.000000 25.018539 -275.000000\nv 228.824997 25.018539 -265.630005\nv 228.824997 30.018539 -265.630005\nv 194.761993 25.018532 -254.067017\nv 194.761993 30.018532 -254.067017\nv 30.000000 25.018494 -0.000012\nv 25.000000 25.018494 -0.000012\nv 27.352699 25.018501 -35.894711\nv 34.370399 25.018509 -71.175217\nv 45.933102 25.018509 -105.238014\nv 61.842999 25.018517 -137.500015\nv 81.827797 25.018524 -167.409012\nv 105.545998 25.018524 -194.454010\nv 132.591003 25.018532 -218.172012\nv 162.500000 25.018532 -238.157013\nv 300.000000 25.018539 -270.000000\nv 264.757996 25.018539 -267.690002\nv 230.119003 25.018539 -260.799988\nv 196.675003 25.018532 -249.447021\nv 165.000000 25.018532 -233.827011\nv 135.634003 25.018532 -214.205017\nv 109.081001 25.018524 -190.919022\nv 85.794601 25.018524 -164.366013\nv 66.173103 25.018517 -135.000015\nv 50.552502 25.018509 -103.325012\nv 39.200001 25.018501 -69.881119\nv 32.309898 25.018501 -35.242111\nv 20.000000 30.018494 -0.000011\nv 25.000000 30.018494 -0.000011\nv 30.000000 20.018494 -0.000013\nv 25.000000 20.018494 -0.000013\nv 20.000000 25.018494 -0.000012\nv 22.395399 30.018501 -36.547310\nv 29.540800 30.018509 -72.469307\nv 41.313702 30.018509 -107.151009\nv 57.512901 30.018517 -140.000015\nv 77.861099 30.018524 -170.453018\nv 102.010002 30.018524 -197.990021\nv 129.546997 30.018532 -222.139023\nv 160.000000 30.018532 -242.487015\nv 192.848999 30.018539 -258.686005\nv 227.531006 30.018539 -270.459015\nv 263.453003 30.018539 -277.605011\nv 300.000000 30.018539 -280.000000\nv 162.500000 30.018532 -238.157013\nv 132.591003 30.018532 -218.172012\nv 105.545998 30.018524 -194.454010\nv 81.827797 30.018524 -167.409012\nv 61.842999 30.018517 -137.500015\nv 45.933102 30.018509 -105.238007\nv 34.370399 30.018509 -71.175209\nv 27.352699 30.018501 -35.894711\nv 22.395399 25.018501 -36.547310\nv 29.540800 25.018509 -72.469315\nv 27.352699 20.018501 -35.894711\nv 34.370399 20.018509 -71.175217\nv 32.309898 20.018501 -35.242111\nv 39.200001 20.018501 -69.881119\nv 50.552502 20.018509 -103.325012\nv 66.173103 20.018517 -135.000015\nv 85.794601 20.018524 -164.366013\nv 109.081001 20.018524 -190.919022\nv 135.634003 20.018532 -214.205017\nv 165.000000 20.018532 -233.827011\nv 196.675003 20.018532 -249.447021\nv 230.119003 20.018539 -260.799988\nv 264.757996 20.018539 -267.690002\nv 300.000000 20.018539 -270.000000\nv 300.000000 20.018539 -275.000000\nv 264.105011 20.018539 -272.647003\nv 228.824997 20.018539 -265.630005\nv 194.761993 20.018532 -254.067017\nv 162.500000 20.018532 -238.157013\nv 132.591003 20.018532 -218.172012\nv 105.545998 20.018524 -194.454010\nv 81.827797 20.018524 -167.409012\nv 61.842999 20.018517 -137.500015\nv 45.933102 20.018509 -105.238014\nv 300.000000 25.018539 -280.000000\nv 263.453003 25.018539 -277.605011\nv 227.531006 25.018539 -270.459015\nv 192.848999 25.018539 -258.686005\nv 160.000000 25.018532 -242.487015\nv 129.546997 25.018532 -222.139023\nv 102.010002 25.018524 -197.990021\nv 77.861099 25.018524 -170.453018\nv 57.512901 25.018517 -140.000015\nv 41.313702 25.018509 -107.151016\nvt 0.000000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.260000\nvt 0.000000 0.680000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.950000\nvt 0.750000 0.950000\nvt 0.700000 0.950000\nvt 0.700000 1.000000\nvt 0.000000 0.730000\nvt 0.400000 0.730000\nvt 0.800000 0.360000\nvt 0.400000 0.360000\nvt 0.400000 0.410000\nvt -0.000000 0.780000\nvt 0.400000 0.780000\nvt 0.000000 0.850000\nvt 0.400000 0.850000\nvt 0.800000 0.410000\nvt 0.400000 0.480000\nvt 0.000000 0.900000\nvt 0.800000 0.530000\nvt 0.400000 0.530000\nvt 0.400000 0.580000\nvt 0.000000 0.950000\nvt 0.400000 0.900000\nvt 0.000000 0.580000\nvt 0.750000 0.900000\nvt 0.000000 0.410000\nvt 0.000000 0.480000\nvt 0.800000 0.310000\nvt 0.000000 0.260000\nvt 0.800000 0.630000\nvt 0.800000 0.580000\nvt 0.650000 0.950000\nvt 0.650000 1.000000\nvt 0.700000 0.900000\nvt -0.000000 0.360000\nvt 0.800000 0.480000\nvt 0.000000 0.530000\nvt 0.800000 0.260000\nf 2/1 3/2 4/3\nf 6/4 2/5 1/6\nf 5/6 7/7 8/4\nf 16/8 17/9 24/10\nf 35/11 10/12 34/13\nf 41/14 42/15 50/4\nf 36/16 31/17 35/18\nf 56/19 57/20 37/15\nf 58/21 59/22 57/20\nf 56/23 35/18 34/24\nf 64/25 78/22 79/21\nf 60/26 33/27 9/28\nf 30/29 29/10 61/30\nf 29/29 28/10 62/30\nf 28/29 27/10 63/30\nf 27/29 26/10 64/30\nf 26/29 25/10 65/30\nf 25/29 24/10 66/30\nf 24/29 23/10 67/30\nf 23/29 22/10 68/30\nf 22/29 21/10 69/30\nf 21/29 20/10 70/30\nf 20/31 19/28 71/27\nf 47/32 82/11 4/12\nf 83/33 82/18 47/17\nf 84/19 83/20 46/15\nf 85/19 84/20 45/15\nf 86/19 85/20 44/15\nf 87/19 86/20 43/15\nf 88/19 87/20 42/15\nf 89/19 88/20 41/15\nf 90/19 89/20 40/15\nf 91/19 90/20 39/15\nf 57/19 91/20 38/15\nf 59/21 81/22 91/20\nf 81/21 80/22 90/20\nf 90/19 80/21 79/22\nf 89/19 79/21 78/22\nf 88/19 78/21 77/22\nf 77/21 76/22 86/20\nf 86/19 76/21 75/22\nf 85/19 75/21 74/22\nf 84/19 74/21 73/22\nf 83/33 73/34 72/24\nf 7/6 18/7 48/4\nf 18/6 17/7 49/4\nf 17/6 16/7 50/4\nf 16/6 15/7 51/4\nf 15/6 14/7 52/4\nf 14/6 13/7 53/4\nf 13/6 12/7 54/4\nf 12/6 11/7 55/4\nf 11/35 10/2 32/3\nf 1/36 2/1 4/3\nf 5/7 6/4 1/6\nf 6/5 5/6 8/4\nf 4/6 19/28 20/31\nf 11/37 9/28 10/6\nf 1/9 20/10 21/29\nf 11/37 30/38 9/28\nf 1/7 4/6 20/31\nf 12/9 30/29 11/8\nf 7/8 21/10 22/29\nf 12/9 29/10 30/29\nf 5/8 1/9 21/29\nf 13/9 29/29 12/8\nf 18/8 22/10 23/29\nf 13/9 28/10 29/29\nf 7/8 5/9 21/10\nf 14/9 28/29 13/8\nf 17/8 23/10 24/29\nf 14/9 27/10 28/29\nf 18/8 7/9 22/10\nf 15/9 27/29 14/8\nf 16/8 24/10 25/29\nf 15/9 26/10 27/29\nf 25/10 26/29 16/9\nf 23/10 17/8 18/9\nf 16/9 26/29 15/8\nf 10/12 35/11 31/32\nf 9/39 33/40 34/13\nf 31/32 32/41 10/12\nf 10/12 9/39 34/13\nf 46/42 3/2 2/1\nf 36/16 32/2 31/17\nf 45/14 2/5 6/4\nf 36/16 55/35 32/2\nf 46/42 47/17 3/2\nf 37/15 55/4 36/14\nf 44/14 6/5 8/4\nf 37/15 54/5 55/4\nf 45/14 46/15 2/5\nf 38/15 54/4 37/14\nf 43/14 8/5 48/4\nf 38/15 53/5 54/4\nf 44/14 45/15 6/5\nf 39/15 53/4 38/14\nf 43/15 48/5 49/4\nf 39/15 52/5 53/4\nf 43/14 44/15 8/5\nf 51/5 52/4 39/14\nf 42/15 49/5 50/4\nf 40/15 51/5 39/14\nf 50/5 40/14 41/15\nf 49/4 42/14 43/15\nf 50/5 51/4 40/14\nf 56/23 36/16 35/18\nf 36/14 56/19 37/15\nf 56/19 58/21 57/20\nf 58/43 56/23 34/24\nf 33/27 58/43 34/24\nf 61/25 81/22 59/21\nf 63/25 79/22 80/21\nf 65/25 66/30 78/21\nf 67/25 68/30 76/21\nf 69/25 73/22 74/21\nf 70/44 71/27 72/24\nf 58/43 33/27 60/26\nf 73/34 70/44 72/24\nf 59/22 60/25 61/30\nf 69/25 70/30 73/22\nf 59/22 58/21 60/25\nf 75/21 69/30 74/22\nf 81/22 61/25 62/30\nf 75/21 68/25 69/30\nf 80/22 62/25 63/30\nf 76/21 68/30 75/22\nf 80/22 81/21 62/25\nf 77/21 67/30 76/22\nf 79/22 63/25 64/30\nf 77/21 66/25 67/30\nf 78/22 64/25 65/30\nf 78/21 66/30 77/22\nf 30/38 60/26 9/28\nf 60/25 30/29 61/30\nf 61/25 29/29 62/30\nf 62/25 28/29 63/30\nf 63/25 27/29 64/30\nf 64/25 26/29 65/30\nf 65/25 25/29 66/30\nf 66/25 24/29 67/30\nf 67/25 23/29 68/30\nf 68/25 22/29 69/30\nf 69/25 21/29 70/30\nf 70/44 20/31 71/27\nf 71/40 19/39 4/12\nf 4/12 3/41 47/32\nf 4/12 82/11 72/13\nf 72/13 71/40 4/12\nf 46/42 83/33 47/17\nf 45/14 84/19 46/15\nf 44/14 85/19 45/15\nf 43/14 86/19 44/15\nf 42/14 87/19 43/15\nf 41/14 88/19 42/15\nf 40/14 89/19 41/15\nf 39/14 90/19 40/15\nf 38/14 91/19 39/15\nf 37/14 57/19 38/15\nf 57/19 59/21 91/20\nf 91/19 81/21 90/20\nf 89/20 90/19 79/22\nf 88/20 89/19 78/22\nf 87/20 88/19 77/22\nf 87/19 77/21 86/20\nf 85/20 86/19 75/22\nf 84/20 85/19 74/22\nf 83/20 84/19 73/22\nf 82/18 83/33 72/24\nf 8/5 7/6 48/4\nf 48/5 18/6 49/4\nf 49/5 17/6 50/4\nf 50/5 16/6 51/4\nf 51/5 15/6 52/4\nf 52/5 14/6 53/4\nf 53/5 13/6 54/4\nf 54/5 12/6 55/4\nf 55/45 11/35 32/3\ng Mesh2 Lane Model\nv 240.472000 25.018532 -222.163010\nv 240.472000 20.018532 -222.163010\nv 269.979004 20.018532 -228.032013\nv 269.979004 25.018532 -228.032013\nv 211.983002 25.018532 -212.492020\nv 211.983002 20.018532 -212.492020\nv 185.000000 25.018524 -199.186020\nv 185.000000 20.018524 -199.186020\nv 159.985001 25.018524 -182.471008\nv 159.985001 20.018524 -182.471008\nv 137.365005 25.018517 -162.635010\nv 137.365005 20.018517 -162.635010\nv 117.528999 25.018517 -140.015015\nv 117.528999 20.018517 -140.015015\nv 100.814003 25.018509 -115.000015\nv 100.814003 20.018509 -115.000015\nv 87.507698 25.018509 -88.017212\nv 87.507698 20.018509 -88.017212\nv 77.837097 25.018501 -59.528412\nv 77.837097 20.018501 -59.528412\nv 71.967697 25.018501 -30.021011\nv 71.967697 20.018501 -30.021013\nv 70.000000 25.018494 -0.000012\nv 70.000000 20.018494 -0.000013\nv 75.000000 25.018494 -0.000012\nv 300.000000 25.018532 -230.000015\nv 300.000000 25.018532 -225.000015\nv 270.631989 25.018532 -223.075012\nv 241.766006 25.018532 -217.333008\nv 213.895996 25.018524 -207.873016\nv 187.500000 25.018524 -194.856018\nv 163.029007 25.018524 -178.505020\nv 140.901001 25.018517 -159.099014\nv 121.495003 25.018517 -136.971008\nv 105.143997 25.018509 -112.500015\nv 92.127098 25.018509 -86.103813\nv 82.666702 25.018501 -58.234310\nv 76.924896 25.018501 -29.368412\nv 75.000000 30.018494 -0.000011\nv 80.000000 30.018494 -0.000011\nv 80.000000 25.018494 -0.000012\nv 75.000000 20.018494 -0.000013\nv 76.924896 30.018501 -29.368412\nv 82.666702 30.018501 -58.234310\nv 92.127098 30.018509 -86.103806\nv 105.143997 30.018509 -112.500008\nv 121.495003 30.018517 -136.971008\nv 140.901001 30.018517 -159.099014\nv 163.029007 30.018524 -178.505020\nv 187.500000 30.018524 -194.856018\nv 213.895996 30.018524 -207.873016\nv 241.766006 30.018532 -217.333008\nv 270.631989 30.018532 -223.075012\nv 300.000000 30.018532 -225.000015\nv 300.000000 20.018532 -230.000015\nv 300.000000 20.018532 -225.000015\nv 300.000000 25.018532 -220.000015\nv 300.000000 30.018532 -220.000015\nv 76.924896 20.018501 -29.368414\nv 82.666702 20.018501 -58.234310\nv 92.127098 20.018509 -86.103813\nv 105.143997 20.018509 -112.500015\nv 121.495003 20.018517 -136.971008\nv 140.901001 20.018517 -159.099014\nv 163.029007 20.018524 -178.505020\nv 187.500000 20.018524 -194.856018\nv 213.895996 20.018524 -207.873016\nv 241.766006 20.018532 -217.333008\nv 270.631989 20.018532 -223.075012\nv 81.882103 25.018501 -28.715811\nv 87.496300 25.018501 -56.940212\nv 96.746498 25.018509 -84.190414\nv 109.473999 25.018509 -110.000015\nv 125.461998 25.018517 -133.928009\nv 144.436996 25.018517 -155.563019\nv 166.072006 25.018524 -174.538010\nv 190.000000 25.018524 -190.526016\nv 215.809998 25.018524 -203.253021\nv 243.059998 25.018532 -212.504013\nv 271.283997 25.018532 -218.118011\nv 271.283997 30.018532 -218.118011\nv 243.059998 30.018532 -212.504013\nv 215.809998 30.018524 -203.253021\nv 190.000000 30.018524 -190.526016\nv 166.072006 30.018524 -174.538010\nv 144.436996 30.018517 -155.563019\nv 125.461998 30.018517 -133.928009\nv 109.473999 30.018509 -110.000008\nv 96.746498 30.018509 -84.190407\nv 87.496300 30.018501 -56.940212\nv 81.882103 30.018501 -28.715811\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.950000\nvt 0.800000 0.580000\nvt 0.400000 0.580000\nvt 0.400000 0.530000\nvt 0.000000 0.950000\nvt 0.000000 1.000000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.800000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.260000\nvt 0.400000 0.680000\nvt 0.000000 0.680000\nvt 0.000000 0.630000\nvt 0.000000 0.260000\nvt 0.650000 1.000000\nvt 0.000000 0.530000\nvt 0.400000 0.850000\nvt 0.800000 0.480000\nvt 0.400000 0.480000\nvt 0.400000 0.410000\nvt -0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.400000 0.780000\nvt -0.000000 0.480000\nvt 0.000000 0.410000\nvt -0.000000 0.310000\nvt 0.400000 0.360000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nvt 0.800000 0.360000\nvt 0.800000 0.530000\nvt 0.400000 0.630000\nvt 0.400000 1.000000\nvt 0.800000 0.630000\nvt 0.000000 0.580000\nvt 0.700000 0.900000\nvt 0.750000 0.900000\nvt 0.650000 0.950000\nvt 0.800000 0.260000\nvt 0.800000 0.410000\nvt 0.000000 0.360000\nf 93/46 94/47 95/48\nf 97/46 93/47 92/48\nf 99/46 97/47 96/48\nf 101/46 99/47 98/48\nf 103/46 101/47 100/48\nf 105/46 103/47 102/48\nf 107/46 105/47 104/48\nf 109/46 107/47 106/48\nf 111/46 109/47 108/48\nf 113/46 111/47 110/48\nf 112/49 114/50 115/51\nf 102/52 100/48 124/53\nf 133/54 116/55 132/56\nf 134/57 130/58 116/59\nf 135/60 134/61 129/62\nf 136/60 135/61 128/62\nf 137/60 136/61 127/62\nf 138/60 137/61 126/62\nf 139/60 138/61 125/62\nf 140/60 139/61 124/62\nf 141/60 140/61 123/62\nf 142/60 141/61 122/62\nf 143/60 142/61 121/62\nf 144/60 143/61 120/62\nf 119/63 118/59 145/58\nf 118/55 146/64 147/54\nf 94/65 146/51 117/50\nf 155/66 103/47 105/46\nf 150/67 133/68 132/69\nf 151/66 150/70 161/71\nf 152/66 151/70 162/71\nf 164/72 153/66 152/70\nf 154/66 153/70 164/71\nf 155/66 154/70 165/71\nf 167/72 156/66 155/70\nf 168/72 157/66 156/70\nf 158/66 157/70 168/71\nf 159/66 158/70 169/71\nf 171/72 160/66 159/70\nf 160/73 171/74 148/69\nf 172/75 149/58 148/76\nf 171/77 170/78 173/61\nf 170/77 169/78 174/61\nf 169/77 168/78 175/61\nf 168/77 167/78 176/61\nf 167/77 166/78 177/61\nf 166/77 165/78 178/61\nf 165/77 164/78 179/61\nf 164/77 163/78 180/61\nf 163/77 162/78 181/61\nf 162/77 161/78 182/61\nf 161/79 132/76 131/58\nf 139/61 140/60 176/77\nf 92/52 93/46 95/48\nf 96/52 97/46 92/48\nf 98/52 99/46 96/48\nf 100/52 101/46 98/48\nf 102/52 103/46 100/48\nf 104/52 105/46 102/48\nf 106/52 107/46 104/48\nf 108/52 109/46 106/48\nf 110/52 111/46 108/48\nf 112/52 113/46 110/48\nf 113/80 112/49 115/51\nf 117/50 118/81 119/62\nf 112/49 116/81 114/50\nf 95/48 119/82 120/53\nf 112/49 129/83 116/81\nf 95/84 117/50 119/62\nf 110/48 129/53 112/52\nf 96/52 120/82 121/53\nf 110/48 128/82 129/53\nf 92/52 95/48 120/53\nf 127/82 128/53 110/52\nf 98/52 121/82 122/53\nf 108/48 127/82 110/52\nf 96/52 92/48 120/82\nf 126/82 127/53 108/52\nf 98/48 122/82 123/53\nf 106/48 126/82 108/52\nf 98/52 96/48 121/82\nf 125/82 126/53 106/52\nf 100/48 123/82 124/53\nf 104/48 125/82 106/52\nf 124/82 104/52 102/48\nf 123/53 100/52 98/48\nf 124/82 125/53 104/52\nf 116/55 133/54 115/64\nf 130/85 131/86 132/56\nf 115/64 114/87 116/55\nf 116/55 130/85 132/56\nf 129/88 134/57 116/59\nf 128/81 135/60 129/62\nf 127/81 136/60 128/62\nf 126/81 137/60 127/62\nf 125/81 138/60 126/62\nf 124/81 139/60 125/62\nf 123/81 140/60 124/62\nf 122/81 141/60 123/62\nf 121/81 142/60 122/62\nf 120/81 143/60 121/62\nf 119/81 144/60 120/62\nf 144/75 119/63 145/58\nf 148/56 149/86 145/85\nf 118/55 147/54 148/56\nf 118/55 117/87 146/64\nf 148/56 145/85 118/55\nf 95/84 94/65 117/50\nf 133/68 113/80 115/51\nf 152/66 109/47 111/46\nf 154/66 105/47 107/46\nf 155/70 101/47 103/46\nf 157/70 158/66 99/46\nf 159/70 94/47 93/46\nf 160/73 147/68 146/51\nf 113/80 133/68 150/67\nf 94/65 160/73 146/51\nf 111/47 150/70 151/66\nf 159/70 160/66 94/47\nf 111/47 113/46 150/70\nf 97/46 159/66 93/47\nf 111/46 151/70 152/66\nf 97/46 158/70 159/66\nf 109/46 152/70 153/66\nf 99/46 158/66 97/47\nf 107/47 109/46 153/66\nf 156/70 157/66 99/47\nf 107/46 153/70 154/66\nf 101/46 156/70 99/47\nf 105/46 154/70 155/66\nf 155/70 156/66 101/47\nf 161/89 150/67 132/69\nf 162/72 151/66 161/71\nf 163/72 152/66 162/71\nf 163/71 164/72 152/70\nf 165/72 154/66 164/71\nf 166/72 155/66 165/71\nf 166/71 167/72 155/70\nf 167/71 168/72 156/70\nf 169/72 158/66 168/71\nf 170/72 159/66 169/71\nf 170/71 171/72 159/70\nf 147/68 160/73 148/69\nf 171/90 172/75 148/76\nf 172/60 171/77 173/61\nf 173/60 170/77 174/61\nf 174/60 169/77 175/61\nf 175/60 168/77 176/61\nf 176/60 167/77 177/61\nf 177/60 166/77 178/61\nf 178/60 165/77 179/61\nf 179/60 164/77 180/61\nf 180/60 163/77 181/61\nf 181/60 162/77 182/61\nf 182/57 161/79 131/58\nf 144/75 149/76 172/90\nf 134/57 131/76 130/58\nf 143/61 172/77 173/78\nf 134/57 182/79 131/76\nf 144/75 145/58 149/76\nf 135/60 182/78 134/61\nf 143/60 173/77 174/78\nf 135/60 181/77 182/78\nf 143/61 144/60 172/77\nf 136/60 181/78 135/61\nf 142/60 174/77 175/78\nf 136/60 180/77 181/78\nf 142/61 143/60 174/78\nf 179/77 180/78 136/61\nf 140/61 175/77 176/78\nf 137/60 179/77 136/61\nf 141/61 142/60 175/78\nf 138/60 179/78 137/61\nf 139/61 176/77 177/78\nf 138/60 178/77 179/78\nf 177/77 178/78 139/60\nf 175/77 140/61 141/60\nf 139/60 178/78 138/61\ng Mesh5 Mount_U_L_1 Model\nv 26.657801 100.000008 -57.975784\nv 31.561701 100.000008 -57.000286\nv 31.561701 80.000008 -57.000290\nv 26.657801 75.000008 -57.975788\nv 25.487301 100.000008 -52.090984\nv 30.391199 100.000008 -51.115585\nv 25.487301 75.000008 -52.090988\nv 30.391199 80.000008 -51.115589\nv 26.462700 75.000008 -56.994987\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.700000 0.000000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nf 183/91 184/92 185/93\nf 187/94 188/95 184/96\nf 190/97 188/98 187/94\nf 191/99 189/100 190/101\nf 191/102 189/103 187/104\nf 184/105 188/93 190/92\nf 186/106 183/91 185/93\nf 183/101 187/94 184/96\nf 189/107 190/97 187/94\nf 185/96 186/104 191/99\nf 191/99 190/101 185/96\nf 183/91 186/106 191/102\nf 191/102 187/104 183/91\nf 185/95 184/105 190/92\ng Mesh9 Mount_D_L_4 Model\nv 242.054993 0.000045 -273.431000\nv 243.074005 0.000044 -268.536011\nv 243.074005 20.000044 -268.536011\nv 242.054993 25.000044 -273.431000\nv 247.929001 0.000045 -274.653992\nv 248.947998 0.000044 -269.759003\nv 247.929001 25.000044 -274.653992\nv 248.947998 20.000044 -269.759003\nv 243.033997 25.000044 -273.635010\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 192/108 193/109 194/110\nf 197/111 193/112 192/113\nf 199/114 197/115 196/116\nf 200/117 198/118 199/113\nf 200/119 198/120 196/121\nf 197/110 199/109 194/111\nf 195/122 192/108 194/110\nf 196/116 197/111 192/113\nf 198/123 199/114 196/116\nf 194/112 195/121 200/117\nf 200/117 199/113 194/112\nf 192/108 195/122 200/119\nf 200/119 196/121 192/108\nf 193/124 197/110 194/111\ng Mesh18 Mount_U_R_3 Model\nv 175.820007 100.000031 -181.279984\nv 173.041000 100.000031 -185.436981\nv 173.041000 80.000031 -185.436981\nv 175.820007 75.000031 -181.279984\nv 180.807999 100.000031 -184.614990\nv 178.029007 100.000031 -188.771988\nv 180.807999 75.000031 -184.614990\nv 178.029007 80.000031 -188.771988\nv 176.651001 75.000031 -181.835983\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 201/125 202/126 203/127\nf 205/128 206/129 202/130\nf 208/131 206/132 205/128\nf 209/133 207/134 208/135\nf 209/136 207/137 205/138\nf 206/127 208/126 203/129\nf 204/139 201/125 203/127\nf 201/135 205/128 202/130\nf 207/140 208/131 205/128\nf 203/130 204/138 209/133\nf 209/133 208/135 203/130\nf 201/125 204/139 209/136\nf 209/136 205/138 201/125\nf 202/141 206/127 203/129\ng Mesh6 Mount_D_L_1 Model\nv 25.487301 0.000008 -52.091000\nv 30.391199 0.000008 -51.115601\nv 30.391199 20.000008 -51.115597\nv 25.487301 25.000008 -52.090996\nv 26.657801 0.000009 -57.975800\nv 31.561701 0.000009 -57.000301\nv 26.657801 25.000010 -57.975796\nv 31.561701 20.000010 -57.000298\nv 25.682400 25.000010 -53.071796\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 210/142 211/143 212/144\nf 215/145 211/146 210/147\nf 217/148 215/149 214/150\nf 218/151 216/152 217/147\nf 218/153 216/154 214/155\nf 215/144 217/143 212/145\nf 213/156 210/142 212/144\nf 214/150 215/145 210/147\nf 216/157 217/148 214/150\nf 212/146 213/155 218/151\nf 218/151 217/147 212/146\nf 210/142 213/156 218/153\nf 218/153 214/155 210/142\nf 211/158 215/144 212/145\ng Mesh8 Mount_D_R_4 Model\nv 260.598999 0.000035 -216.024002\nv 259.579010 0.000036 -220.919006\nv 259.579010 20.000036 -220.919006\nv 260.598999 25.000034 -216.024002\nv 254.725006 0.000035 -214.800995\nv 253.705002 0.000036 -219.695999\nv 254.725006 25.000034 -214.800995\nv 253.705002 20.000036 -219.695999\nv 259.619995 25.000034 -215.820007\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 219/159 220/160 221/161\nf 223/162 224/163 220/164\nf 226/165 224/166 223/162\nf 227/167 225/168 226/169\nf 227/170 225/171 223/172\nf 224/161 226/160 221/163\nf 222/173 219/159 221/161\nf 219/169 223/162 220/164\nf 225/174 226/165 223/162\nf 221/164 222/172 227/167\nf 227/167 226/169 221/164\nf 219/159 222/173 227/170\nf 227/170 223/172 219/159\nf 220/175 224/161 221/163\ng Mesh17 Mount_U_L_3 Model\nv 147.098007 100.000038 -234.229980\nv 149.876999 100.000038 -230.072983\nv 149.876999 80.000038 -230.072983\nv 147.098007 75.000038 -234.229980\nv 142.110001 100.000038 -230.894989\nv 144.889008 100.000038 -226.737991\nv 142.110001 75.000038 -230.894989\nv 144.889008 80.000038 -226.737991\nv 146.266998 75.000038 -233.673981\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 228/176 229/177 230/178\nf 232/179 233/180 229/181\nf 235/182 233/183 232/179\nf 236/184 234/185 235/186\nf 236/187 234/188 232/189\nf 233/178 235/177 230/180\nf 231/190 228/176 230/178\nf 228/186 232/179 229/181\nf 234/191 235/182 232/179\nf 230/181 231/189 236/184\nf 236/184 235/186 230/181\nf 228/176 231/190 236/187\nf 236/187 232/189 228/176\nf 229/192 233/178 230/180\ng Mesh7 Mount_D_R_1 Model\nv 85.274498 0.000008 -46.270302\nv 80.370598 0.000008 -47.245800\nv 80.370598 20.000008 -47.245796\nv 85.274498 25.000008 -46.270298\nv 84.103996 0.000007 -40.385601\nv 79.199997 0.000007 -41.361099\nv 84.103996 25.000006 -40.385597\nv 79.199997 20.000008 -41.361095\nv 85.079399 25.000008 -45.289497\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 237/193 238/194 239/195\nf 242/196 238/197 237/198\nf 244/199 242/200 241/201\nf 245/202 243/203 244/198\nf 245/204 243/205 241/206\nf 242/195 244/194 239/196\nf 240/207 237/193 239/195\nf 241/201 242/196 237/198\nf 243/208 244/199 241/201\nf 239/197 240/206 245/202\nf 245/202 244/198 239/197\nf 237/193 240/207 245/204\nf 245/204 241/206 237/193\nf 238/209 242/195 239/196\ng Mesh10 Mount_U_L_4 Model\nv 247.929001 100.000046 -274.653961\nv 248.947998 100.000046 -269.758972\nv 248.947998 80.000046 -269.759003\nv 247.929001 75.000046 -274.653992\nv 242.054993 100.000046 -273.430969\nv 243.074005 100.000046 -268.535980\nv 242.054993 75.000046 -273.431000\nv 243.074005 80.000046 -268.536011\nv 246.949997 75.000046 -274.450012\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.700000 0.000000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nf 246/210 247/211 248/212\nf 250/213 251/214 247/215\nf 253/216 251/217 250/213\nf 254/218 252/219 253/220\nf 254/221 252/222 250/223\nf 247/224 251/212 253/211\nf 249/225 246/210 248/212\nf 246/220 250/213 247/215\nf 252/226 253/216 250/213\nf 248/215 249/223 254/218\nf 254/218 253/220 248/215\nf 246/210 249/225 254/221\nf 254/221 250/223 246/210\nf 248/214 247/224 253/211\ng Mesh12 Mount_U_R_2 Model\nv 116.164001 100.000023 -119.813988\nv 112.004997 100.000023 -122.589981\nv 112.004997 80.000023 -122.589981\nv 116.164001 75.000023 -119.813988\nv 119.494003 100.000023 -124.804985\nv 115.334999 100.000023 -127.579987\nv 119.494003 75.000023 -124.804985\nv 115.334999 80.000023 -127.579987\nv 116.719002 75.000023 -120.645988\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 255/227 256/228 257/229\nf 259/230 260/231 256/232\nf 262/233 260/234 259/230\nf 263/235 261/236 262/237\nf 263/238 261/239 259/240\nf 260/229 262/228 257/231\nf 258/241 255/227 257/229\nf 255/237 259/230 256/232\nf 261/242 262/233 259/230\nf 257/232 258/240 263/235\nf 263/235 262/237 257/232\nf 255/227 258/241 263/238\nf 263/238 259/240 255/227\nf 256/243 260/229 257/231\ng Mesh11 Mount_U_R_4 Model\nv 254.725006 100.000038 -214.800980\nv 253.705002 100.000038 -219.695984\nv 253.705002 80.000038 -219.695984\nv 254.725006 75.000038 -214.800980\nv 260.598999 100.000038 -216.023987\nv 259.579010 100.000038 -220.918991\nv 260.598999 75.000038 -216.023987\nv 259.579010 80.000038 -220.918991\nv 255.703995 75.000038 -215.004990\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 264/244 265/245 266/246\nf 269/247 265/248 264/249\nf 271/250 269/251 268/252\nf 272/253 270/254 271/249\nf 272/255 270/256 268/257\nf 269/246 271/245 266/247\nf 267/258 264/244 266/246\nf 268/252 269/247 264/249\nf 270/259 271/250 268/252\nf 266/248 267/257 272/253\nf 272/253 271/249 266/248\nf 264/244 267/258 272/255\nf 272/255 268/257 264/244\nf 265/260 269/246 266/247\ng Mesh14 Mount_D_L_2 Model\nv 66.020500 0.000025 -152.731995\nv 70.179604 0.000024 -149.957001\nv 70.179604 20.000025 -149.957001\nv 66.020500 25.000025 -152.731995\nv 69.350800 0.000026 -157.723007\nv 73.509903 0.000025 -154.947998\nv 69.350800 25.000025 -157.723007\nv 73.509903 20.000025 -154.947998\nv 66.575600 25.000025 -153.563995\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 273/261 274/262 275/263\nf 277/264 278/265 274/266\nf 280/267 278/268 277/264\nf 281/269 279/270 280/271\nf 281/272 279/273 277/274\nf 278/263 280/262 275/265\nf 276/275 273/261 275/263\nf 273/271 277/264 274/266\nf 279/276 280/267 277/264\nf 275/266 276/274 281/269\nf 281/269 280/271 275/266\nf 273/261 276/275 281/272\nf 281/272 277/274 273/261\nf 274/277 278/263 275/265\ng Mesh0 Lane Model\nv 240.472000 75.000038 -222.162979\nv 240.472000 80.000038 -222.162979\nv 269.979004 80.000038 -228.031982\nv 269.979004 75.000038 -228.031982\nv 211.983002 75.000038 -212.491989\nv 211.983002 80.000038 -212.491989\nv 185.000000 75.000031 -199.185989\nv 185.000000 80.000031 -199.185989\nv 159.985001 75.000031 -182.470978\nv 159.985001 80.000031 -182.470978\nv 137.365005 75.000023 -162.634979\nv 137.365005 80.000023 -162.634979\nv 117.528999 75.000023 -140.014984\nv 117.528999 80.000023 -140.014984\nv 100.814003 75.000015 -114.999985\nv 100.814003 80.000015 -114.999985\nv 87.507698 75.000015 -88.017181\nv 87.507698 80.000015 -88.017181\nv 77.837097 75.000008 -59.528389\nv 77.837097 80.000008 -59.528389\nv 71.967697 75.000008 -30.020988\nv 71.967697 80.000008 -30.020987\nv 70.000000 75.000000 0.000012\nv 70.000000 80.000000 0.000013\nv 75.000000 75.000000 0.000012\nv 300.000000 75.000038 -229.999985\nv 300.000000 75.000038 -224.999985\nv 270.631989 75.000038 -223.074982\nv 241.766006 75.000038 -217.332977\nv 213.895996 75.000031 -207.872986\nv 187.500000 75.000031 -194.855988\nv 163.029007 75.000031 -178.504990\nv 140.901001 75.000023 -159.098984\nv 121.495003 75.000023 -136.970978\nv 105.143997 75.000015 -112.499985\nv 92.127098 75.000015 -86.103783\nv 82.666702 75.000008 -58.234287\nv 76.924896 75.000008 -29.368389\nv 75.000000 70.000000 0.000011\nv 80.000000 70.000000 0.000011\nv 80.000000 75.000000 0.000012\nv 75.000000 80.000000 0.000013\nv 76.924896 70.000008 -29.368389\nv 82.666702 70.000008 -58.234287\nv 92.127098 70.000015 -86.103790\nv 105.143997 70.000015 -112.499992\nv 121.495003 70.000023 -136.970978\nv 140.901001 70.000023 -159.098984\nv 163.029007 70.000031 -178.504990\nv 187.500000 70.000031 -194.855988\nv 213.895996 70.000031 -207.872986\nv 241.766006 70.000038 -217.332977\nv 270.631989 70.000038 -223.074982\nv 300.000000 70.000038 -224.999985\nv 300.000000 80.000038 -229.999985\nv 300.000000 80.000038 -224.999985\nv 300.000000 75.000038 -219.999985\nv 300.000000 70.000038 -219.999985\nv 76.924896 80.000008 -29.368387\nv 82.666702 80.000008 -58.234287\nv 92.127098 80.000015 -86.103783\nv 105.143997 80.000015 -112.499985\nv 121.495003 80.000023 -136.970978\nv 140.901001 80.000023 -159.098984\nv 163.029007 80.000031 -178.504990\nv 187.500000 80.000031 -194.855988\nv 213.895996 80.000031 -207.872986\nv 241.766006 80.000038 -217.332977\nv 270.631989 80.000038 -223.074982\nv 81.882103 75.000008 -28.715788\nv 87.496300 75.000008 -56.940189\nv 96.746498 75.000015 -84.190384\nv 109.473999 75.000015 -109.999985\nv 125.461998 75.000023 -133.927979\nv 144.436996 75.000023 -155.562988\nv 166.072006 75.000031 -174.537979\nv 190.000000 75.000031 -190.525986\nv 215.809998 75.000031 -203.252991\nv 243.059998 75.000038 -212.503983\nv 271.283997 75.000038 -218.117981\nv 271.283997 70.000038 -218.117981\nv 243.059998 70.000038 -212.503983\nv 215.809998 70.000031 -203.252991\nv 190.000000 70.000031 -190.525986\nv 166.072006 70.000031 -174.537979\nv 144.436996 70.000023 -155.562988\nv 125.461998 70.000023 -133.927979\nv 109.473999 70.000015 -109.999992\nv 96.746498 70.000015 -84.190392\nv 87.496300 70.000008 -56.940189\nv 81.882103 70.000008 -28.715788\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.950000\nvt 0.800000 0.580000\nvt 0.400000 0.580000\nvt 0.400000 0.530000\nvt 0.000000 0.950000\nvt 0.000000 1.000000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.800000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.260000\nvt 0.400000 0.680000\nvt 0.000000 0.680000\nvt 0.000000 0.630000\nvt 0.000000 0.260000\nvt 0.650000 1.000000\nvt 0.000000 0.530000\nvt 0.400000 0.850000\nvt 0.800000 0.480000\nvt 0.400000 0.480000\nvt 0.400000 0.410000\nvt -0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.400000 0.780000\nvt -0.000000 0.480000\nvt 0.000000 0.410000\nvt -0.000000 0.310000\nvt 0.400000 0.360000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nvt 0.800000 0.360000\nvt 0.800000 0.530000\nvt 0.400000 0.630000\nvt 0.400000 1.000000\nvt 0.800000 0.630000\nvt 0.000000 0.580000\nvt 0.700000 0.900000\nvt 0.750000 0.900000\nvt 0.650000 0.950000\nvt 0.800000 0.260000\nvt 0.800000 0.410000\nvt 0.000000 0.360000\nf 283/278 284/279 285/280\nf 287/278 283/279 282/280\nf 289/278 287/279 286/280\nf 291/278 289/279 288/280\nf 293/278 291/279 290/280\nf 295/278 293/279 292/280\nf 297/278 295/279 294/280\nf 299/278 297/279 296/280\nf 301/278 299/279 298/280\nf 303/278 301/279 300/280\nf 302/281 304/282 305/283\nf 292/284 290/280 314/285\nf 323/286 306/287 322/288\nf 324/289 320/290 306/291\nf 325/292 324/293 319/294\nf 326/292 325/293 318/294\nf 327/292 326/293 317/294\nf 328/292 327/293 316/294\nf 329/292 328/293 315/294\nf 330/292 329/293 314/294\nf 331/292 330/293 313/294\nf 332/292 331/293 312/294\nf 333/292 332/293 311/294\nf 334/292 333/293 310/294\nf 309/295 308/291 335/290\nf 308/287 336/296 337/286\nf 284/297 336/283 307/282\nf 345/298 293/279 295/278\nf 340/299 323/300 322/301\nf 341/298 340/302 351/303\nf 342/298 341/302 352/303\nf 354/304 343/298 342/302\nf 344/298 343/302 354/303\nf 345/298 344/302 355/303\nf 357/304 346/298 345/302\nf 358/304 347/298 346/302\nf 348/298 347/302 358/303\nf 349/298 348/302 359/303\nf 361/304 350/298 349/302\nf 350/305 361/306 338/301\nf 362/307 339/290 338/308\nf 361/309 360/310 363/293\nf 360/309 359/310 364/293\nf 359/309 358/310 365/293\nf 358/309 357/310 366/293\nf 357/309 356/310 367/293\nf 356/309 355/310 368/293\nf 355/309 354/310 369/293\nf 354/309 353/310 370/293\nf 353/309 352/310 371/293\nf 352/309 351/310 372/293\nf 351/311 322/308 321/290\nf 329/293 330/292 366/309\nf 282/284 283/278 285/280\nf 286/284 287/278 282/280\nf 288/284 289/278 286/280\nf 290/284 291/278 288/280\nf 292/284 293/278 290/280\nf 294/284 295/278 292/280\nf 296/284 297/278 294/280\nf 298/284 299/278 296/280\nf 300/284 301/278 298/280\nf 302/284 303/278 300/280\nf 303/312 302/281 305/283\nf 307/282 308/313 309/294\nf 302/281 306/313 304/282\nf 285/280 309/314 310/285\nf 302/281 319/315 306/313\nf 285/316 307/282 309/294\nf 300/280 319/285 302/284\nf 286/284 310/314 311/285\nf 300/280 318/314 319/285\nf 282/284 285/280 310/285\nf 317/314 318/285 300/284\nf 288/284 311/314 312/285\nf 298/280 317/314 300/284\nf 286/284 282/280 310/314\nf 316/314 317/285 298/284\nf 288/280 312/314 313/285\nf 296/280 316/314 298/284\nf 288/284 286/280 311/314\nf 315/314 316/285 296/284\nf 290/280 313/314 314/285\nf 294/280 315/314 296/284\nf 314/314 294/284 292/280\nf 313/285 290/284 288/280\nf 314/314 315/285 294/284\nf 306/287 323/286 305/296\nf 320/317 321/318 322/288\nf 305/296 304/319 306/287\nf 306/287 320/317 322/288\nf 319/320 324/289 306/291\nf 318/313 325/292 319/294\nf 317/313 326/292 318/294\nf 316/313 327/292 317/294\nf 315/313 328/292 316/294\nf 314/313 329/292 315/294\nf 313/313 330/292 314/294\nf 312/313 331/292 313/294\nf 311/313 332/292 312/294\nf 310/313 333/292 311/294\nf 309/313 334/292 310/294\nf 334/307 309/295 335/290\nf 338/288 339/318 335/317\nf 308/287 337/286 338/288\nf 308/287 307/319 336/296\nf 338/288 335/317 308/287\nf 285/316 284/297 307/282\nf 323/300 303/312 305/283\nf 342/298 299/279 301/278\nf 344/298 295/279 297/278\nf 345/302 291/279 293/278\nf 347/302 348/298 289/278\nf 349/302 284/279 283/278\nf 350/305 337/300 336/283\nf 303/312 323/300 340/299\nf 284/297 350/305 336/283\nf 301/279 340/302 341/298\nf 349/302 350/298 284/279\nf 301/279 303/278 340/302\nf 287/278 349/298 283/279\nf 301/278 341/302 342/298\nf 287/278 348/302 349/298\nf 299/278 342/302 343/298\nf 289/278 348/298 287/279\nf 297/279 299/278 343/298\nf 346/302 347/298 289/279\nf 297/278 343/302 344/298\nf 291/278 346/302 289/279\nf 295/278 344/302 345/298\nf 345/302 346/298 291/279\nf 351/321 340/299 322/301\nf 352/304 341/298 351/303\nf 353/304 342/298 352/303\nf 353/303 354/304 342/302\nf 355/304 344/298 354/303\nf 356/304 345/298 355/303\nf 356/303 357/304 345/302\nf 357/303 358/304 346/302\nf 359/304 348/298 358/303\nf 360/304 349/298 359/303\nf 360/303 361/304 349/302\nf 337/300 350/305 338/301\nf 361/322 362/307 338/308\nf 362/292 361/309 363/293\nf 363/292 360/309 364/293\nf 364/292 359/309 365/293\nf 365/292 358/309 366/293\nf 366/292 357/309 367/293\nf 367/292 356/309 368/293\nf 368/292 355/309 369/293\nf 369/292 354/309 370/293\nf 370/292 353/309 371/293\nf 371/292 352/309 372/293\nf 372/289 351/311 321/290\nf 334/307 339/308 362/322\nf 324/289 321/308 320/290\nf 333/293 362/309 363/310\nf 324/289 372/311 321/308\nf 334/307 335/290 339/308\nf 325/292 372/310 324/293\nf 333/292 363/309 364/310\nf 325/292 371/309 372/310\nf 333/293 334/292 362/309\nf 326/292 371/310 325/293\nf 332/292 364/309 365/310\nf 326/292 370/309 371/310\nf 332/293 333/292 364/310\nf 369/309 370/310 326/293\nf 330/293 365/309 366/310\nf 327/292 369/309 326/293\nf 331/293 332/292 365/310\nf 328/292 369/310 327/293\nf 329/293 366/309 367/310\nf 328/292 368/309 369/310\nf 367/309 368/310 329/292\nf 365/309 330/293 331/292\nf 329/292 368/310 328/293\ng Mesh19 Mount_D_L_3 Model\nv 142.110001 0.000038 -230.895004\nv 144.889008 0.000037 -226.738007\nv 144.889008 20.000036 -226.738007\nv 142.110001 25.000038 -230.895004\nv 147.098007 0.000038 -234.229996\nv 149.876999 0.000037 -230.072998\nv 147.098007 25.000038 -234.229996\nv 149.876999 20.000038 -230.072998\nv 142.940994 25.000038 -231.451004\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 373/323 374/324 375/325\nf 378/326 374/327 373/328\nf 380/329 378/330 377/331\nf 381/332 379/333 380/328\nf 381/334 379/335 377/336\nf 378/325 380/324 375/326\nf 376/337 373/323 375/325\nf 377/331 378/326 373/328\nf 379/338 380/329 377/331\nf 375/327 376/336 381/332\nf 381/332 380/328 375/327\nf 373/323 376/337 381/334\nf 381/334 377/336 373/323\nf 374/339 378/325 375/326\ng Mesh1 Lane Model\nv 264.105011 75.000046 -272.647003\nv 264.105011 70.000046 -272.647003\nv 300.000000 70.000046 -275.000000\nv 300.000000 75.000046 -275.000000\nv 228.824997 75.000046 -265.630005\nv 228.824997 70.000046 -265.630005\nv 194.761993 75.000038 -254.066986\nv 194.761993 70.000038 -254.066986\nv 30.000000 75.000000 0.000012\nv 25.000000 75.000000 0.000012\nv 27.352699 75.000008 -35.894688\nv 34.370399 75.000015 -71.175186\nv 45.933102 75.000015 -105.237984\nv 61.842999 75.000023 -137.499985\nv 81.827797 75.000031 -167.408981\nv 105.545998 75.000031 -194.453979\nv 132.591003 75.000038 -218.171982\nv 162.500000 75.000038 -238.156982\nv 300.000000 75.000046 -270.000000\nv 264.757996 75.000046 -267.690002\nv 230.119003 75.000046 -260.799988\nv 196.675003 75.000038 -249.446991\nv 165.000000 75.000038 -233.826981\nv 135.634003 75.000038 -214.204987\nv 109.081001 75.000031 -190.918991\nv 85.794601 75.000031 -164.365982\nv 66.173103 75.000023 -134.999985\nv 50.552502 75.000015 -103.324982\nv 39.200001 75.000008 -69.881088\nv 32.309898 75.000008 -35.242088\nv 20.000000 70.000000 0.000011\nv 25.000000 70.000000 0.000011\nv 30.000000 80.000000 0.000013\nv 25.000000 80.000000 0.000013\nv 20.000000 75.000000 0.000012\nv 22.395399 70.000008 -36.547287\nv 29.540800 70.000015 -72.469292\nv 41.313702 70.000015 -107.150993\nv 57.512901 70.000023 -139.999985\nv 77.861099 70.000031 -170.452988\nv 102.010002 70.000031 -197.989990\nv 129.546997 70.000038 -222.138992\nv 160.000000 70.000038 -242.486984\nv 192.848999 70.000046 -258.686005\nv 227.531006 70.000046 -270.459015\nv 263.453003 70.000046 -277.605011\nv 300.000000 70.000046 -280.000000\nv 162.500000 70.000038 -238.156982\nv 132.591003 70.000038 -218.171982\nv 105.545998 70.000031 -194.453979\nv 81.827797 70.000031 -167.408981\nv 61.842999 70.000023 -137.499985\nv 45.933102 70.000015 -105.237991\nv 34.370399 70.000015 -71.175194\nv 27.352699 70.000008 -35.894688\nv 22.395399 75.000008 -36.547287\nv 29.540800 75.000015 -72.469284\nv 27.352699 80.000008 -35.894688\nv 34.370399 80.000015 -71.175186\nv 32.309898 80.000008 -35.242088\nv 39.200001 80.000008 -69.881088\nv 50.552502 80.000015 -103.324982\nv 66.173103 80.000023 -134.999985\nv 85.794601 80.000031 -164.365982\nv 109.081001 80.000031 -190.918991\nv 135.634003 80.000038 -214.204987\nv 165.000000 80.000038 -233.826981\nv 196.675003 80.000038 -249.446991\nv 230.119003 80.000046 -260.799988\nv 264.757996 80.000046 -267.690002\nv 300.000000 80.000046 -270.000000\nv 300.000000 80.000046 -275.000000\nv 264.105011 80.000046 -272.647003\nv 228.824997 80.000046 -265.630005\nv 194.761993 80.000038 -254.066986\nv 162.500000 80.000038 -238.156982\nv 132.591003 80.000038 -218.171982\nv 105.545998 80.000031 -194.453979\nv 81.827797 80.000031 -167.408981\nv 61.842999 80.000023 -137.499985\nv 45.933102 80.000015 -105.237984\nv 300.000000 75.000046 -280.000000\nv 263.453003 75.000046 -277.605011\nv 227.531006 75.000046 -270.459015\nv 192.848999 75.000046 -258.686005\nv 160.000000 75.000038 -242.486984\nv 129.546997 75.000038 -222.138992\nv 102.010002 75.000031 -197.989990\nv 77.861099 75.000031 -170.452988\nv 57.512901 75.000023 -139.999985\nv 41.313702 75.000015 -107.150986\nvt 0.000000 0.310000\nvt 0.400000 0.310000\nvt 0.400000 0.260000\nvt 0.000000 0.680000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.950000\nvt 0.750000 0.950000\nvt 0.700000 0.950000\nvt 0.700000 1.000000\nvt 0.000000 0.730000\nvt 0.400000 0.730000\nvt 0.800000 0.360000\nvt 0.400000 0.360000\nvt 0.400000 0.410000\nvt -0.000000 0.780000\nvt 0.400000 0.780000\nvt 0.000000 0.850000\nvt 0.400000 0.850000\nvt 0.800000 0.410000\nvt 0.400000 0.480000\nvt 0.000000 0.900000\nvt 0.800000 0.530000\nvt 0.400000 0.530000\nvt 0.400000 0.580000\nvt 0.000000 0.950000\nvt 0.400000 0.900000\nvt 0.000000 0.580000\nvt 0.750000 0.900000\nvt 0.000000 0.410000\nvt 0.000000 0.480000\nvt 0.800000 0.310000\nvt 0.000000 0.260000\nvt 0.800000 0.630000\nvt 0.800000 0.580000\nvt 0.650000 0.950000\nvt 0.650000 1.000000\nvt 0.700000 0.900000\nvt -0.000000 0.360000\nvt 0.800000 0.480000\nvt 0.000000 0.530000\nvt 0.800000 0.260000\nf 383/340 384/341 385/342\nf 387/343 383/344 382/345\nf 386/345 388/346 389/343\nf 397/347 398/348 405/349\nf 416/350 391/351 415/352\nf 422/353 423/354 431/343\nf 417/355 412/356 416/357\nf 437/358 438/359 418/354\nf 439/360 440/361 438/359\nf 437/362 416/357 415/363\nf 445/364 459/361 460/360\nf 441/365 414/366 390/367\nf 411/368 410/349 442/369\nf 410/368 409/349 443/369\nf 409/368 408/349 444/369\nf 408/368 407/349 445/369\nf 407/368 406/349 446/369\nf 406/368 405/349 447/369\nf 405/368 404/349 448/369\nf 404/368 403/349 449/369\nf 403/368 402/349 450/369\nf 402/368 401/349 451/369\nf 401/370 400/367 452/366\nf 428/371 463/350 385/351\nf 464/372 463/357 428/356\nf 465/358 464/359 427/354\nf 466/358 465/359 426/354\nf 467/358 466/359 425/354\nf 468/358 467/359 424/354\nf 469/358 468/359 423/354\nf 470/358 469/359 422/354\nf 471/358 470/359 421/354\nf 472/358 471/359 420/354\nf 438/358 472/359 419/354\nf 440/360 462/361 472/359\nf 462/360 461/361 471/359\nf 471/358 461/360 460/361\nf 470/358 460/360 459/361\nf 469/358 459/360 458/361\nf 458/360 457/361 467/359\nf 467/358 457/360 456/361\nf 466/358 456/360 455/361\nf 465/358 455/360 454/361\nf 464/372 454/373 453/363\nf 388/345 399/346 429/343\nf 399/345 398/346 430/343\nf 398/345 397/346 431/343\nf 397/345 396/346 432/343\nf 396/345 395/346 433/343\nf 395/345 394/346 434/343\nf 394/345 393/346 435/343\nf 393/345 392/346 436/343\nf 392/374 391/341 413/342\nf 382/375 383/340 385/342\nf 386/346 387/343 382/345\nf 387/344 386/345 389/343\nf 385/345 400/367 401/370\nf 392/376 390/367 391/345\nf 382/348 401/349 402/368\nf 392/376 411/377 390/367\nf 382/346 385/345 401/370\nf 393/348 411/368 392/347\nf 388/347 402/349 403/368\nf 393/348 410/349 411/368\nf 386/347 382/348 402/368\nf 394/348 410/368 393/347\nf 399/347 403/349 404/368\nf 394/348 409/349 410/368\nf 388/347 386/348 402/349\nf 395/348 409/368 394/347\nf 398/347 404/349 405/368\nf 395/348 408/349 409/368\nf 399/347 388/348 403/349\nf 396/348 408/368 395/347\nf 397/347 405/349 406/368\nf 396/348 407/349 408/368\nf 406/349 407/368 397/348\nf 404/349 398/347 399/348\nf 397/348 407/368 396/347\nf 391/351 416/350 412/371\nf 390/378 414/379 415/352\nf 412/371 413/380 391/351\nf 391/351 390/378 415/352\nf 427/381 384/341 383/340\nf 417/355 413/341 412/356\nf 426/353 383/344 387/343\nf 417/355 436/374 413/341\nf 427/381 428/356 384/341\nf 418/354 436/343 417/353\nf 425/353 387/344 389/343\nf 418/354 435/344 436/343\nf 426/353 427/354 383/344\nf 419/354 435/343 418/353\nf 424/353 389/344 429/343\nf 419/354 434/344 435/343\nf 425/353 426/354 387/344\nf 420/354 434/343 419/353\nf 424/354 429/344 430/343\nf 420/354 433/344 434/343\nf 424/353 425/354 389/344\nf 432/344 433/343 420/353\nf 423/354 430/344 431/343\nf 421/354 432/344 420/353\nf 431/344 421/353 422/354\nf 430/343 423/353 424/354\nf 431/344 432/343 421/353\nf 437/362 417/355 416/357\nf 417/353 437/358 418/354\nf 437/358 439/360 438/359\nf 439/382 437/362 415/363\nf 414/366 439/382 415/363\nf 442/364 462/361 440/360\nf 444/364 460/361 461/360\nf 446/364 447/369 459/360\nf 448/364 449/369 457/360\nf 450/364 454/361 455/360\nf 451/383 452/366 453/363\nf 439/382 414/366 441/365\nf 454/373 451/383 453/363\nf 440/361 441/364 442/369\nf 450/364 451/369 454/361\nf 440/361 439/360 441/364\nf 456/360 450/369 455/361\nf 462/361 442/364 443/369\nf 456/360 449/364 450/369\nf 461/361 443/364 444/369\nf 457/360 449/369 456/361\nf 461/361 462/360 443/364\nf 458/360 448/369 457/361\nf 460/361 444/364 445/369\nf 458/360 447/364 448/369\nf 459/361 445/364 446/369\nf 459/360 447/369 458/361\nf 411/377 441/365 390/367\nf 441/364 411/368 442/369\nf 442/364 410/368 443/369\nf 443/364 409/368 444/369\nf 444/364 408/368 445/369\nf 445/364 407/368 446/369\nf 446/364 406/368 447/369\nf 447/364 405/368 448/369\nf 448/364 404/368 449/369\nf 449/364 403/368 450/369\nf 450/364 402/368 451/369\nf 451/383 401/370 452/366\nf 452/379 400/378 385/351\nf 385/351 384/380 428/371\nf 385/351 463/350 453/352\nf 453/352 452/379 385/351\nf 427/381 464/372 428/356\nf 426/353 465/358 427/354\nf 425/353 466/358 426/354\nf 424/353 467/358 425/354\nf 423/353 468/358 424/354\nf 422/353 469/358 423/354\nf 421/353 470/358 422/354\nf 420/353 471/358 421/354\nf 419/353 472/358 420/354\nf 418/353 438/358 419/354\nf 438/358 440/360 472/359\nf 472/358 462/360 471/359\nf 470/359 471/358 460/361\nf 469/359 470/358 459/361\nf 468/359 469/358 458/361\nf 468/358 458/360 467/359\nf 466/359 467/358 456/361\nf 465/359 466/358 455/361\nf 464/359 465/358 454/361\nf 463/357 464/372 453/363\nf 389/344 388/345 429/343\nf 429/344 399/345 430/343\nf 430/344 398/345 431/343\nf 431/344 397/345 432/343\nf 432/344 396/345 433/343\nf 433/344 395/345 434/343\nf 434/344 394/345 435/343\nf 435/344 393/345 436/343\nf 436/384 392/374 413/342\ng Mesh13 Mount_U_L_2 Model\nv 69.350800 100.000023 -157.722992\nv 73.509903 100.000023 -154.947983\nv 73.509903 80.000023 -154.947983\nv 69.350800 75.000023 -157.722992\nv 66.020500 100.000023 -152.731979\nv 70.179604 100.000023 -149.956985\nv 66.020500 75.000023 -152.731979\nv 70.179604 80.000023 -149.956985\nv 68.795799 75.000023 -156.890991\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 473/385 474/386 475/387\nf 478/388 474/389 473/390\nf 480/391 478/392 477/393\nf 481/394 479/395 480/390\nf 481/396 479/397 477/398\nf 478/387 480/386 475/388\nf 476/399 473/385 475/387\nf 477/393 478/388 473/390\nf 479/400 480/391 477/393\nf 475/389 476/398 481/394\nf 481/394 480/390 475/389\nf 473/385 476/399 481/396\nf 481/396 477/398 473/385\nf 474/401 478/387 475/388\ng Mesh4 Mount_U_R_1 Model\nv 84.103996 100.000008 -40.385586\nv 79.199997 100.000008 -41.361084\nv 79.199997 80.000008 -41.361088\nv 84.103996 75.000008 -40.385590\nv 85.274498 100.000008 -46.270287\nv 80.370598 100.000008 -47.245785\nv 85.274498 75.000008 -46.270290\nv 80.370598 80.000008 -47.245789\nv 84.299004 75.000008 -41.366390\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.930000 0.000000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 482/402 483/403 484/404\nf 486/405 487/406 483/407\nf 489/408 487/409 486/405\nf 490/410 488/411 489/412\nf 490/413 488/414 486/415\nf 487/404 489/403 484/406\nf 485/416 482/402 484/404\nf 482/412 486/405 483/407\nf 488/417 489/408 486/405\nf 484/407 485/415 490/410\nf 490/410 489/412 484/407\nf 482/402 485/416 490/413\nf 490/413 486/415 482/402\nf 483/418 487/404 484/406\ng Mesh15 Mount_D_R_2 Model\nv 119.494003 0.000020 -124.805000\nv 115.334999 0.000021 -127.580002\nv 115.334999 20.000021 -127.580002\nv 119.494003 25.000021 -124.804993\nv 116.164001 0.000020 -119.814003\nv 112.004997 0.000020 -122.589996\nv 116.164001 25.000019 -119.813995\nv 112.004997 20.000019 -122.589996\nv 118.939003 25.000021 -123.972992\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 491/419 492/420 493/421\nf 496/422 492/423 491/424\nf 498/425 496/426 495/427\nf 499/428 497/429 498/424\nf 499/430 497/431 495/432\nf 496/421 498/420 493/422\nf 494/433 491/419 493/421\nf 495/427 496/422 491/424\nf 497/434 498/425 495/427\nf 493/423 494/432 499/428\nf 499/428 498/424 493/423\nf 491/419 494/433 499/430\nf 499/430 495/432 491/419\nf 492/435 496/421 493/422\ng Mesh16 Mount_D_R_3 Model\nv 180.807999 0.000030 -184.615005\nv 178.029007 0.000031 -188.772003\nv 178.029007 20.000031 -188.772003\nv 180.807999 25.000031 -184.615005\nv 175.820007 0.000030 -181.279999\nv 173.041000 0.000030 -185.436996\nv 175.820007 25.000029 -181.279999\nv 173.041000 20.000031 -185.436996\nv 179.975998 25.000031 -184.059006\nvt 0.860000 0.120000\nvt 0.860000 0.070000\nvt 0.700000 0.070000\nvt 0.860000 0.000000\nvt 0.860000 0.100000\nvt 0.930000 0.100000\nvt 0.980000 0.160000\nvt 0.980000 -0.000000\nvt 0.930000 -0.000000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nvt 0.650000 0.130000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.650000 0.120000\nvt 0.930000 0.210000\nvt 0.700000 0.000000\nf 500/436 501/437 502/438\nf 505/439 501/440 500/441\nf 507/442 505/443 504/444\nf 508/445 506/446 507/441\nf 508/447 506/448 504/449\nf 505/438 507/437 502/439\nf 503/450 500/436 502/438\nf 504/444 505/439 500/441\nf 506/451 507/442 504/444\nf 502/440 503/449 508/445\nf 508/445 507/441 502/440\nf 500/436 503/450 508/447\nf 508/447 504/449 500/436\nf 501/452 505/438 502/439\n"
  },
  {
    "path": "resources/logisticspipes/models/PipeModel_Transport_Box.obj",
    "content": "g InnerTransportBox\nv 32.000000 68.000000 -75.000000\nv 32.000000 68.000000 -68.000000\nv 32.000000 31.999996 -68.000000\nv 32.000000 31.999996 -75.000000\nv 68.000000 68.000000 -75.000000\nv 68.000000 68.000000 -68.000000\nv 68.000000 31.999996 -75.000000\nv 68.000000 31.999996 -68.000000\nv 32.000000 24.999996 -68.000000\nv 68.000000 24.999996 -68.000000\nv 32.000000 24.999996 -75.000000\nv 68.000000 24.999996 -75.000000\nv 32.000000 75.000000 -75.000000\nv 68.000000 75.000000 -75.000000\nv 25.000000 68.000000 -75.000000\nv 25.000000 75.000000 -75.000000\nv 25.000000 31.999996 -75.000000\nv 25.000000 24.999996 -75.000000\nv 25.000000 24.999996 -68.000000\nv 32.000000 24.999998 -32.000000\nv 25.000000 24.999998 -32.000000\nv 32.000000 31.999998 -32.000000\nv 25.000000 31.999996 -68.000000\nv 25.000000 31.999998 -32.000000\nv 25.000000 31.999998 -25.000002\nv 25.000000 24.999998 -25.000002\nv 25.000000 68.000000 -25.000004\nv 25.000000 68.000000 -32.000004\nv 25.000000 75.000000 -25.000004\nv 25.000000 75.000000 -32.000004\nv 32.000000 75.000000 -25.000004\nv 32.000000 75.000000 -32.000004\nv 68.000000 75.000000 -25.000004\nv 68.000000 75.000000 -32.000004\nv 75.000000 75.000000 -25.000004\nv 75.000000 75.000000 -32.000004\nv 75.000000 68.000000 -25.000004\nv 75.000000 68.000000 -32.000004\nv 75.000000 31.999998 -25.000002\nv 75.000000 31.999998 -32.000000\nv 75.000000 24.999998 -25.000002\nv 75.000000 24.999998 -32.000000\nv 68.000000 24.999998 -25.000002\nv 68.000000 24.999998 -32.000000\nv 68.000000 31.999998 -25.000002\nv 68.000000 68.000000 -25.000004\nv 32.000000 68.000000 -25.000004\nv 32.000000 31.999998 -25.000002\nv 32.000000 68.000000 -32.000004\nv 68.000000 31.999998 -32.000000\nv 68.000000 68.000000 -32.000004\nv 68.000000 75.000000 -68.000000\nv 32.000000 75.000000 -68.000000\nv 75.000000 75.000000 -68.000000\nv 75.000000 68.000000 -68.000000\nv 75.000000 31.999996 -68.000000\nv 25.000000 75.000000 -68.000000\nv 25.000000 68.000000 -68.000000\nv 75.000000 75.000000 -75.000000\nv 75.000000 68.000000 -75.000000\nv 75.000000 31.999996 -75.000000\nv 75.000000 24.999996 -75.000000\nv 75.000000 24.999996 -68.000000\nv 32.000000 24.999998 -25.000002\nvt 0.750000 0.890625\nvt 0.703125 0.890625\nvt 0.703125 0.656250\nvt 0.750000 0.656250\nvt 0.656250 0.890625\nvt 0.609375 0.890625\nvt 0.609375 0.656250\nvt 0.656250 0.656250\nvt 0.046875 0.890625\nvt 0.093750 0.890625\nvt 0.093750 0.656250\nvt 0.046875 0.656250\nvt 0.187500 0.656250\nvt 0.187500 0.890625\nvt 0.234375 0.890625\nvt 0.234375 0.656250\nvt 0.656250 0.609375\nvt 0.656250 0.375000\nvt 0.703125 0.375000\nvt 0.703125 0.609375\nvt 0.609375 0.609375\nvt 0.609375 0.375000\nvt 0.375000 0.609375\nvt 0.375000 0.375000\nvt 0.328125 0.609375\nvt 0.328125 0.375000\nvt 0.375000 0.656250\nvt 0.328125 0.656250\nvt 0.937500 0.609375\nvt 0.937500 0.656250\nvt 0.984375 0.656250\nvt 0.984375 0.890625\nvt 0.937500 0.890625\nvt 0.000000 0.890625\nvt 0.234375 0.937500\nvt 0.000000 0.937500\nvt 0.046875 0.000000\nvt 0.281250 0.000000\nvt 0.281250 0.046875\nvt 0.046875 0.046875\nvt 0.328125 0.046875\nvt 0.328125 0.000000\nvt 0.328125 0.281250\nvt 0.281250 0.281250\nvt 0.328125 0.328125\nvt 0.281250 0.328125\nvt 0.000000 0.609375\nvt 0.046875 0.609375\nvt 0.000000 0.656250\nvt 0.000000 0.375000\nvt 0.046875 0.375000\nvt 0.000000 0.328125\nvt 0.046875 0.328125\nvt 0.656250 0.281250\nvt 0.703125 0.281250\nvt 0.703125 0.328125\nvt 0.656250 0.328125\nvt 0.656250 0.046875\nvt 0.703125 0.046875\nvt 0.656250 0.000000\nvt 0.703125 0.000000\nvt 0.984375 0.328125\nvt 0.984375 0.375000\nvt 0.937500 0.375000\nvt 0.937500 0.328125\nvt 0.375000 0.328125\nvt 0.375000 0.281250\nvt 0.609375 0.328125\nvt 0.609375 0.281250\nvt 0.609375 0.046875\nvt 0.609375 0.000000\nvt 0.375000 0.046875\nvt 0.375000 0.000000\nvt 0.796875 0.656250\nvt 0.796875 0.890625\nvt 0.703125 0.937500\nvt 0.468750 0.937500\nvt 0.468750 0.890625\nvt 0.890625 0.656250\nvt 0.843750 0.656250\nvt 0.843750 0.890625\nvt 0.890625 0.890625\nvt 0.140625 0.890625\nvt 0.140625 0.656250\nvt 0.281250 0.890625\nvt 0.281250 0.656250\nvt 0.328125 0.890625\nvt 0.281250 0.375000\nvt 0.281250 0.609375\nvt 0.937500 0.281250\nvt 0.937500 0.046875\nvt 0.562500 0.656250\nvt 0.562500 0.890625\nvt 0.515625 0.890625\nvt 0.515625 0.656250\nvt 0.000000 0.281250\nvt 0.046875 0.281250\nvt 0.000000 0.046875\nvt 0.000000 0.000000\nvt 0.984375 0.281250\nvt 0.984375 0.046875\nvt 0.984375 0.000000\nvt 0.937500 0.000000\nvt 0.375000 0.890625\nvt 0.468750 0.656250\nvt 0.421875 0.656250\nvt 0.421875 0.890625\nvt 0.984375 0.609375\nf 1/1 2/2 3/3 4/4\nf 2/5 1/6 5/7 6/8\nf 7/9 8/10 6/11 5/12\nf 4/2 3/5 8/8 7/3\nf 9/13 10/14 8/15 3/16\nf 11/17 12/18 10/19 9/20\nf 4/21 7/22 12/18 11/17\nf 1/23 5/24 7/22 4/21\nf 5/24 1/23 13/25 14/26\nf 13/25 1/23 15/27 16/28\nf 1/23 4/21 17/7 15/27\nf 17/7 4/21 11/17 18/8\nf 18/8 11/17 9/20 19/3\nf 19/3 9/20 20/29 21/30\nf 3/31 22/32 20/33 9/30\nf 23/34 24/15 22/35 3/36\nf 19/37 21/38 24/39 23/40\nf 25/41 24/39 21/38 26/42\nf 27/43 28/44 24/39 25/41\nf 29/45 30/46 28/44 27/43\nf 31/47 32/48 30/12 29/49\nf 33/50 34/51 32/48 31/47\nf 35/52 36/53 34/51 33/50\nf 37/54 38/55 36/56 35/57\nf 39/58 40/59 38/55 37/54\nf 41/60 42/61 40/59 39/58\nf 41/62 43/63 44/64 42/65\nf 39/66 45/67 43/43 41/45\nf 37/68 46/69 45/67 39/66\nf 33/54 46/69 37/68 35/57\nf 33/54 31/58 47/70 46/69\nf 29/60 27/71 47/70 31/58\nf 48/72 47/70 27/71 25/73\nf 47/70 48/72 45/67 46/69\nf 48/4 22/74 49/75 47/1\nf 45/2 50/76 22/77 48/78\nf 46/79 51/80 50/81 45/82\nf 47/14 49/83 51/84 46/13\nf 32/85 34/86 51/28 49/87\nf 34/51 52/88 53/89 32/48\nf 36/53 54/46 52/88 34/51\nf 54/65 36/56 38/55 55/90\nf 55/90 38/55 40/59 56/91\nf 51/92 6/93 55/94 38/95\nf 6/6 51/7 34/92 52/93\nf 52/85 53/86 2/16 6/15\nf 13/25 53/89 52/88 14/26\nf 16/28 57/86 53/89 13/25\nf 15/96 58/97 57/53 16/52\nf 17/98 23/40 58/97 15/96\nf 18/99 19/37 23/40 17/98\nf 58/35 23/77 3/78 2/15\nf 28/44 58/97 23/40 24/39\nf 58/97 28/44 30/46 57/53\nf 2/10 49/11 28/84 58/83\nf 49/34 2/49 53/12 32/9\nf 32/48 53/89 57/86 30/12\nf 24/75 28/74 49/80 22/81\nf 14/26 52/88 54/46 59/45\nf 54/65 55/90 60/100 59/62\nf 61/101 60/100 55/90 56/91\nf 60/66 61/68 7/22 5/24\nf 12/18 7/22 61/68 62/57\nf 62/102 61/101 56/91 63/103\nf 56/91 40/59 42/61 63/103\nf 40/87 56/28 8/27 50/104\nf 56/78 55/105 6/106 8/107\nf 50/94 8/95 10/105 44/78\nf 42/65 44/64 10/19 63/56\nf 20/29 9/20 10/19 44/64\nf 20/29 44/64 43/63 64/108\nf 44/30 20/33 22/82 50/79\nf 45/67 48/72 64/41 43/43\nf 26/42 64/41 48/72 25/73\nf 21/30 20/29 64/108 26/31\nf 63/56 10/19 12/18 62/57\nf 38/104 40/27 50/106 51/107\nf 60/66 5/24 14/26 59/45\n"
  },
  {
    "path": "resources/logisticspipes/models/PipeModel_moved.obj",
    "content": "g Mesh332 Side_Texture_Plate_Side3 Texture_Side_N\nv 31.250000 75.000015 -81.250000\nv 31.250000 81.250000 -81.250000\nv 68.750000 81.250000 -81.250000\nv 68.750000 75.000015 -81.250000\nvt 0.000000 1.000000\nf 1/1 2/1 3/1 4/1\ng Mesh123 Texture_Plate_E1\nv 81.250000 68.750000 -31.250000\nv 81.250000 68.750000 -68.750000\nv 81.250000 31.250000 -68.750000\nv 81.250000 31.250000 -31.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 5/2 6/3 7/4 8/5\ng Mesh122 Texture_Connector_Plate25 Texture_Connector_Plate_Mirror13 Texture_Connector_N_U\nv 68.750000 81.250000 -74.999985\nv 31.250000 81.250000 -74.999985\nv 31.250000 68.750000 -74.999992\nv 68.750000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 9/6 10/6 11/6 12/6\ng Mesh413 Mount_W_S\nv 0.000000 43.750000 -18.750000\nv 0.000000 43.750000 -25.000000\nv 18.750000 43.750000 -25.000000\nv 25.000000 43.750000 -18.750000\nv 0.000000 56.250000 -18.750000\nv 0.000000 56.250000 -24.999998\nv 25.000000 56.250000 -18.750000\nv 18.750000 56.250000 -24.999998\nv 25.000000 48.000004 -18.750000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.190000\nvt 0.650000 0.180000\nvt 0.650000 0.190000\nvt 0.930000 0.190000\nvt 0.930000 0.110000\nf 13/7 14/8 15/9 16/10\nf 14/11 13/12 17/13 18/7\nf 19/14 20/15 18/16 17/17\nf 14/13 18/16 20/15 15/18\nf 17/17 13/19 19/14\nf 19/14 13/19 21/20\nf 21/20 13/19 16/21\nf 19/22 20/19 15/12\nf 21/23 19/22 15/12\nf 16/11 21/23 15/12\ng Mesh215 Side_Texture_Plate87 Side_Texture_Plate_Mirror44 Texture_Side_D1\nv 31.250000 18.750000 -24.999996\nv 31.250000 0.000002 -25.000000\nv 68.750000 0.000002 -25.000000\nv 68.750000 18.750000 -24.999996\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 22/24 23/25 24/26 25/27\ng Mesh431 Side_Texture_Plate_Side44 Texture_Side_S2\nv 75.000000 31.250000 0.000003\nv 81.250000 31.250000 0.000003\nv 81.250000 68.750000 0.000005\nv 75.000000 68.750000 0.000005\nvt 0.000000 1.000000\nf 26/28 27/28 28/28 29/28\ng Mesh266 Side_Texture_Plate73 Side_Texture_Plate_Mirror37 Texture_Side_U2\nv 31.250000 81.250000 -81.250000\nv 31.250000 100.000015 -81.250000\nv 68.750000 100.000015 -81.250000\nv 68.750000 81.250000 -81.250000\nvt 0.000000 1.000000\nf 30/29 31/29 32/29 33/29\ng Mesh268 Side_Texture_Plate48 Side_Texture_Plate_Mirror24 Texture_Side_S3\nv 31.250000 25.000004 -18.750000\nv 31.250000 25.000000 0.000002\nv 68.750000 25.000000 0.000002\nv 68.750000 25.000004 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 34/30 35/31 36/32 37/33\ng Mesh388 Texture_Connector_Plate18 Texture_Connector_Plate_Mirror9 Texture_Connector_E_D\nv 75.000000 31.250000 -68.750000\nv 75.000000 31.250000 -31.250000\nv 75.000000 18.750000 -31.250000\nv 75.000000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 38/34 39/34 40/34 41/34\ng Mesh6 Side_Texture_Plate19 Side_Texture_Plate_Mirror10 Texture_Side_E\nv 81.250000 31.250000 -24.999998\nv 100.000000 31.250000 -24.999998\nv 100.000000 68.750000 -24.999996\nv 81.250000 68.750000 -24.999996\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 42/35 43/36 44/37 45/38\ng Mesh375 Side_Texture_Plate82 Side_Texture_Plate_Mirror41 Texture_Side_D\nv 18.750000 18.750000 -31.250000\nv 18.750000 0.000003 -31.250000\nv 18.750000 0.000005 -68.750000\nv 18.750000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 46/39 47/39 48/39 49/39\ng Mesh457 Side_Texture_Plate_Side28 Texture_Side_E2\nv 100.000000 31.250000 -74.999992\nv 100.000000 31.250000 -81.250000\nv 100.000000 68.750000 -81.250000\nv 100.000000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 50/40 51/40 52/40 53/40\ng Mesh37 Side_Texture_Plate78 Side_Texture_Plate_Mirror39 Texture_Side_U3\nv 81.250000 81.250000 -31.250000\nv 81.250000 100.000008 -31.250000\nv 81.250000 100.000008 -68.750000\nv 81.250000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 54/41 55/41 56/41 57/41\ng Mesh101 Side_Texture_Plate67 Side_Texture_Plate_Mirror34 Texture_Side_U\nv 25.000000 81.250000 -31.250000\nv 25.000000 100.000008 -31.250000\nv 25.000000 100.000008 -68.750000\nv 25.000000 81.250000 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 58/42 59/43 60/44 61/45\ng Mesh279 Texture_Connector_Plate3 Texture_Connector_Plate_Mirror2 Texture_Connector_U_N\nv 68.750000 75.000015 -81.250000\nv 31.250000 75.000015 -81.250000\nv 31.250000 75.000008 -68.750000\nv 68.750000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 62/46 63/46 64/46 65/46\ng Mesh583 Side_Texture_Plate85 Side_Texture_Plate_Mirror43 Texture_Side_D1\nv 31.250000 18.750000 -18.750000\nv 31.250000 0.000001 -18.750000\nv 68.750000 0.000001 -18.750000\nv 68.750000 18.750000 -18.750000\nvt 0.000000 1.000000\nf 66/47 67/47 68/47 69/47\ng Mesh588 Support_W_U\nv 18.750000 68.750000 -43.750000\nv 18.750000 31.250000 -43.750000\nv 23.000000 31.250000 -43.750000\nv 23.000000 68.750000 -43.750000\nv 18.750000 68.750000 -56.250000\nv 18.750000 31.250000 -56.250000\nv 23.000000 68.750000 -56.250000\nv 23.000000 31.250000 -56.250000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 70/48 71/49 72/50 73/51\nf 71/52 70/53 74/54 75/55\nf 75/56 74/57 76/51 77/50\nf 77/55 76/54 73/58 72/59\ng Mesh120 Corner_M_D_NE\nv 75.000000 31.250000 -74.999992\nv 75.000000 24.999996 -74.999992\nv 75.000000 24.999996 -68.750000\nv 75.000000 31.250000 -68.750000\nv 68.750000 31.250000 -74.999992\nv 68.750000 24.999996 -74.999992\nv 68.750000 24.999996 -68.750000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 78/60 79/61 80/62 81/63\nf 78/62 82/64 83/65 79/63\nf 83/64 84/66 80/67 79/65\ng Mesh554 Corner_I3_U_SW\nv 25.000000 81.250000 -18.750000\nv 18.750000 81.250000 -25.000002\nv 18.750000 75.000000 -18.750000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 85/68 86/69 87/70\ng Mesh52 Side_BC_S\nv 25.000000 68.750000 -0.000001\nv 25.000000 50.000000 0.000000\nv 25.000000 50.000000 -3.000000\nv 25.000000 68.750000 -3.000000\nv 50.000000 75.000000 0.000000\nv 31.250000 75.000000 0.000000\nv 31.250000 75.000000 -3.000000\nv 50.000000 75.000000 -3.000000\nv 25.000000 75.000000 0.000000\nv 25.000000 75.000000 -9.999999\nv 25.000000 68.750000 -10.000000\nv 31.250000 75.000000 -9.999999\nvt 0.250000 0.480000\nvt 0.580000 0.480000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.430000\nvt 0.250000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.430000\nvt 0.000000 0.000000\nvt 0.130000 0.530000\nvt 0.220000 0.480000\nf 88/71 89/72 90/73 91/74\nf 92/75 93/76 94/71 95/72\nf 96/71 88/76 97/77\nf 97/77 88/76 98/78\nf 98/79 88/79 91/79\nf 96/74 97/80 99/77\nf 96/74 99/77 94/81\nf 94/81 93/71 96/74\ng Mesh83 Side_1 Side_W\nv 0.000000 18.750000 -75.000000\nv 0.000000 24.999998 -81.250000\nv 18.750000 24.999998 -81.250000\nv 18.750000 18.750000 -75.000000\nv 0.000000 24.999996 -74.999992\nv 0.000000 18.750000 -68.750000\nv 0.000000 24.999996 -68.750000\nv 18.750000 24.999996 -68.750000\nv 18.750000 24.999996 -74.999992\nv 18.750000 18.750000 -68.750000\nv 18.750000 31.250000 -74.999992\nv 0.000000 31.250000 -74.999992\nv 18.750000 31.250000 -81.250000\nv 0.000000 31.250000 -81.250000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 100/82 101/83 102/84 103/85\nf 100/86 104/87 101/88\nf 100/86 105/89 106/90 104/87\nf 104/89 106/90 107/91 108/92\nf 107/91 106/90 105/93 109/94\nf 100/82 103/85 109/95 105/96\nf 108/97 110/98 111/99 104/100\nf 111/99 110/98 112/95 113/96\nf 112/94 102/84 101/83 113/93\nf 113/101 101/88 104/87 111/102\ng Mesh430 Side_Texture_Plate_Side85 Texture_Side_D1\nv 31.250000 0.000002 -25.000000\nv 31.250000 0.000001 -18.750000\nv 68.750000 0.000001 -18.750000\nv 68.750000 0.000002 -25.000000\nvt 0.000000 1.000000\nf 114/103 115/103 116/103 117/103\ng Mesh414 Texture_Connector_Plate42 Texture_Connector_Plate_Mirror21 Texture_Connector_W_S\nv 25.000000 68.750000 -31.250000\nv 25.000000 31.250000 -31.250000\nv 25.000000 31.250000 -18.750000\nv 25.000000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 118/104 119/104 120/104 121/104\ng Mesh396 Support_E_U\nv 81.250000 68.750000 -56.250000\nv 81.250000 31.250000 -56.250000\nv 77.000000 31.250000 -56.250000\nv 77.000000 68.750000 -56.250000\nv 81.250000 68.750000 -43.750000\nv 81.250000 31.250000 -43.750000\nv 77.000000 68.750000 -43.750000\nv 77.000000 31.250000 -43.750000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 122/105 123/106 124/107 125/108\nf 123/109 122/110 126/111 127/112\nf 127/113 126/114 128/108 129/107\nf 129/112 128/111 125/115 124/116\ng Mesh466 Mount_W_N\nv 0.000000 56.250000 -81.250000\nv 0.000000 56.250000 -74.999992\nv 18.750000 56.250000 -74.999992\nv 25.000000 56.250000 -81.250000\nv 0.000000 43.750000 -81.250000\nv 0.000000 43.750000 -74.999992\nv 25.000000 43.750000 -81.250000\nv 18.750000 43.750000 -74.999992\nv 25.000000 51.999996 -81.250000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.130000\nvt 0.860000 0.190000\nvt 0.930000 0.120000\nvt 0.930000 0.190000\nf 130/117 131/118 132/119 133/120\nf 131/121 130/117 134/122 135/123\nf 136/124 137/125 135/126 134/127\nf 131/121 135/126 137/125 132/128\nf 134/129 130/124 133/127\nf 134/129 133/127 138/130\nf 134/129 138/130 136/131\nf 137/131 132/123 133/122\nf 137/131 133/122 138/132\nf 137/131 138/132 136/133\ng Mesh367 Side_Texture_Plate38 Side_Texture_Plate_Mirror19 Texture_Side_S1\nv 68.750000 81.250000 -18.750000\nv 68.750000 81.250000 0.000007\nv 31.250000 81.250000 0.000007\nv 31.250000 81.250000 -18.750000\nvt 0.000000 1.000000\nf 139/134 140/134 141/134 142/134\ng Mesh517 Mount_N_E\nv 81.250000 56.250000 -99.999992\nv 75.000000 56.250000 -99.999992\nv 75.000000 56.250000 -81.250000\nv 81.250000 56.250000 -74.999992\nv 81.250000 43.750000 -99.999992\nv 75.000000 43.750000 -99.999992\nv 81.250000 43.750000 -74.999992\nv 75.000000 43.750000 -81.250000\nv 81.250000 51.999996 -74.999992\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.110000\nvt 0.860000 0.110000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.650000 0.180000\nvt 0.930000 0.130000\nvt 0.930000 0.190000\nf 143/135 144/136 145/137 146/138\nf 144/139 143/135 147/140 148/141\nf 149/142 150/143 148/144 147/145\nf 144/143 148/146 150/139 145/144\nf 143/147 146/148 151/149\nf 147/145 143/147 151/149\nf 147/145 151/149 149/142\nf 150/147 145/141 146/140\nf 150/147 146/140 151/150\nf 150/147 151/150 149/151\ng Mesh591 Texture_Connector_Plate40 Texture_Connector_Plate_Mirror20 Texture_Connector_W_N\nv 18.750000 68.750000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 18.750000 31.250000 -68.750000\nv 18.750000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 152/152 153/152 154/152 155/152\ng Mesh406 Corner_I_D_SE1\nv 75.000000 31.250000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 81.250000 31.250000 -31.250000\nv 75.000000 31.250000 -31.250000\nv 75.000000 18.750000 -18.750000\nv 81.250000 18.750000 -24.999996\nv 81.250000 25.000004 -18.750000\nv 81.250000 18.750000 -31.250000\nv 75.000000 18.750000 -31.250000\nv 75.000000 18.750000 -24.999996\nv 68.750000 18.750000 -24.999996\nv 68.750000 24.999996 -25.000004\nv 75.000000 24.999996 -25.000004\nv 68.750000 25.000004 -18.750000\nv 68.750000 18.750000 -18.750000\nv 75.000000 25.000004 -18.750000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nf 156/153 157/154 158/155 159/156\nf 160/157 161/158 162/159\nf 163/156 164/155 159/160 158/161\nf 165/162 166/163 167/164 168/159\nf 169/165 167/166 166/167 170/168\nf 169/163 171/162 168/165 167/168\nf 171/164 156/163 159/169\nf 171/164 159/169 168/157\nf 168/157 159/169 164/170\nf 165/171 168/157 164/170\nf 158/172 157/169 162/173\nf 163/167 158/172 162/173\nf 163/167 162/173 161/174\ng Mesh346 Side_Texture_Plate81 Side_Texture_Plate_Mirror41 Texture_Side_D\nv 18.750000 18.750000 -68.750000\nv 18.750000 0.000005 -68.750000\nv 18.750000 0.000003 -31.250000\nv 18.750000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 172/175 173/175 174/175 175/175\ng Mesh4 Side_Texture_Plate59 Side_Texture_Plate_Mirror30 Texture_Side_W2\nv 18.750000 31.250000 -74.999992\nv 0.000000 31.250000 -74.999992\nv 0.000000 68.750000 -74.999992\nv 18.750000 68.750000 -74.999992\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 176/176 177/177 178/178 179/179\ng Mesh539 Texture_Connector_Plate96 Texture_Connector_Plate_Mirror48 Texture_Connector_D_W\nv 18.750000 18.750000 -31.250000\nv 18.750000 18.750000 -68.750000\nv 31.250000 18.750000 -68.750000\nv 31.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 180/180 181/180 182/180 183/180\ng Mesh429 Side_Texture_Plate71 Side_Texture_Plate_Mirror36 Texture_Side_U1\nv 68.750000 81.250000 -24.999994\nv 68.750000 100.000008 -24.999990\nv 31.250000 100.000008 -24.999990\nv 31.250000 81.250000 -24.999994\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 184/181 185/182 186/183 187/184\ng Mesh488 Inner_BC_Side6 Side_BC_E\nv 97.000000 75.000008 -68.750000\nv 97.000000 75.000008 -50.000004\nv 100.000000 75.000008 -50.000004\nv 100.000000 75.000008 -68.750000\nv 100.000000 49.999996 -74.999992\nv 97.000000 49.999996 -74.999992\nv 97.000000 68.750000 -74.999992\nv 100.000000 68.750000 -74.999992\nv 81.250000 68.750000 -74.999992\nv 90.000000 68.750000 -74.999992\nv 90.000000 75.000015 -74.999985\nv 81.250000 75.000015 -74.999985\nv 81.250000 68.750000 -81.250000\nv 81.250000 75.000015 -81.250000\nv 81.250000 81.250000 -74.999985\nv 90.000000 75.000008 -68.750000\nv 81.250000 81.250000 -68.750000\nv 81.250000 75.000008 -68.750000\nv 100.000000 75.000015 -74.999985\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.130000 0.640000\nf 188/185 189/186 190/187 191/188\nf 192/186 193/189 194/190 195/185\nf 196/191 197/192 198/193 199/194\nf 200/187 197/195 196/196\nf 198/197 197/198 200/199 201/200\nf 198/201 201/202 202/187\nf 203/203 198/197 202/200 204/204\nf 199/203 198/204 203/192 205/191\nf 203/187 204/195 205/189\nf 197/203 198/197 206/185\nf 197/203 206/185 195/188\nf 194/205 197/205 195/205\nf 206/190 198/198 203/197\nf 191/185 206/190 203/197\nf 203/205 188/205 191/205\ng Mesh580 Mount_D_N\nv 43.750000 0.000001 -81.250000\nv 43.750000 0.000000 -75.000000\nv 43.750000 18.750000 -75.000000\nv 43.750000 24.999998 -81.250000\nv 56.250000 0.000001 -81.250000\nv 56.250000 0.000000 -75.000000\nv 56.250000 24.999998 -81.250000\nv 56.250000 18.750000 -75.000000\nv 48.000000 24.999998 -81.250000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.140000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.870000 0.190000\nvt 0.930000 0.190000\nf 207/206 208/207 209/208 210/209\nf 208/210 207/206 211/211 212/212\nf 213/213 214/214 212/215 211/216\nf 208/210 212/215 214/214 209/217\nf 207/213 210/216 215/218\nf 207/213 215/218 213/219\nf 207/213 213/219 211/220\nf 209/212 210/219 215/221\nf 209/212 215/221 213/222\nf 209/212 213/222 214/211\ng Mesh328 Side_Texture_Plate75 Side_Texture_Plate_Mirror38 Texture_Side_U2\nv 31.250000 81.250000 -74.999985\nv 31.250000 100.000015 -75.000000\nv 68.750000 100.000015 -75.000000\nv 68.750000 81.250000 -74.999985\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 216/223 217/224 218/225 219/226\ng Mesh382 Side_Texture_Plate_Side91 Texture_Side_D2\nv 31.250000 18.750000 -75.000000\nv 31.250000 18.750000 -81.250000\nv 68.750000 18.750000 -81.250000\nv 68.750000 18.750000 -75.000000\nvt 0.000000 1.000000\nf 220/227 221/227 222/227 223/227\ng Mesh483 Texture_Connector_Plate63 Texture_Connector_Plate_Mirror32 Texture_Connector_S_E\nv 68.750000 31.250000 -18.750000\nv 68.750000 68.750000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 81.250000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 224/228 225/228 226/228 227/228\ng Mesh333 Side_Texture_Plate_Side19 Texture_Side_E\nv 81.250000 68.750000 -24.999996\nv 81.250000 68.750000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 81.250000 31.250000 -24.999998\nvt 0.000000 1.000000\nf 228/229 229/229 230/229 231/229\ng Mesh233 Texture_Connector_Plate71 Texture_Connector_Plate_Mirror36 Texture_Connector_U_W\nv 18.750000 81.250000 -31.250000\nv 18.750000 81.250000 -68.750000\nv 31.250000 81.250000 -68.750000\nv 31.250000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 232/230 233/230 234/230 235/230\ng Mesh575 Spacer21 Group7\nv 68.750000 68.750000 -25.000004\nv 68.750000 68.750000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 68.750000 81.250000 -25.000002\nv 75.000000 81.250000 -18.750000\nv 75.000000 68.750000 -18.750000\nv 81.250000 81.250000 -25.000002\nv 81.250000 68.750000 -25.000004\nv 81.250000 68.750000 -31.250000\nv 81.250000 81.250000 -31.250000\nv 75.000000 81.250000 -31.250000\nv 75.000000 68.750000 -31.250000\nv 75.000000 81.250000 -25.000002\nv 75.000000 68.750000 -25.000004\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 236/231 237/232 238/233 239/234\nf 240/235 238/233 237/232 241/236\nf 242/237 240/235 241/236 243/238\nf 243/238 244/239 245/240 242/237\nf 246/241 245/240 244/239 247/242\nf 248/243 246/241 247/242 249/244\nf 249/245 236/231 239/234 248/246\ng Mesh397 Side_BC_N\nv 75.000000 68.750000 -99.999992\nv 75.000000 50.000000 -99.999992\nv 75.000000 50.000000 -96.999992\nv 75.000000 68.750000 -96.999992\nv 50.000000 74.999985 -99.999985\nv 68.750000 74.999985 -99.999985\nv 68.750000 74.999985 -96.999985\nv 50.000000 74.999985 -96.999985\nv 75.000000 68.750000 -89.999992\nv 75.000000 74.999985 -89.999985\nv 75.000000 74.999985 -99.999985\nv 68.750000 74.999985 -89.999985\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.000000 0.000000\nvt 0.210000 0.430000\nvt 0.130000 0.430000\nf 250/247 251/248 252/249 253/250\nf 254/249 255/250 256/251 257/252\nf 258/253 259/254 260/251\nf 260/251 250/250 258/253\nf 258/255 250/255 253/255\nf 256/256 255/247 260/250\nf 256/256 260/250 259/253\nf 261/257 256/256 259/253\ng Mesh477 Corner_M_D_NW\nv 31.250000 24.999996 -74.999992\nv 25.000000 24.999996 -74.999992\nv 25.000000 24.999996 -68.750000\nv 31.250000 24.999996 -68.750000\nv 31.250000 31.250000 -74.999992\nv 25.000000 31.250000 -74.999992\nv 25.000000 31.250000 -68.750000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 262/258 263/259 264/260 265/261\nf 262/260 266/262 267/263 263/261\nf 267/262 268/264 264/265 263/263\ng Mesh305 Side_BC_S\nv 31.250000 25.000000 0.000000\nv 50.000000 25.000000 0.000000\nv 50.000000 25.000000 -3.000000\nv 31.250000 25.000000 -3.000000\nv 25.000000 50.000000 0.000000\nv 25.000000 31.250000 0.000001\nv 25.000000 31.250000 -3.000000\nv 25.000000 50.000000 -3.000000\nv 31.250000 25.000002 -10.000000\nv 25.000000 25.000002 -10.000000\nv 25.000000 25.000000 0.000000\nv 25.000000 31.250000 -9.999999\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.130000 0.430000\nvt 0.130000 0.480000\nvt 0.210000 0.430000\nvt 0.210000 0.480000\nvt 0.130000 0.530000\nf 269/266 270/267 271/268 272/269\nf 273/268 274/269 275/270 276/271\nf 277/272 278/273 279/269\nf 272/274 277/272 279/269\nf 269/266 272/274 279/269\nf 275/275 274/269 279/270\nf 280/273 275/275 279/270\nf 278/276 280/273 279/270\ng Mesh586 Corner_I3_U_NW\nv 18.750000 81.250000 -74.999985\nv 25.000000 81.250000 -81.250000\nv 18.750000 75.000015 -81.250000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 281/277 282/278 283/279\ng Mesh374 Side_Texture_Plate20 Side_Texture_Plate_Mirror10 Texture_Side_E\nv 81.250000 68.750000 -24.999996\nv 100.000000 68.750000 -24.999996\nv 100.000000 31.250000 -24.999998\nv 81.250000 31.250000 -24.999998\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 284/280 285/281 286/282 287/283\ng Mesh461 Side_Texture_Plate22 Side_Texture_Plate_Mirror11 Texture_Side_E1\nv 81.250000 81.250000 -68.750000\nv 100.000000 81.250000 -68.750000\nv 100.000000 81.250000 -31.250000\nv 81.250000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 288/284 289/284 290/284 291/284\ng Mesh443 Inner_BC_Side20 Side_BC_W\nv 3.000000 24.999996 -68.750000\nv 3.000000 25.000000 -49.999996\nv 0.000000 25.000000 -49.999996\nv 0.000000 24.999996 -68.750000\nv 0.000000 49.999996 -74.999992\nv 3.000000 49.999996 -74.999992\nv 3.000000 31.250000 -74.999992\nv 0.000000 31.250000 -74.999992\nv 18.750000 31.250000 -74.999992\nv 10.000000 31.250000 -74.999992\nv 10.000000 24.999996 -74.999992\nv 18.750000 24.999996 -74.999992\nv 18.750000 31.250000 -81.250000\nv 18.750000 24.999998 -81.250000\nv 18.750000 18.750000 -75.000000\nv 10.000000 24.999996 -68.750000\nv 18.750000 18.750000 -68.750000\nv 18.750000 24.999996 -68.750000\nv 0.000000 24.999996 -74.999992\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.130000 0.640000\nf 292/285 293/286 294/287 295/288\nf 296/286 297/289 298/290 299/285\nf 300/291 301/292 302/293 303/294\nf 304/287 301/295 300/296\nf 302/297 301/298 304/299 305/300\nf 302/301 305/302 306/287\nf 307/303 302/297 306/300 308/304\nf 303/303 302/304 307/292 309/291\nf 307/287 308/295 309/289\nf 310/290 299/285 298/305\nf 310/290 298/305 301/297\nf 310/290 301/297 302/298\nf 295/288 310/285 302/297\nf 295/288 302/297 307/303\nf 292/306 295/306 307/306\ng Mesh248 Corner_I_D_NW\nv 18.750000 24.999996 -68.750000\nv 18.750000 18.750000 -68.750000\nv 31.250000 18.750000 -68.750000\nv 31.250000 24.999996 -68.750000\nv 18.750000 24.999998 -81.250000\nv 25.000000 18.750000 -81.250000\nv 18.750000 18.750000 -75.000000\nv 31.250000 18.750000 -81.250000\nv 31.250000 24.999998 -81.250000\nv 25.000000 24.999998 -81.250000\nv 25.000000 31.250000 -81.250000\nv 25.000000 31.250000 -74.999992\nv 25.000000 24.999996 -74.999992\nv 18.750000 31.250000 -74.999992\nv 18.750000 31.250000 -81.250000\nv 18.750000 24.999996 -74.999992\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.380000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nf 311/307 312/308 313/309 314/310\nf 315/311 316/312 317/313\nf 318/314 319/315 314/308 313/307\nf 320/316 321/317 322/318 323/319\nf 324/320 322/321 321/322 325/312\nf 324/317 326/320 323/321 322/316\nf 319/323 320/324 323/313\nf 314/325 319/323 323/313\nf 326/322 311/321 323/313\nf 323/313 311/321 314/325\nf 317/326 316/327 318/319\nf 317/326 318/319 313/328\nf 312/325 317/326 313/328\ng Mesh364 Side_Texture_Plate_Side11 Texture_Side_N2\nv 68.750000 25.000006 -81.250000\nv 68.750000 18.750000 -81.250000\nv 31.250000 18.750000 -81.250000\nv 31.250000 25.000006 -81.250000\nvt 0.000000 1.000000\nf 327/329 328/329 329/329 330/329\ng Mesh170 Texture_Connector_Plate17 Texture_Connector_Plate_Mirror9 Texture_Connector_E_D\nv 75.000000 31.250000 -31.250000\nv 75.000000 31.250000 -68.750000\nv 75.000000 18.750000 -68.750000\nv 75.000000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 331/330 332/330 333/330 334/330\ng Mesh524 Inner_BC_Side19 Side_BC_W\nv 3.000000 31.250000 -25.000002\nv 3.000000 50.000004 -25.000000\nv 0.000000 50.000004 -25.000000\nv 0.000000 31.250000 -25.000002\nv 0.000000 25.000000 -49.999996\nv 3.000000 25.000000 -49.999996\nv 3.000000 24.999998 -31.250000\nv 0.000000 24.999998 -31.250000\nv 18.750000 24.999998 -31.250000\nv 10.000000 24.999998 -31.250000\nv 10.000000 24.999996 -25.000004\nv 18.750000 24.999996 -25.000004\nv 18.750000 18.750000 -31.250000\nv 18.750000 18.750000 -24.999996\nv 18.750000 25.000004 -18.750000\nv 10.000000 31.250000 -25.000002\nv 18.750000 31.250000 -18.750000\nv 18.750000 31.250000 -25.000002\nv 0.000000 24.999996 -25.000004\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.220000 0.530000\nvt 0.220000 0.580000\nf 335/331 336/332 337/333 338/334\nf 339/332 340/335 341/336 342/331\nf 343/337 344/338 345/339 346/340\nf 347/333 344/341 343/342\nf 345/343 344/344 347/345 348/346\nf 345/347 348/348 349/333\nf 350/349 345/343 349/346 351/350\nf 346/349 345/350 350/338 352/337\nf 350/333 351/341 352/335\nf 353/331 342/334 341/351\nf 353/331 341/351 344/349\nf 353/331 344/349 345/343\nf 335/352 338/331 353/336\nf 350/343 335/352 353/336\nf 345/344 350/343 353/336\ng Mesh271 Texture_Connector_Plate37 Texture_Connector_Plate_Mirror19 Texture_Connector_W_N\nv 25.000000 31.250000 -81.250000\nv 25.000000 68.750000 -81.250000\nv 25.000000 68.750000 -68.750000\nv 25.000000 31.250000 -68.750000\nvt 0.000000 1.000000\nf 354/353 355/353 356/353 357/353\ng Mesh153 Texture_Connector_Plate62 Texture_Connector_Plate_Mirror31 Texture_Connector_S_E\nv 68.750000 68.750000 -25.000004\nv 68.750000 31.250000 -25.000002\nv 81.250000 31.250000 -25.000002\nv 81.250000 68.750000 -25.000004\nvt 0.000000 1.000000\nf 358/354 359/354 360/354 361/354\ng Mesh132 Side_Texture_Plate62 Side_Texture_Plate_Mirror31 Texture_Side_W3\nv 18.750000 81.250000 -31.250000\nv 0.000000 81.250000 -31.250000\nv 0.000000 81.250000 -68.750000\nv 18.750000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 362/355 363/355 364/355 365/355\ng Mesh432 Side_Texture_Plate92 Side_Texture_Plate_Mirror46 Texture_Side_D2\nv 31.250000 18.750000 -75.000000\nv 31.250000 0.000006 -75.000000\nv 68.750000 0.000006 -75.000000\nv 68.750000 18.750000 -75.000000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 366/356 367/357 368/358 369/359\ng Mesh455 Side_Texture_Plate_Side52 Texture_Side_W\nv 0.000000 31.250000 -24.999998\nv 0.000000 31.250000 -18.750000\nv 0.000000 68.750000 -18.750000\nv 0.000000 68.750000 -24.999996\nvt 0.000000 1.000000\nf 370/360 371/360 372/360 373/360\ng Mesh49 Side_BC_E\nv 100.000000 24.999998 -31.250000\nv 100.000000 25.000000 -49.999996\nv 97.000000 25.000000 -49.999996\nv 97.000000 24.999998 -31.250000\nv 100.000000 50.000004 -25.000000\nv 100.000000 31.250000 -25.000002\nv 97.000000 31.250000 -25.000002\nv 97.000000 50.000004 -25.000000\nv 90.000000 24.999998 -31.250000\nv 90.000000 24.999996 -25.000004\nv 100.000000 24.999996 -25.000004\nv 90.000000 31.250000 -25.000002\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.200000 0.430000\nvt 0.130000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.220000 0.480000\nf 374/361 375/362 376/363 377/364\nf 378/363 379/364 380/365 381/366\nf 377/367 382/368 383/369\nf 374/361 377/367 383/369\nf 384/364 374/361 383/369\nf 383/370 385/369 380/371\nf 380/371 379/364 383/370\nf 383/370 379/364 384/365\ng Mesh411 Support_E_S\nv 81.250000 56.250000 -31.250000\nv 81.250000 56.250000 -68.750000\nv 77.000000 56.250000 -68.750000\nv 77.000000 56.250000 -31.250000\nv 81.250000 43.750000 -31.250000\nv 81.250000 43.750000 -68.750000\nv 77.000000 43.750000 -31.250000\nv 77.000000 43.750000 -68.750000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 386/372 387/373 388/374 389/375\nf 387/376 386/377 390/378 391/379\nf 391/380 390/381 392/375 393/374\nf 393/379 392/378 389/382 388/383\ng Mesh251 Texture_Connector_Plate70 Texture_Connector_Plate_Mirror35 Texture_Connector_U_W\nv 18.750000 75.000008 -68.750000\nv 18.750000 75.000008 -31.250000\nv 31.250000 75.000008 -31.250000\nv 31.250000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 394/384 395/384 396/384 397/384\ng Mesh63 Corner_I3_D_NE\nv 81.250000 24.999998 -81.250000\nv 81.250000 18.750000 -75.000000\nv 75.000000 18.750000 -81.250000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 398/385 399/386 400/387\ng Mesh549 Side_Texture_Plate_Side59 Texture_Side_W2\nv 18.750000 68.750000 -74.999992\nv 18.750000 68.750000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 18.750000 31.250000 -74.999992\nvt 0.000000 1.000000\nf 401/388 402/388 403/388 404/388\ng Mesh208 Texture_Connector_Plate5 Texture_Connector_Plate_Mirror3 Texture_Connector_E_N\nv 75.000000 68.750000 -81.250000\nv 75.000000 31.250000 -81.250000\nv 75.000000 31.250000 -68.750000\nv 75.000000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 405/389 406/389 407/389 408/389\ng Mesh392 Texture_Plate_U\nv 68.750000 81.250000 -31.250000\nv 31.250000 81.250000 -31.250000\nv 31.250000 81.250000 -68.750000\nv 68.750000 81.250000 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 409/390 410/391 411/392 412/393\ng Mesh563 Side_Texture_Plate_Side31 Texture_Side_E3\nv 81.250000 25.000002 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 18.750000 -68.750000\nv 81.250000 25.000004 -68.750000\nvt 0.000000 1.000000\nf 413/394 414/394 415/394 416/394\ng Mesh121 Side_BC_N\nv 25.000000 31.250000 -99.999992\nv 25.000000 50.000000 -99.999992\nv 25.000000 50.000000 -96.999992\nv 25.000000 31.250000 -96.999992\nv 50.000000 25.000002 -99.999992\nv 31.250000 25.000002 -99.999992\nv 31.250000 25.000000 -96.999992\nv 50.000000 25.000000 -96.999992\nv 25.000000 31.250000 -89.999992\nv 25.000000 25.000000 -89.999992\nv 25.000000 25.000002 -99.999992\nv 31.250000 25.000000 -89.999992\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.210000 0.430000\nvt 0.130000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.210000 0.480000\nf 417/395 418/396 419/397 420/398\nf 421/397 422/398 423/399 424/400\nf 420/401 425/402 426/403\nf 417/399 420/401 426/403\nf 427/398 417/399 426/403\nf 422/398 427/395 426/404\nf 423/405 422/398 426/404\nf 428/403 423/405 426/404\ng Mesh272 Edge_M_D_E\nv 81.250000 24.999998 -31.250000\nv 75.000000 18.750000 -31.250000\nv 75.000000 18.750000 -68.750000\nv 81.250000 24.999996 -68.750000\nv 68.750000 18.750000 -68.750000\nv 68.750000 18.750000 -31.250000\nv 68.750000 24.999998 -31.250000\nv 68.750000 24.999996 -68.750000\nv 75.000000 24.999996 -68.750000\nv 75.000000 24.999998 -31.250000\nv 75.000000 31.250000 -31.250000\nv 75.000000 31.250000 -68.750000\nv 81.250000 31.250000 -31.250000\nv 81.250000 31.250000 -68.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 429/406 430/407 431/408 432/409\nf 433/410 431/408 430/407 434/411\nf 435/411 436/410 433/412 434/413\nf 437/414 436/412 435/413 438/415\nf 438/416 439/417 440/418 437/419\nf 440/419 439/416 441/420 442/421\nf 429/406 432/409 442/421 441/420\ng Mesh428 Side_Texture_Plate_Side45 Texture_Side_S3\nv 68.750000 25.000000 0.000002\nv 68.750000 18.750000 0.000001\nv 31.250000 18.750000 0.000001\nv 31.250000 25.000000 0.000002\nvt 0.000000 1.000000\nf 443/422 444/422 445/422 446/422\ng Mesh574 Texture_Connector_Plate34 Texture_Connector_Plate_Mirror17 Texture_Connector_N_E\nv 81.250000 68.750000 -74.999992\nv 81.250000 31.250000 -74.999992\nv 68.750000 31.250000 -74.999992\nv 68.750000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 447/423 448/423 449/423 450/423\ng Mesh253 Side_Texture_Plate_Side40 Texture_Side_S1\nv 68.750000 75.000000 0.000006\nv 68.750000 81.250000 0.000007\nv 31.250000 81.250000 0.000007\nv 31.250000 75.000000 0.000006\nvt 0.000000 1.000000\nf 451/424 452/424 453/424 454/424\ng Mesh53 Texture_Connector_Plate82 Texture_Connector_Plate_Mirror41 Texture_Connector_D_S\nv 68.750000 25.000004 -18.750000\nv 31.250000 25.000004 -18.750000\nv 31.250000 24.999998 -31.250000\nv 68.750000 24.999998 -31.250000\nvt 0.000000 1.000000\nf 455/425 456/425 457/425 458/425\ng Mesh322 Inner_BC_Side10 Side_BC_S\nv 68.750000 75.000000 -3.000000\nv 50.000000 75.000000 -3.000000\nv 50.000000 75.000000 0.000000\nv 68.750000 75.000000 0.000000\nv 75.000000 50.000000 0.000000\nv 75.000000 50.000000 -3.000000\nv 75.000000 68.750000 -3.000000\nv 75.000000 68.750000 -0.000001\nv 75.000000 68.750000 -18.750000\nv 75.000000 68.750000 -10.000000\nv 75.000000 75.000000 -9.999999\nv 75.000000 75.000000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 81.250000 75.000000 -18.750000\nv 75.000000 81.250000 -18.750000\nv 68.750000 75.000000 -9.999999\nv 68.750000 81.250000 -18.750000\nv 68.750000 75.000000 -18.750000\nv 75.000000 75.000000 0.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.130000 0.640000\nvt 0.210000 0.580000\nf 459/426 460/427 461/428 462/429\nf 463/427 464/430 465/431 466/426\nf 467/432 468/433 469/434 470/435\nf 471/428 468/436 467/437\nf 469/438 468/439 471/440 472/441\nf 469/442 472/443 473/428\nf 474/444 469/438 473/441 475/445\nf 470/444 469/445 474/433 476/432\nf 474/428 475/436 476/430\nf 469/438 477/426 466/429\nf 468/444 469/438 466/429\nf 468/446 466/446 465/446\nf 474/438 459/447 469/439\nf 469/439 459/447 477/431\nf 477/431 459/447 462/426\ng Mesh72 Inner_BC_Side1 Group1 Side_BC_N\nv 31.250000 74.999985 -96.999985\nv 50.000000 74.999985 -96.999985\nv 50.000000 74.999985 -99.999985\nv 31.250000 74.999985 -99.999985\nv 25.000000 50.000000 -99.999992\nv 25.000000 50.000000 -96.999992\nv 25.000000 68.750000 -96.999992\nv 25.000000 68.750000 -99.999992\nv 25.000000 68.750000 -81.250000\nv 25.000000 68.750000 -89.999992\nv 25.000000 74.999985 -89.999985\nv 25.000000 75.000015 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 75.000015 -81.250000\nv 25.000000 81.250000 -81.250000\nv 31.250000 74.999985 -89.999985\nv 31.250000 81.250000 -81.250000\nv 31.250000 75.000015 -81.250000\nv 25.000000 74.999985 -99.999985\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.130000 0.640000\nvt 0.220000 0.530000\nf 478/448 479/449 480/450 481/451\nf 482/449 483/452 484/453 485/448\nf 486/454 487/455 488/456 489/457\nf 490/450 487/458 486/459\nf 488/460 487/461 490/462 491/463\nf 488/464 491/465 492/450\nf 493/466 488/460 492/463 494/467\nf 489/466 488/467 493/455 495/454\nf 493/450 494/458 495/452\nf 487/460 488/461 496/453\nf 487/460 496/453 485/448\nf 484/468 487/468 485/468\nf 481/451 496/448 488/460\nf 478/469 481/451 488/460\nf 493/466 478/469 488/460\ng Mesh578 Side_ Side_W\nv 0.000000 75.000015 -81.250000\nv 0.000000 81.250000 -74.999985\nv 18.750000 81.250000 -74.999985\nv 18.750000 75.000015 -81.250000\nv 0.000000 75.000015 -74.999985\nv 0.000000 68.750000 -81.250000\nv 0.000000 68.750000 -74.999992\nv 18.750000 68.750000 -74.999992\nv 18.750000 75.000015 -74.999985\nv 18.750000 68.750000 -81.250000\nv 18.750000 75.000008 -68.750000\nv 0.000000 75.000008 -68.750000\nv 18.750000 81.250000 -68.750000\nv 0.000000 81.250000 -68.750000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 497/470 498/471 499/472 500/473\nf 497/474 501/475 498/476\nf 497/474 502/477 503/478 501/475\nf 501/477 503/478 504/479 505/480\nf 504/479 503/478 502/481 506/482\nf 497/470 500/473 506/483 502/484\nf 505/485 507/486 508/487 501/488\nf 508/487 507/486 509/483 510/484\nf 509/482 499/472 498/471 510/481\nf 510/489 498/476 501/475 508/490\ng Mesh156 Side_Texture_Plate_Side36 Texture_Side_S\nv 25.000000 68.750000 0.000005\nv 18.750000 68.750000 0.000005\nv 18.750000 31.250000 0.000003\nv 25.000000 31.250000 0.000003\nvt 0.000000 1.000000\nf 511/491 512/491 513/491 514/491\ng Mesh357 Corner_I_U_SE\nv 68.750000 75.000008 -31.250000\nv 68.750000 81.250000 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 75.000008 -31.250000\nv 68.750000 75.000000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 75.000000 68.750000 -25.000004\nv 75.000000 75.000008 -25.000004\nv 81.250000 75.000008 -25.000004\nv 81.250000 68.750000 -25.000004\nv 75.000000 68.750000 -18.750000\nv 75.000000 75.000000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 81.250000 81.250000 -25.000002\nv 75.000000 81.250000 -18.750000\nv 81.250000 75.000000 -18.750000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.750000 0.390000\nvt 0.690000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 515/492 516/493 517/494 518/495\nf 516/496 515/497 519/493 520/492\nf 521/498 522/499 523/500 524/501\nf 522/498 521/502 525/503 526/499\nf 527/500 525/504 521/505 524/501\nf 528/505 529/506 530/507\nf 517/503 516/508 520/509\nf 528/510 517/503 520/509\nf 529/511 528/510 520/509\nf 519/500 515/509 522/506\nf 522/506 515/509 518/512\nf 522/506 518/512 523/513\nf 519/500 522/506 526/504\ng Mesh160 Side_Texture_Plate24 Side_Texture_Plate_Mirror12 Texture_Side_E1\nv 81.250000 75.000008 -68.750000\nv 100.000000 75.000008 -68.750000\nv 100.000000 75.000008 -31.250000\nv 81.250000 75.000008 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 531/514 532/515 533/516 534/517\ng Mesh136 Side_Texture_Plate_Side78 Texture_Side_U3\nv 75.000000 81.250000 -68.750000\nv 81.250000 81.250000 -68.750000\nv 81.250000 81.250000 -31.250000\nv 75.000000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 535/518 536/518 537/518 538/518\ng Mesh33 Side_Texture_Plate_Side79 Texture_Side_U3\nv 75.000000 81.250000 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 81.250000 -68.750000\nv 75.000000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 539/519 540/519 541/519 542/519\ng Mesh302 Side_Texture_Plate_Side89 Texture_Side_D2\nv 68.750000 0.000006 -75.000000\nv 68.750000 0.000007 -81.250000\nv 31.250000 0.000007 -81.250000\nv 31.250000 0.000006 -75.000000\nvt 0.000000 1.000000\nf 543/520 544/520 545/520 546/520\ng Mesh478 Side_BC_U\nv 75.000000 100.000008 -31.250000\nv 75.000000 100.000008 -50.000000\nv 75.000000 97.000008 -50.000000\nv 75.000000 97.000008 -31.250000\nv 50.000000 100.000008 -24.999998\nv 68.750000 100.000008 -24.999998\nv 68.750000 97.000008 -25.000000\nv 50.000000 97.000008 -25.000000\nv 75.000000 100.000008 -24.999998\nv 75.000000 90.000008 -25.000000\nv 75.000000 90.000008 -31.250000\nv 68.750000 90.000008 -25.000000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.130000 0.480000\nvt 0.220000 0.430000\nvt 0.130000 0.430000\nvt 0.210000 0.480000\nvt 0.130000 0.530000\nf 547/521 548/522 549/523 550/524\nf 551/523 552/524 553/525 554/526\nf 555/524 547/521 556/527\nf 556/527 547/521 550/528\nf 556/527 550/528 557/529\nf 553/530 552/524 555/525\nf 553/530 555/525 556/531\nf 558/527 553/530 556/531\ng Mesh107 Corner_M_D_NW\nv 31.250000 18.750000 -75.000000\nv 31.250000 18.750000 -68.750000\nv 25.000000 18.750000 -68.750000\nv 25.000000 18.750000 -75.000000\nv 18.750000 24.999996 -74.999992\nv 18.750000 24.999996 -68.750000\nv 25.000000 24.999998 -81.250000\nv 18.750000 31.250000 -74.999992\nv 25.000000 31.250000 -81.250000\nv 31.250000 31.250000 -81.250000\nv 31.250000 24.999998 -81.250000\nv 18.750000 31.250000 -68.750000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 559/532 560/533 561/534 562/535\nf 563/536 562/535 561/534 564/537\nf 562/538 563/539 565/540\nf 566/541 567/542 565/535 563/536\nf 567/542 568/543 569/532 565/535\nf 569/544 559/545 562/546 565/540\nf 570/532 566/543 563/547 564/548\ng Mesh512 Texture_Connector_Plate32 Texture_Connector_Plate_Mirror16 Texture_Connector_N_W\nv 31.250000 68.750000 -81.250000\nv 31.250000 31.250000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 18.750000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 571/549 572/549 573/549 574/549\ng Mesh180 Side_Texture_Plate_Side21 Texture_Side_E1\nv 100.000000 75.000008 -31.250000\nv 100.000000 81.250000 -31.250000\nv 100.000000 81.250000 -68.750000\nv 100.000000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 575/550 576/550 577/550 578/550\ng Mesh606 Edge_Side_S_DS Side_E\nv 100.000000 18.750000 -24.999996\nv 100.000000 25.000004 -18.750000\nv 81.250000 25.000004 -18.750000\nv 81.250000 18.750000 -24.999996\nv 100.000000 24.999996 -25.000004\nv 100.000000 18.750000 -31.250000\nv 100.000000 24.999998 -31.250000\nv 81.250000 24.999998 -31.250000\nv 81.250000 24.999996 -25.000004\nv 81.250000 18.750000 -31.250000\nv 81.250000 31.250000 -25.000002\nv 100.000000 31.250000 -25.000002\nv 81.250000 31.250000 -18.750000\nv 100.000000 31.250000 -18.750000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 579/551 580/552 581/553 582/554\nf 579/555 583/556 580/557\nf 579/555 584/558 585/559 583/556\nf 583/558 585/559 586/560 587/561\nf 586/560 585/559 584/562 588/563\nf 579/551 582/554 588/564 584/565\nf 587/566 589/567 590/568 583/569\nf 590/568 589/567 591/564 592/565\nf 591/563 581/553 580/552 592/562\nf 592/570 580/557 583/556 590/571\ng Mesh527 Inner_BC_Side4 Side_BC_N\nv 68.750000 25.000000 -96.999992\nv 50.000000 25.000000 -96.999992\nv 50.000000 25.000002 -99.999992\nv 68.750000 25.000002 -99.999992\nv 75.000000 50.000000 -99.999992\nv 75.000000 50.000000 -96.999992\nv 75.000000 31.250000 -96.999992\nv 75.000000 31.250000 -99.999992\nv 75.000000 31.250000 -81.250000\nv 75.000000 31.250000 -89.999992\nv 75.000000 25.000000 -89.999992\nv 75.000000 24.999998 -81.250000\nv 81.250000 31.250000 -81.250000\nv 81.250000 24.999998 -81.250000\nv 75.000000 18.750000 -81.250000\nv 68.750000 25.000000 -89.999992\nv 68.750000 18.750000 -81.250000\nv 68.750000 24.999998 -81.250000\nv 75.000000 25.000002 -99.999992\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 593/572 594/573 595/574 596/575\nf 597/573 598/576 599/577 600/572\nf 601/578 602/579 603/580 604/581\nf 605/574 602/582 601/583\nf 603/584 602/585 605/586 606/587\nf 603/588 606/589 607/574\nf 608/590 603/584 607/587 609/591\nf 604/590 603/591 608/579 610/578\nf 608/574 609/582 610/576\nf 599/592 602/584 603/585\nf 600/572 599/592 603/585\nf 611/577 600/572 603/585\nf 593/593 596/575 611/572\nf 593/593 611/572 603/584\nf 608/590 593/593 603/584\ng Mesh473 Corner_I_D_SW\nv 31.250000 25.000004 -18.750000\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 -31.250000\nv 31.250000 24.999998 -31.250000\nv 18.750000 25.000004 -18.750000\nv 18.750000 18.750000 -24.999996\nv 25.000000 18.750000 -18.750000\nv 18.750000 18.750000 -31.250000\nv 18.750000 24.999998 -31.250000\nv 18.750000 24.999996 -25.000004\nv 18.750000 31.250000 -25.000002\nv 25.000000 31.250000 -25.000002\nv 25.000000 24.999996 -25.000004\nv 25.000000 31.250000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 25.000000 25.000004 -18.750000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.380000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nf 612/594 613/595 614/596 615/597\nf 616/598 617/599 618/600\nf 619/601 620/602 615/595 614/594\nf 621/603 622/604 623/605 624/606\nf 625/607 623/608 622/609 626/599\nf 625/604 627/607 624/608 623/603\nf 615/610 620/611 621/612\nf 624/600 615/610 621/612\nf 612/608 615/610 624/600\nf 612/608 624/600 627/609\nf 617/613 619/606 614/614\nf 617/613 614/614 613/610\nf 618/615 617/613 613/610\ng Mesh144 Corner_M_U_NW\nv 18.750000 68.750000 -74.999992\nv 18.750000 68.750000 -68.750000\nv 18.750000 75.000008 -68.750000\nv 18.750000 75.000015 -74.999985\nv 25.000000 81.250000 -74.999985\nv 25.000000 81.250000 -68.750000\nv 25.000000 75.000015 -81.250000\nv 31.250000 81.250000 -74.999985\nv 31.250000 75.000015 -81.250000\nv 31.250000 68.750000 -81.250000\nv 25.000000 68.750000 -81.250000\nv 31.250000 81.250000 -68.750000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 628/616 629/617 630/618 631/619\nf 632/620 631/619 630/618 633/621\nf 631/622 632/623 634/624\nf 635/625 636/626 634/619 632/620\nf 636/626 637/627 638/616 634/619\nf 638/628 628/629 631/630 634/624\nf 639/616 635/627 632/631 633/632\ng Mesh548 Side_Texture_Plate1 Side_Texture_Plate_Mirror1 Texture_Side_N\nv 68.750000 81.250000 -81.250000\nv 68.750000 81.250000 -99.999985\nv 31.250000 81.250000 -99.999985\nv 31.250000 81.250000 -81.250000\nvt 0.000000 1.000000\nf 640/633 641/633 642/633 643/633\ng Mesh385 Texture_Connector_Plate88 Texture_Connector_Plate_Mirror44 Texture_Connector_D_N\nv 68.750000 18.750000 -68.750000\nv 31.250000 18.750000 -68.750000\nv 31.250000 18.750000 -81.250000\nv 68.750000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 644/634 645/634 646/634 647/634\ng Mesh598 Side_BC_W\nv 0.000000 75.000008 -31.250000\nv 0.000000 75.000008 -50.000004\nv 3.000000 75.000008 -50.000004\nv 3.000000 75.000008 -31.250000\nv 0.000000 50.000004 -25.000000\nv 0.000000 68.750000 -25.000004\nv 3.000000 68.750000 -25.000004\nv 3.000000 50.000004 -25.000000\nv 0.000000 75.000008 -25.000004\nv 10.000000 75.000008 -31.250000\nv 10.000000 75.000008 -25.000004\nv 10.000000 68.750000 -25.000004\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.220000 0.480000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.130000 0.430000\nvt 0.000000 0.000000\nf 648/635 649/636 650/637 651/638\nf 652/639 653/640 654/638 655/637\nf 656/640 648/638 651/641\nf 656/640 651/641 657/642\nf 656/640 657/642 658/643\nf 653/635 656/638 658/642\nf 653/635 658/642 659/644\nf 654/645 653/645 659/645\ng Mesh559 Corner_I3_U_SW\nv 18.750000 81.250000 -31.250000\nv 25.000000 81.250000 -31.250000\nv 25.000000 75.000008 -31.250000\nv 18.750000 75.000008 -31.250000\nv 25.000000 81.250000 -25.000002\nv 25.000000 75.000008 -25.000004\nv 31.250000 81.250000 -25.000002\nv 31.250000 75.000008 -25.000004\nv 31.250000 75.000000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 25.000000 75.000000 -18.750000\nv 25.000000 68.750000 -25.000004\nv 25.000000 68.750000 -18.750000\nv 18.750000 68.750000 -25.000004\nv 18.750000 75.000008 -25.000004\nv 18.750000 68.750000 -18.750000\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 660/646 661/647 662/648 663/649\nf 664/650 665/651 662/652 661/653\nf 665/654 664/653 666/652 667/655\nf 668/646 667/649 666/656 669/655\nf 670/655 665/656 667/657 668/654\nf 671/647 665/646 670/658 672/659\nf 665/660 671/659 673/658 674/661\nf 675/658 673/646 671/655 672/652\nf 663/658 662/652 665/651 674/661\ng Mesh77 Corner_I_U_NE\nv 68.750000 75.000008 -68.750000\nv 68.750000 81.250000 -68.750000\nv 68.750000 81.250000 -81.250000\nv 68.750000 75.000015 -81.250000\nv 81.250000 75.000008 -68.750000\nv 81.250000 81.250000 -68.750000\nv 75.000000 68.750000 -74.999992\nv 75.000000 75.000015 -74.999985\nv 75.000000 75.000015 -81.250000\nv 75.000000 68.750000 -81.250000\nv 81.250000 68.750000 -74.999992\nv 81.250000 75.000015 -74.999985\nv 81.250000 68.750000 -81.250000\nv 75.000000 81.250000 -81.250000\nv 81.250000 81.250000 -74.999985\nv 81.250000 75.000015 -81.250000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 676/662 677/663 678/664 679/665\nf 677/666 676/667 680/663 681/662\nf 682/668 683/669 684/670 685/671\nf 683/668 682/672 686/673 687/669\nf 688/670 686/674 682/675 685/671\nf 689/675 690/676 691/677\nf 689/678 678/673 677/679\nf 690/680 689/678 677/679\nf 681/681 690/680 677/679\nf 676/681 679/682 684/683\nf 676/681 684/683 683/676\nf 676/681 683/676 687/674\nf 676/681 687/674 680/670\ng Mesh402 Inner_BC_Side23 Side_BC_D\nv 68.750000 3.000000 -25.000000\nv 50.000000 3.000000 -25.000000\nv 50.000000 0.000000 -25.000000\nv 68.750000 0.000000 -25.000000\nv 75.000000 0.000000 -50.000000\nv 75.000000 3.000000 -50.000000\nv 75.000000 3.000000 -31.250000\nv 75.000000 0.000001 -31.250000\nv 75.000000 18.750000 -31.250000\nv 75.000000 10.000001 -31.250000\nv 75.000000 10.000000 -24.999998\nv 75.000000 18.750000 -24.999996\nv 81.250000 18.750000 -31.250000\nv 81.250000 18.750000 -24.999996\nv 75.000000 18.750000 -18.750000\nv 68.750000 10.000000 -24.999998\nv 68.750000 18.750000 -18.750000\nv 68.750000 18.750000 -24.999996\nv 75.000000 0.000000 -25.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.530000\nvt 0.210000 0.580000\nf 692/684 693/685 694/686 695/687\nf 696/685 697/688 698/689 699/684\nf 700/690 701/691 702/692 703/693\nf 704/686 701/694 700/695\nf 702/696 701/697 704/698 705/699\nf 702/700 705/701 706/686\nf 707/702 702/696 706/699 708/703\nf 703/702 702/703 707/691 709/690\nf 707/686 708/694 709/688\nf 701/702 702/696 710/684\nf 698/704 701/702 710/684\nf 699/687 698/704 710/684\nf 707/696 692/705 702/697\nf 702/697 692/705 710/689\nf 710/689 692/705 695/684\ng Mesh475 Spacer1 Group2\nv 25.000000 68.750000 -68.750000\nv 18.750000 68.750000 -68.750000\nv 18.750000 68.750000 -81.250000\nv 25.000000 68.750000 -81.250000\nv 18.750000 75.000015 -81.250000\nv 18.750000 75.000008 -68.750000\nv 25.000000 81.250000 -81.250000\nv 25.000000 81.250000 -68.750000\nv 31.250000 81.250000 -68.750000\nv 31.250000 81.250000 -81.250000\nv 31.250000 75.000015 -81.250000\nv 31.250000 75.000008 -68.750000\nv 25.000000 75.000015 -81.250000\nv 25.000000 75.000008 -68.750000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 711/706 712/707 713/708 714/709\nf 715/710 713/708 712/707 716/711\nf 717/712 715/710 716/711 718/713\nf 718/713 719/714 720/715 717/712\nf 721/716 720/715 719/714 722/717\nf 723/718 721/716 722/717 724/719\nf 724/720 711/706 714/709 723/721\ng Mesh238 Edge_Side_S_UN Side_E\nv 100.000000 81.250000 -74.999985\nv 100.000000 75.000015 -81.250000\nv 81.250000 75.000015 -81.250000\nv 81.250000 81.250000 -74.999985\nv 100.000000 75.000015 -74.999985\nv 100.000000 81.250000 -68.750000\nv 100.000000 75.000008 -68.750000\nv 81.250000 75.000008 -68.750000\nv 81.250000 75.000015 -74.999985\nv 81.250000 81.250000 -68.750000\nv 81.250000 68.750000 -74.999992\nv 100.000000 68.750000 -74.999992\nv 81.250000 68.750000 -81.250000\nv 100.000000 68.750000 -81.250000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 725/722 726/723 727/724 728/725\nf 725/726 729/727 726/728\nf 725/726 730/729 731/730 729/727\nf 729/729 731/730 732/731 733/732\nf 732/731 731/730 730/733 734/734\nf 725/722 728/725 734/735 730/736\nf 733/737 735/738 736/739 729/740\nf 736/739 735/738 737/735 738/736\nf 737/734 727/724 726/723 738/733\nf 738/741 726/728 729/727 736/742\ng Mesh401 Texture_Connector_Plate60 Texture_Connector_Plate_Mirror30 Texture_Connector_S_D\nv 68.750000 31.250000 -18.750000\nv 31.250000 31.250000 -18.750000\nv 31.250000 18.750000 -18.750000\nv 68.750000 18.750000 -18.750000\nvt 0.000000 1.000000\nf 739/743 740/743 741/743 742/743\ng Mesh181 Side_Texture_Plate_Side83 Texture_Side_D\nv 25.000000 18.750000 -31.250000\nv 18.750000 18.750000 -31.250000\nv 18.750000 18.750000 -68.750000\nv 25.000000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 743/744 744/744 745/744 746/744\ng Mesh535 Corner_M_U_SW\nv 25.000000 68.750000 -18.750000\nv 31.250000 68.750000 -18.750000\nv 31.250000 75.000000 -18.750000\nv 25.000000 75.000000 -18.750000\nv 25.000000 81.250000 -25.000002\nv 31.250000 81.250000 -25.000002\nv 18.750000 75.000008 -25.000004\nv 25.000000 81.250000 -31.250000\nv 18.750000 75.000008 -31.250000\nv 18.750000 68.750000 -31.250000\nv 18.750000 68.750000 -25.000004\nv 31.250000 81.250000 -31.250000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 747/745 748/746 749/747 750/748\nf 751/749 750/748 749/747 752/750\nf 750/751 751/752 753/753\nf 754/754 755/755 753/748 751/749\nf 755/755 756/756 757/745 753/748\nf 757/757 747/758 750/759 753/753\nf 758/745 754/756 751/760 752/761\ng Mesh418 Mount_S_W\nv 18.750000 56.250000 0.000001\nv 25.000000 56.250000 0.000001\nv 25.000000 56.250000 -18.750000\nv 18.750000 56.250000 -24.999998\nv 18.750000 43.750000 -0.000000\nv 25.000000 43.750000 -0.000000\nv 18.750000 43.750000 -25.000000\nv 25.000000 43.750000 -18.750000\nv 18.750000 52.000004 -25.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.080000\nvt 0.860000 0.080000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.650000 0.180000\nvt 0.930000 0.190000\nvt 0.860000 0.170000\nf 759/762 760/763 761/764 762/765\nf 760/766 759/762 763/767 764/768\nf 765/769 766/770 764/771 763/772\nf 760/770 764/773 766/766 761/771\nf 763/772 759/774 762/775\nf 763/772 762/775 767/776\nf 763/772 767/776 765/769\nf 761/777 762/774 767/778\nf 766/767 761/777 767/778\nf 766/767 767/778 765/768\ng Mesh54 Texture_Connector_Plate27 Texture_Connector_Plate_Mirror14 Texture_Connector_N_U\nv 68.750000 81.250000 -81.250000\nv 31.250000 81.250000 -81.250000\nv 31.250000 68.750000 -81.250000\nv 68.750000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 768/779 769/779 770/779 771/779\ng Mesh200 Side_Texture_Plate_Side58 Texture_Side_W2\nv 18.750000 31.250000 -74.999992\nv 18.750000 31.250000 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 772/780 773/780 774/780 775/780\ng Mesh169 Texture_Connector_Plate46 Texture_Connector_Plate_Mirror23 Texture_Connector_W_D\nv 25.000000 31.250000 -31.250000\nv 25.000000 31.250000 -68.750000\nv 25.000000 18.750000 -68.750000\nv 25.000000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 776/781 777/781 778/781 779/781\ng Mesh407 Inner_Plate_S1\nv 31.250000 68.750000 -25.000004\nv 68.750000 68.750000 -25.000004\nv 68.750000 31.250000 -25.000002\nv 31.250000 31.250000 -25.000002\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 780/782 781/783 782/784 783/785\ng Mesh131 Side_Texture_Plate68 Side_Texture_Plate_Mirror34 Texture_Side_U\nv 25.000000 81.250000 -68.750000\nv 25.000000 100.000008 -68.750000\nv 25.000000 100.000008 -31.250000\nv 25.000000 81.250000 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 784/786 785/787 786/788 787/789\ng Mesh564 Side_Texture_Plate53 Side_Texture_Plate_Mirror27 Texture_Side_W1\nv 18.750000 18.750000 -31.250000\nv 0.000000 18.750000 -31.250000\nv 0.000000 18.750000 -68.750000\nv 18.750000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 788/790 789/790 790/790 791/790\ng Mesh17 Texture_Connector_Plate58 Texture_Connector_Plate_Mirror29 Texture_Connector_S_D\nv 68.750000 31.250000 -25.000002\nv 31.250000 31.250000 -25.000002\nv 31.250000 18.750000 -24.999996\nv 68.750000 18.750000 -24.999996\nvt 0.000000 1.000000\nf 792/791 793/791 794/791 795/791\ng Mesh297 Side_Texture_Plate29 Side_Texture_Plate_Mirror15 Texture_Side_E3\nv 81.250000 18.750000 -68.750000\nv 100.000000 18.750000 -68.750000\nv 100.000000 18.750000 -31.250000\nv 81.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 796/792 797/792 798/792 799/792\ng Mesh350 Side_Texture_Plate_Side88 Texture_Side_D1\nv 68.750000 0.000002 -25.000000\nv 68.750000 0.000001 -18.750000\nv 31.250000 0.000001 -18.750000\nv 31.250000 0.000002 -25.000000\nvt 0.000000 1.000000\nf 800/793 801/793 802/793 803/793\ng Mesh218 Texture_Connector_Plate44 Texture_Connector_Plate_Mirror22 Texture_Connector_W_S\nv 18.750000 68.750000 -31.250000\nv 18.750000 31.250000 -31.250000\nv 18.750000 31.250000 -18.750000\nv 18.750000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 804/794 805/794 806/794 807/794\ng Mesh352 Side_Texture_Plate10 Side_Texture_Plate_Mirror5 Texture_Side_N2\nv 68.750000 18.750000 -81.250000\nv 68.750000 18.750000 -100.000000\nv 31.250000 18.750000 -100.000000\nv 31.250000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 808/795 809/795 810/795 811/795\ng Mesh336 Corner_M_D_NE\nv 81.250000 31.250000 -74.999992\nv 81.250000 31.250000 -68.750000\nv 81.250000 24.999996 -68.750000\nv 81.250000 24.999996 -74.999992\nv 75.000000 18.750000 -75.000000\nv 75.000000 18.750000 -68.750000\nv 75.000000 24.999998 -81.250000\nv 68.750000 18.750000 -75.000000\nv 68.750000 24.999998 -81.250000\nv 68.750000 31.250000 -81.250000\nv 75.000000 31.250000 -81.250000\nv 68.750000 18.750000 -68.750000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 812/796 813/797 814/798 815/799\nf 816/800 815/799 814/798 817/801\nf 815/802 816/803 818/804\nf 819/805 820/806 818/799 816/800\nf 820/806 821/807 822/796 818/799\nf 822/808 812/809 815/810 818/804\nf 823/796 819/807 816/811 817/812\ng Mesh36 Side_Texture_Plate46 Side_Texture_Plate_Mirror23 Texture_Side_S3\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 0.000001\nv 68.750000 18.750000 0.000001\nv 68.750000 18.750000 -18.750000\nvt 0.000000 1.000000\nf 824/813 825/813 826/813 827/813\ng Mesh125 Inner_BC_Side12 Side_BC_S\nv 31.250000 25.000000 -3.000000\nv 50.000000 25.000000 -3.000000\nv 50.000000 25.000000 0.000000\nv 31.250000 25.000000 0.000000\nv 25.000000 50.000000 0.000000\nv 25.000000 50.000000 -3.000000\nv 25.000000 31.250000 -3.000000\nv 25.000000 31.250000 0.000001\nv 25.000000 31.250000 -18.750000\nv 25.000000 31.250000 -9.999999\nv 25.000000 25.000002 -10.000000\nv 25.000000 25.000004 -18.750000\nv 18.750000 31.250000 -18.750000\nv 18.750000 25.000004 -18.750000\nv 25.000000 18.750000 -18.750000\nv 31.250000 25.000002 -10.000000\nv 31.250000 18.750000 -18.750000\nv 31.250000 25.000004 -18.750000\nv 25.000000 25.000000 0.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 828/814 829/815 830/816 831/817\nf 832/815 833/818 834/819 835/814\nf 836/820 837/821 838/822 839/823\nf 840/816 837/824 836/825\nf 838/826 837/827 840/828 841/829\nf 838/830 841/831 842/816\nf 843/832 838/826 842/829 844/833\nf 839/832 838/833 843/821 845/820\nf 843/816 844/824 845/818\nf 846/819 835/814 834/834\nf 846/819 834/834 837/826\nf 846/819 837/826 838/827\nf 846/814 838/826 843/832\nf 843/832 828/835 846/814\nf 846/814 828/835 831/817\ng Mesh577 Texture_Connector_Plate24 Texture_Connector_Plate_Mirror12 Texture_Connector_N_D\nv 31.250000 31.250000 -81.250000\nv 68.750000 31.250000 -81.250000\nv 68.750000 18.750000 -81.250000\nv 31.250000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 847/836 848/836 849/836 850/836\ng Mesh134 Side_D3 Side_D\nv 18.750000 18.750000 -75.000000\nv 25.000000 18.750000 -81.250000\nv 25.000000 0.000001 -81.250000\nv 18.750000 0.000000 -75.000000\nv 31.250000 0.000001 -81.250000\nv 31.250000 18.750000 -81.250000\nv 31.250000 0.000000 -75.000000\nv 25.000000 0.000000 -75.000000\nv 31.250000 18.750000 -75.000000\nv 25.000000 18.750000 -75.000000\nv 25.000000 18.750000 -68.750000\nv 25.000000 -0.000001 -68.750000\nv 18.750000 18.750000 -68.750000\nv 18.750000 -0.000001 -68.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.650000 0.850000\nvt 0.650000 0.780000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.650000 0.950000\nvt 0.700000 0.950000\nvt 0.700000 1.000000\nvt 0.650000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.950000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.650000 0.630000\nvt 0.650000 0.680000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.750000 0.900000\nvt 0.750000 0.950000\nvt 0.700000 0.900000\nf 851/837 852/838 853/839 854/840\nf 855/841 853/839 852/838 856/842\nf 857/843 858/844 853/845 855/846\nf 858/843 857/846 859/847 860/848\nf 855/841 856/842 859/848 857/843\nf 860/849 861/850 862/851 858/852\nf 863/853 864/854 862/852 861/849\nf 851/837 854/840 864/854 863/853\nf 864/855 854/856 858/844 862/857\nf 853/845 858/844 854/856\ng Mesh173 Texture_Connector_Plate91 Texture_Connector_Plate_Mirror46 Texture_Connector_D_E\nv 68.750000 18.750000 -68.750000\nv 68.750000 18.750000 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 865/858 866/858 867/858 868/858\ng Mesh278 Texture_Connector_Plate59 Texture_Connector_Plate_Mirror30 Texture_Connector_S_D\nv 31.250000 31.250000 -18.750000\nv 68.750000 31.250000 -18.750000\nv 68.750000 18.750000 -18.750000\nv 31.250000 18.750000 -18.750000\nvt 0.000000 1.000000\nf 869/859 870/859 871/859 872/859\ng Mesh31 Side_Texture_Plate_Side24 Texture_Side_E1\nv 100.000000 75.000008 -68.750000\nv 100.000000 81.250000 -68.750000\nv 100.000000 81.250000 -31.250000\nv 100.000000 75.000008 -31.250000\nvt 0.000000 1.000000\nf 873/860 874/860 875/860 876/860\ng Mesh26 Texture_Connector_Plate31 Texture_Connector_Plate_Mirror16 Texture_Connector_N_W\nv 31.250000 31.250000 -81.250000\nv 31.250000 68.750000 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 877/861 878/861 879/861 880/861\ng Mesh543 Side_Texture_Plate_Side14 Texture_Side_N3\nv 75.000000 31.250000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 75.000000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 881/862 882/862 883/862 884/862\ng Mesh525 Texture_Plate_W\nv 18.750000 68.750000 -31.250000\nv 18.750000 68.750000 -68.750000\nv 18.750000 31.250000 -68.750000\nv 18.750000 31.250000 -31.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 885/863 886/864 887/865 888/866\ng Mesh41 Side_Texture_Plate80 Side_Texture_Plate_Mirror40 Texture_Side_U3\nv 75.000000 81.250000 -31.250000\nv 75.000000 100.000008 -31.250000\nv 75.000000 100.000008 -68.750000\nv 75.000000 81.250000 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 889/867 890/868 891/869 892/870\ng Mesh111 Corner_I_D_SE\nv 81.250000 24.999998 -31.250000\nv 81.250000 18.750000 -31.250000\nv 68.750000 18.750000 -31.250000\nv 68.750000 24.999998 -31.250000\nv 81.250000 25.000004 -18.750000\nv 75.000000 18.750000 -18.750000\nv 81.250000 18.750000 -24.999996\nv 68.750000 18.750000 -18.750000\nv 68.750000 25.000004 -18.750000\nv 75.000000 25.000004 -18.750000\nv 75.000000 31.250000 -18.750000\nv 75.000000 31.250000 -25.000002\nv 75.000000 24.999996 -25.000004\nv 81.250000 31.250000 -25.000002\nv 81.250000 31.250000 -18.750000\nv 81.250000 24.999996 -25.000004\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.380000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nf 893/871 894/872 895/873 896/874\nf 897/875 898/876 899/877\nf 900/878 901/879 896/872 895/871\nf 902/880 903/881 904/882 905/883\nf 906/884 904/885 903/886 907/876\nf 906/881 908/884 905/885 904/880\nf 905/877 896/887 901/888\nf 893/885 896/887 905/877\nf 908/886 893/885 905/877\nf 902/889 905/877 901/888\nf 900/883 895/890 894/887\nf 900/883 894/887 899/891\nf 900/883 899/891 898/892\ng Mesh44 Side_Texture_Plate_Side77 Texture_Side_U3\nv 75.000000 100.000008 -68.750000\nv 81.250000 100.000008 -68.750000\nv 81.250000 100.000008 -31.250000\nv 75.000000 100.000008 -31.250000\nvt 0.000000 1.000000\nf 909/893 910/893 911/893 912/893\ng Mesh24 Edge_Side_U_NE Side_U\nv 75.000000 100.000015 -81.250000\nv 81.250000 100.000015 -75.000015\nv 81.250000 81.250000 -74.999985\nv 75.000000 81.250000 -81.250000\nv 75.000000 100.000015 -75.000015\nv 68.750000 100.000015 -81.250000\nv 68.750000 100.000015 -75.000015\nv 68.750000 81.250000 -74.999985\nv 75.000000 81.250000 -74.999985\nv 68.750000 81.250000 -81.250000\nv 75.000000 81.250000 -68.750000\nv 75.000000 100.000008 -68.750000\nv 81.250000 81.250000 -68.750000\nv 81.250000 100.000008 -68.750000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 913/894 914/895 915/896 916/897\nf 913/898 917/899 914/900\nf 913/898 918/901 919/902 917/899\nf 917/901 919/902 920/903 921/904\nf 920/903 919/902 918/905 922/906\nf 913/894 916/897 922/907 918/908\nf 921/909 923/910 924/911 917/912\nf 924/911 923/910 925/907 926/908\nf 925/906 915/896 914/895 926/905\nf 926/913 914/900 917/899 924/914\ng Mesh465 Side_Texture_Plate_Side81 Texture_Side_D\nv 25.000000 0.000005 -68.750000\nv 18.750000 0.000005 -68.750000\nv 18.750000 0.000003 -31.250000\nv 25.000000 0.000003 -31.250000\nvt 0.000000 1.000000\nf 927/915 928/915 929/915 930/915\ng Mesh182 Side_Texture_Plate_Side70 Texture_Side_U1\nv 68.750000 81.250000 -24.999994\nv 68.750000 81.250000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 31.250000 81.250000 -24.999994\nvt 0.000000 1.000000\nf 931/916 932/916 933/916 934/916\ng Mesh441 Inner_Plate_W1\nv 25.000000 68.750000 -68.750000\nv 25.000000 68.750000 -31.250000\nv 25.000000 31.250000 -31.250000\nv 25.000000 31.250000 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 935/917 936/918 937/919 938/920\ng Mesh159 Side_Texture_Plate_Side9 Texture_Side_N2\nv 31.250000 25.000010 -99.999992\nv 31.250000 18.750000 -100.000000\nv 68.750000 18.750000 -100.000000\nv 68.750000 25.000010 -99.999992\nvt 0.000000 1.000000\nf 939/921 940/921 941/921 942/921\ng Mesh499 Side_3 Side_W\nv 0.000000 81.250000 -25.000002\nv 0.000000 75.000000 -18.750000\nv 18.750000 75.000000 -18.750000\nv 18.750000 81.250000 -25.000002\nv 0.000000 75.000008 -25.000004\nv 0.000000 81.250000 -31.250000\nv 0.000000 75.000008 -31.250000\nv 18.750000 75.000008 -31.250000\nv 18.750000 75.000008 -25.000004\nv 18.750000 81.250000 -31.250000\nv 18.750000 68.750000 -25.000004\nv 0.000000 68.750000 -25.000004\nv 18.750000 68.750000 -18.750000\nv 0.000000 68.750000 -18.750000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 943/922 944/923 945/924 946/925\nf 943/926 947/927 944/928\nf 943/926 948/929 949/930 947/927\nf 947/929 949/930 950/931 951/932\nf 950/931 949/930 948/933 952/934\nf 943/922 946/925 952/935 948/936\nf 951/937 953/938 954/939 947/940\nf 954/939 953/938 955/935 956/936\nf 955/934 945/924 944/923 956/933\nf 956/941 944/928 947/927 954/942\ng Mesh74 Texture_Connector_Plate53 Texture_Connector_Plate_Mirror27 Texture_Connector_S_U\nv 31.250000 81.250000 -25.000002\nv 68.750000 81.250000 -25.000002\nv 68.750000 68.750000 -25.000004\nv 31.250000 68.750000 -25.000004\nvt 0.000000 1.000000\nf 957/943 958/943 959/943 960/943\ng Mesh490 Inner_BC_Side16 Side_BC_U\nv 25.000000 97.000008 -68.750000\nv 25.000000 97.000008 -50.000000\nv 25.000000 100.000008 -50.000000\nv 25.000000 100.000008 -68.750000\nv 50.000000 100.000015 -75.000015\nv 50.000000 97.000015 -75.000015\nv 31.250000 97.000015 -75.000015\nv 31.250000 100.000015 -75.000015\nv 31.250000 81.250000 -74.999985\nv 31.250000 90.000015 -75.000015\nv 25.000000 90.000015 -75.000015\nv 25.000000 81.250000 -74.999985\nv 31.250000 81.250000 -81.250000\nv 25.000000 81.250000 -81.250000\nv 18.750000 81.250000 -74.999985\nv 25.000000 90.000008 -68.750000\nv 18.750000 81.250000 -68.750000\nv 25.000000 81.250000 -68.750000\nv 25.000000 100.000015 -75.000015\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 961/944 962/945 963/946 964/947\nf 965/945 966/948 967/949 968/944\nf 969/950 970/951 971/952 972/953\nf 973/946 970/954 969/955\nf 971/956 970/957 973/958 974/959\nf 971/960 974/961 975/946\nf 976/962 971/956 975/959 977/963\nf 972/962 971/963 976/951 978/950\nf 976/946 977/954 978/948\nf 971/957 979/949 968/944\nf 971/957 968/944 967/964\nf 971/957 967/964 970/956\nf 961/965 964/947 979/944\nf 961/965 979/944 971/956\nf 976/962 961/965 971/956\ng Mesh81 Edge_M_S_SE\nv 81.250000 68.750000 -25.000004\nv 75.000000 68.750000 -18.750000\nv 75.000000 31.250000 -18.750000\nv 81.250000 31.250000 -25.000002\nv 68.750000 31.250000 -18.750000\nv 68.750000 68.750000 -18.750000\nv 68.750000 68.750000 -25.000004\nv 68.750000 31.250000 -25.000002\nv 75.000000 31.250000 -25.000002\nv 75.000000 68.750000 -25.000004\nv 75.000000 68.750000 -31.250000\nv 75.000000 31.250000 -31.250000\nv 81.250000 68.750000 -31.250000\nv 81.250000 31.250000 -31.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 980/966 981/967 982/968 983/969\nf 984/970 982/968 981/967 985/971\nf 986/971 987/970 984/972 985/973\nf 988/974 987/972 986/973 989/975\nf 989/976 990/977 991/978 988/979\nf 991/979 990/976 992/980 993/981\nf 980/966 983/969 993/981 992/980\ng Mesh387 Spacer19 Group6\nv 31.250000 31.250000 -25.000002\nv 31.250000 31.250000 -18.750000\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 -24.999996\nv 25.000000 18.750000 -18.750000\nv 25.000000 31.250000 -18.750000\nv 18.750000 18.750000 -24.999996\nv 18.750000 31.250000 -25.000002\nv 18.750000 31.250000 -31.250000\nv 18.750000 18.750000 -31.250000\nv 25.000000 18.750000 -31.250000\nv 25.000000 31.250000 -31.250000\nv 25.000000 18.750000 -24.999996\nv 25.000000 31.250000 -25.000002\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 994/982 995/983 996/984 997/985\nf 998/986 996/984 995/983 999/987\nf 1000/988 998/986 999/987 1001/989\nf 1001/989 1002/990 1003/991 1000/988\nf 1004/992 1003/991 1002/990 1005/993\nf 1006/994 1004/992 1005/993 1007/995\nf 1007/996 994/982 997/985 1006/997\ng Mesh103 Side_Texture_Plate_Side49 Texture_Side_W\nv 0.000000 68.750000 -24.999996\nv 0.000000 68.750000 -18.750000\nv 0.000000 31.250000 -18.750000\nv 0.000000 31.250000 -24.999998\nvt 0.000000 1.000000\nf 1008/998 1009/998 1010/998 1011/998\ng Mesh596 Texture_Connector_Plate67 Texture_Connector_Plate_Mirror34 Texture_Connector_S_W\nv 18.750000 31.250000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 31.250000 68.750000 -18.750000\nv 31.250000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 1012/999 1013/999 1014/999 1015/999\ng Mesh469 Corner_M_U_NW\nv 25.000000 68.750000 -74.999992\nv 25.000000 75.000015 -74.999985\nv 25.000000 75.000008 -68.750000\nv 25.000000 68.750000 -68.750000\nv 31.250000 68.750000 -74.999992\nv 31.250000 75.000015 -74.999985\nv 31.250000 75.000008 -68.750000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 1016/1000 1017/1001 1018/1002 1019/1003\nf 1016/1002 1020/1004 1021/1005 1017/1003\nf 1021/1004 1022/1006 1018/1007 1017/1005\ng Mesh493 Spacer15 Group5\nv 31.250000 31.250000 -74.999992\nv 31.250000 31.250000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 18.750000 31.250000 -74.999992\nv 18.750000 24.999998 -81.250000\nv 31.250000 24.999998 -81.250000\nv 18.750000 18.750000 -75.000000\nv 31.250000 18.750000 -75.000000\nv 31.250000 18.750000 -68.750000\nv 18.750000 18.750000 -68.750000\nv 18.750000 24.999996 -68.750000\nv 31.250000 24.999996 -68.750000\nv 18.750000 24.999996 -74.999992\nv 31.250000 24.999996 -74.999992\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1023/1008 1024/1009 1025/1010 1026/1011\nf 1027/1012 1025/1010 1024/1009 1028/1013\nf 1029/1014 1027/1012 1028/1013 1030/1015\nf 1030/1015 1031/1016 1032/1017 1029/1014\nf 1033/1018 1032/1017 1031/1016 1034/1019\nf 1035/1020 1033/1018 1034/1019 1036/1021\nf 1036/1022 1023/1008 1026/1011 1035/1023\ng Mesh311 Inner_BC_Side18 Side_BC_W\nv 3.000000 75.000008 -31.250000\nv 3.000000 75.000008 -50.000004\nv 0.000000 75.000008 -50.000004\nv 0.000000 75.000008 -31.250000\nv 0.000000 50.000004 -25.000000\nv 3.000000 50.000004 -25.000000\nv 3.000000 68.750000 -25.000004\nv 0.000000 68.750000 -25.000004\nv 18.750000 68.750000 -25.000004\nv 10.000000 68.750000 -25.000004\nv 10.000000 75.000008 -25.000004\nv 18.750000 75.000008 -25.000004\nv 18.750000 68.750000 -18.750000\nv 18.750000 75.000000 -18.750000\nv 18.750000 81.250000 -25.000002\nv 10.000000 75.000008 -31.250000\nv 18.750000 81.250000 -31.250000\nv 18.750000 75.000008 -31.250000\nv 0.000000 75.000008 -25.000004\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.530000\nf 1037/1024 1038/1025 1039/1026 1040/1027\nf 1041/1025 1042/1028 1043/1029 1044/1024\nf 1045/1030 1046/1031 1047/1032 1048/1033\nf 1049/1026 1046/1034 1045/1035\nf 1047/1036 1046/1037 1049/1038 1050/1039\nf 1047/1040 1050/1041 1051/1026\nf 1052/1042 1047/1036 1051/1039 1053/1043\nf 1048/1042 1047/1043 1052/1031 1054/1030\nf 1052/1026 1053/1034 1054/1028\nf 1047/1037 1055/1029 1044/1024\nf 1046/1036 1047/1037 1044/1024\nf 1046/1037 1044/1037 1043/1037\nf 1037/1044 1040/1027 1055/1024\nf 1052/1042 1037/1044 1055/1024\nf 1047/1036 1052/1042 1055/1024\ng Mesh178 Side_Texture_Plate33 Side_Texture_Plate_Mirror17 Texture_Side_S\nv 18.750000 31.250000 -18.750000\nv 18.750000 31.250000 0.000003\nv 18.750000 68.750000 0.000005\nv 18.750000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 1056/1045 1057/1045 1058/1045 1059/1045\ng Mesh129 Texture_Connector_Plate56 Texture_Connector_Plate_Mirror28 Texture_Connector_S_U\nv 68.750000 81.250000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 31.250000 68.750000 -18.750000\nv 68.750000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 1060/1046 1061/1046 1062/1046 1063/1046\ng Mesh88 Texture_Connector_Plate92 Texture_Connector_Plate_Mirror46 Texture_Connector_D_E\nv 68.750000 18.750000 -31.250000\nv 68.750000 18.750000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 1064/1047 1065/1047 1066/1047 1067/1047\ng Mesh496 Texture_Connector_Plate35 Texture_Connector_Plate_Mirror18 Texture_Connector_N_E\nv 81.250000 31.250000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 68.750000 68.750000 -81.250000\nv 68.750000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 1068/1048 1069/1048 1070/1048 1071/1048\ng Mesh501 Texture_Plate_N1\nv 68.750000 68.750000 -81.250000\nv 31.250000 68.750000 -81.250000\nv 31.250000 31.250000 -81.250000\nv 68.750000 31.250000 -81.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 1072/1049 1073/1050 1074/1051 1075/1052\ng Mesh255 Side_Texture_Plate55 Side_Texture_Plate_Mirror28 Texture_Side_W1\nv 18.750000 25.000002 -31.250000\nv 0.000000 25.000002 -31.250000\nv 0.000000 25.000004 -68.750000\nv 18.750000 25.000004 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1076/1053 1077/1054 1078/1055 1079/1056\ng Mesh164 Side_Texture_Plate_Side18 Texture_Side_E\nv 81.250000 31.250000 -24.999998\nv 81.250000 31.250000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 81.250000 68.750000 -24.999996\nvt 0.000000 1.000000\nf 1080/1057 1081/1057 1082/1057 1083/1057\ng Mesh593 Texture_Connector_Plate89 Texture_Connector_Plate_Mirror45 Texture_Connector_D_E\nv 68.750000 24.999996 -68.750000\nv 68.750000 24.999998 -31.250000\nv 81.250000 24.999998 -31.250000\nv 81.250000 24.999996 -68.750000\nvt 0.000000 1.000000\nf 1084/1058 1085/1058 1086/1058 1087/1058\ng Mesh285 Edge_M_U_E\nv 81.250000 75.000008 -68.750000\nv 75.000000 81.250000 -68.750000\nv 75.000000 81.250000 -31.250000\nv 81.250000 75.000008 -31.250000\nv 68.750000 81.250000 -31.250000\nv 68.750000 81.250000 -68.750000\nv 68.750000 75.000008 -68.750000\nv 68.750000 75.000008 -31.250000\nv 75.000000 75.000008 -31.250000\nv 75.000000 75.000008 -68.750000\nv 75.000000 68.750000 -68.750000\nv 75.000000 68.750000 -31.250000\nv 81.250000 68.750000 -68.750000\nv 81.250000 68.750000 -31.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 1088/1059 1089/1060 1090/1061 1091/1062\nf 1092/1063 1090/1061 1089/1060 1093/1064\nf 1094/1064 1095/1063 1092/1065 1093/1066\nf 1096/1067 1095/1065 1094/1066 1097/1068\nf 1097/1069 1098/1070 1099/1071 1096/1072\nf 1099/1072 1098/1069 1100/1073 1101/1074\nf 1088/1059 1091/1062 1101/1074 1100/1073\ng Mesh29 Side_Texture_Plate_Side13 Texture_Side_N3\nv 75.000000 31.250000 -99.999992\nv 81.250000 31.250000 -99.999992\nv 81.250000 68.750000 -99.999992\nv 75.000000 68.750000 -99.999992\nvt 0.000000 1.000000\nf 1102/1075 1103/1075 1104/1075 1105/1075\ng Mesh62 Texture_Connector_Plate12 Texture_Connector_Plate_Mirror6 Texture_Connector_E_U\nv 81.250000 81.250000 -68.750000\nv 81.250000 81.250000 -31.250000\nv 81.250000 68.750000 -31.250000\nv 81.250000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 1106/1076 1107/1076 1108/1076 1109/1076\ng Mesh355 Inner_BC_Side15 Side_BC_U\nv 31.250000 97.000008 -25.000000\nv 50.000000 97.000008 -25.000000\nv 50.000000 100.000008 -24.999998\nv 31.250000 100.000008 -24.999998\nv 25.000000 100.000008 -50.000000\nv 25.000000 97.000008 -50.000000\nv 25.000000 97.000008 -31.250000\nv 25.000000 100.000008 -31.250000\nv 25.000000 81.250000 -31.250000\nv 25.000000 90.000008 -31.250000\nv 25.000000 90.000008 -25.000000\nv 25.000000 81.250000 -25.000002\nv 18.750000 81.250000 -31.250000\nv 18.750000 81.250000 -25.000002\nv 25.000000 81.250000 -18.750000\nv 31.250000 90.000008 -25.000000\nv 31.250000 81.250000 -18.750000\nv 31.250000 81.250000 -25.000002\nv 25.000000 100.000008 -24.999998\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.530000\nvt 0.210000 0.580000\nf 1110/1077 1111/1078 1112/1079 1113/1080\nf 1114/1078 1115/1081 1116/1082 1117/1077\nf 1118/1083 1119/1084 1120/1085 1121/1086\nf 1122/1079 1119/1087 1118/1088\nf 1120/1089 1119/1090 1122/1091 1123/1092\nf 1120/1093 1123/1094 1124/1079\nf 1125/1095 1120/1089 1124/1092 1126/1096\nf 1121/1095 1120/1096 1125/1084 1127/1083\nf 1125/1079 1126/1087 1127/1081\nf 1120/1089 1128/1077 1117/1080\nf 1120/1089 1117/1080 1116/1097\nf 1120/1089 1116/1097 1119/1095\nf 1113/1077 1128/1082 1120/1090\nf 1110/1098 1113/1077 1120/1090\nf 1125/1089 1110/1098 1120/1090\ng Mesh318 Corner_I_U_NW\nv 31.250000 75.000008 -68.750000\nv 31.250000 81.250000 -68.750000\nv 18.750000 81.250000 -68.750000\nv 18.750000 75.000008 -68.750000\nv 31.250000 75.000015 -81.250000\nv 31.250000 81.250000 -81.250000\nv 25.000000 68.750000 -74.999992\nv 25.000000 75.000015 -74.999985\nv 18.750000 75.000015 -74.999985\nv 18.750000 68.750000 -74.999992\nv 25.000000 68.750000 -81.250000\nv 25.000000 75.000015 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 81.250000 -74.999985\nv 25.000000 81.250000 -81.250000\nv 18.750000 75.000015 -81.250000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1129/1099 1130/1100 1131/1101 1132/1102\nf 1130/1103 1129/1104 1133/1100 1134/1099\nf 1135/1105 1136/1106 1137/1107 1138/1108\nf 1136/1105 1135/1109 1139/1110 1140/1106\nf 1141/1107 1139/1111 1135/1112 1138/1108\nf 1142/1112 1143/1113 1144/1114\nf 1134/1115 1143/1116 1142/1117\nf 1130/1118 1134/1115 1142/1117\nf 1130/1118 1142/1117 1131/1110\nf 1136/1113 1140/1111 1133/1107\nf 1133/1107 1129/1115 1136/1113\nf 1132/1119 1137/1120 1136/1113\nf 1136/1113 1129/1115 1132/1119\ng Mesh363 Side_Texture_Plate4 Side_Texture_Plate_Mirror2 Texture_Side_N\nv 31.250000 75.000015 -81.250000\nv 31.250000 75.000000 -99.999985\nv 68.750000 75.000000 -99.999985\nv 68.750000 75.000015 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1145/1121 1146/1122 1147/1123 1148/1124\ng Mesh229 Side_Texture_Plate_Side63 Texture_Side_W3\nv 18.750000 75.000008 -31.250000\nv 18.750000 81.250000 -31.250000\nv 18.750000 81.250000 -68.750000\nv 18.750000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 1149/1125 1150/1125 1151/1125 1152/1125\ng Mesh351 Side_Texture_Plate5 Side_Texture_Plate_Mirror3 Texture_Side_N1\nv 18.750000 68.750000 -81.250000\nv 18.750000 68.750000 -99.999992\nv 18.750000 31.250000 -99.999992\nv 18.750000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 1153/1126 1154/1126 1155/1126 1156/1126\ng Mesh555 Mount_D_W\nv 18.750000 -0.000000 -43.750000\nv 25.000000 -0.000000 -43.750000\nv 25.000000 18.750000 -43.750000\nv 18.750000 25.000000 -43.750000\nv 18.750000 0.000001 -56.250000\nv 25.000000 0.000001 -56.250000\nv 18.750000 25.000002 -56.250000\nv 25.000000 18.750000 -56.250000\nv 18.750000 25.000000 -47.999996\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.650000 0.180000\nvt 0.860000 0.170000\nvt 0.930000 0.190000\nf 1157/1127 1158/1128 1159/1129 1160/1130\nf 1158/1131 1157/1132 1161/1133 1162/1127\nf 1163/1134 1164/1135 1162/1136 1161/1137\nf 1158/1133 1162/1136 1164/1135 1159/1138\nf 1157/1139 1160/1140 1165/1141\nf 1157/1139 1165/1141 1163/1134\nf 1157/1139 1163/1134 1161/1137\nf 1165/1142 1163/1132 1164/1131\nf 1165/1142 1164/1131 1159/1143\nf 1160/1139 1165/1142 1159/1143\ng Mesh560 Side_Texture_Plate91 Side_Texture_Plate_Mirror46 Texture_Side_D2\nv 68.750000 18.750000 -75.000000\nv 68.750000 0.000006 -75.000000\nv 31.250000 0.000006 -75.000000\nv 31.250000 18.750000 -75.000000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1166/1144 1167/1145 1168/1146 1169/1147\ng Mesh244 Edge_Side4 Side_N\nv 18.750000 25.000002 -99.999992\nv 25.000000 18.750000 -100.000000\nv 25.000000 18.750000 -81.250000\nv 18.750000 24.999998 -81.250000\nv 25.000000 25.000002 -99.999992\nv 18.750000 31.250000 -99.999992\nv 25.000000 31.250000 -99.999992\nv 25.000000 31.250000 -81.250000\nv 25.000000 24.999998 -81.250000\nv 18.750000 31.250000 -81.250000\nv 31.250000 24.999998 -81.250000\nv 31.250000 25.000002 -99.999992\nv 31.250000 18.750000 -81.250000\nv 31.250000 18.750000 -100.000000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 1170/1148 1171/1149 1172/1150 1173/1151\nf 1170/1152 1174/1153 1171/1154\nf 1170/1152 1175/1155 1176/1156 1174/1153\nf 1174/1155 1176/1156 1177/1157 1178/1158\nf 1177/1157 1176/1156 1175/1159 1179/1160\nf 1170/1148 1173/1151 1179/1161 1175/1162\nf 1178/1163 1180/1164 1181/1165 1174/1166\nf 1181/1165 1180/1164 1182/1161 1183/1162\nf 1182/1160 1172/1150 1171/1149 1183/1159\nf 1183/1167 1171/1154 1174/1153 1181/1168\ng Mesh9 Side_Texture_Plate23 Side_Texture_Plate_Mirror12 Texture_Side_E1\nv 81.250000 75.000008 -31.250000\nv 100.000000 75.000008 -31.250000\nv 100.000000 75.000008 -68.750000\nv 81.250000 75.000008 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1184/1169 1185/1170 1186/1171 1187/1172\ng Mesh607 Corner_I3_U_NW\nv 31.250000 81.250000 -81.250000\nv 31.250000 81.250000 -74.999985\nv 31.250000 75.000015 -74.999985\nv 31.250000 75.000015 -81.250000\nv 25.000000 81.250000 -74.999985\nv 25.000000 75.000015 -74.999985\nv 25.000000 81.250000 -68.750000\nv 25.000000 75.000008 -68.750000\nv 18.750000 75.000008 -68.750000\nv 18.750000 81.250000 -68.750000\nv 18.750000 75.000015 -74.999985\nv 25.000000 68.750000 -74.999992\nv 18.750000 68.750000 -74.999992\nv 25.000000 68.750000 -81.250000\nv 25.000000 75.000015 -81.250000\nv 18.750000 68.750000 -81.250000\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 1188/1173 1189/1174 1190/1175 1191/1176\nf 1192/1177 1193/1178 1190/1179 1189/1180\nf 1193/1181 1192/1180 1194/1179 1195/1182\nf 1196/1173 1195/1176 1194/1183 1197/1182\nf 1198/1182 1193/1183 1195/1184 1196/1181\nf 1199/1174 1193/1173 1198/1185 1200/1186\nf 1193/1187 1199/1186 1201/1185 1202/1188\nf 1203/1185 1201/1173 1199/1182 1200/1179\nf 1191/1185 1190/1179 1193/1178 1202/1188\ng Mesh386 Spacer24 Group7\nv 25.000000 68.750000 -31.250000\nv 18.750000 68.750000 -31.250000\nv 18.750000 81.250000 -31.250000\nv 25.000000 81.250000 -31.250000\nv 18.750000 81.250000 -25.000002\nv 18.750000 68.750000 -25.000004\nv 25.000000 81.250000 -18.750000\nv 25.000000 68.750000 -18.750000\nv 31.250000 68.750000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 31.250000 81.250000 -25.000002\nv 31.250000 68.750000 -25.000004\nv 25.000000 81.250000 -25.000002\nv 25.000000 68.750000 -25.000004\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1204/1189 1205/1190 1206/1191 1207/1192\nf 1208/1193 1206/1191 1205/1190 1209/1194\nf 1210/1195 1208/1193 1209/1194 1211/1196\nf 1211/1196 1212/1197 1213/1198 1210/1195\nf 1214/1199 1213/1198 1212/1197 1215/1200\nf 1216/1201 1214/1199 1215/1200 1217/1202\nf 1217/1203 1204/1189 1207/1192 1216/1204\ng Mesh258 Side_Texture_Plate_Side90 Texture_Side_D2\nv 68.750000 18.750000 -75.000000\nv 68.750000 18.750000 -81.250000\nv 31.250000 18.750000 -81.250000\nv 31.250000 18.750000 -75.000000\nvt 0.000000 1.000000\nf 1218/1205 1219/1205 1220/1205 1221/1205\ng Mesh192 Side_Texture_Plate27 Side_Texture_Plate_Mirror14 Texture_Side_E2\nv 81.250000 68.750000 -74.999992\nv 100.000000 68.750000 -74.999992\nv 100.000000 31.250000 -74.999992\nv 81.250000 31.250000 -74.999992\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1222/1206 1223/1207 1224/1208 1225/1209\ng Mesh377 Side_Texture_Plate21 Side_Texture_Plate_Mirror11 Texture_Side_E1\nv 81.250000 81.250000 -31.250000\nv 100.000000 81.250000 -31.250000\nv 100.000000 81.250000 -68.750000\nv 81.250000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 1226/1210 1227/1210 1228/1210 1229/1210\ng Mesh393 Corner_I3_D_NE\nv 81.250000 24.999996 -68.750000\nv 75.000000 24.999996 -68.750000\nv 75.000000 18.750000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 24.999996 -74.999992\nv 75.000000 24.999996 -74.999992\nv 81.250000 31.250000 -74.999992\nv 75.000000 31.250000 -74.999992\nv 75.000000 31.250000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 75.000000 24.999998 -81.250000\nv 68.750000 24.999998 -81.250000\nv 68.750000 24.999996 -74.999992\nv 68.750000 18.750000 -81.250000\nv 68.750000 18.750000 -75.000000\nv 75.000000 18.750000 -75.000000\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 1230/1211 1231/1212 1232/1213 1233/1214\nf 1231/1215 1230/1216 1234/1217 1235/1218\nf 1234/1219 1236/1218 1237/1217 1235/1220\nf 1238/1211 1237/1214 1236/1221 1239/1220\nf 1238/1220 1240/1221 1235/1222 1237/1219\nf 1241/1212 1242/1211 1235/1223 1240/1224\nf 1243/1225 1244/1224 1242/1223 1241/1226\nf 1242/1223 1244/1211 1245/1220 1235/1217\nf 1232/1223 1231/1217 1235/1216 1245/1226\ng Mesh42 Side_Texture_Plate_Side54 Texture_Side_W1\nv 18.750000 25.000002 -31.250000\nv 18.750000 18.750000 -31.250000\nv 18.750000 18.750000 -68.750000\nv 18.750000 25.000004 -68.750000\nvt 0.000000 1.000000\nf 1246/1227 1247/1227 1248/1227 1249/1227\ng Mesh105 Texture_Connector_Plate61 Texture_Connector_Plate_Mirror31 Texture_Connector_S_E\nv 68.750000 31.250000 -25.000002\nv 68.750000 68.750000 -25.000004\nv 81.250000 68.750000 -25.000004\nv 81.250000 31.250000 -25.000002\nvt 0.000000 1.000000\nf 1250/1228 1251/1228 1252/1228 1253/1228\ng Mesh541 Edge_Side_S_DW Side_S\nv 25.000000 18.750000 -0.000001\nv 18.750000 25.000000 0.000000\nv 18.750000 25.000004 -18.750000\nv 25.000000 18.750000 -18.750000\nv 25.000000 25.000000 0.000000\nv 31.250000 18.750000 -0.000001\nv 31.250000 25.000000 0.000000\nv 31.250000 25.000004 -18.750000\nv 25.000000 25.000004 -18.750000\nv 31.250000 18.750000 -18.750000\nv 25.000000 31.250000 -18.750000\nv 25.000000 31.250000 0.000001\nv 18.750000 31.250000 -18.750000\nv 18.750000 31.250000 0.000001\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 1254/1229 1255/1230 1256/1231 1257/1232\nf 1254/1233 1258/1234 1255/1235\nf 1254/1233 1259/1236 1260/1237 1258/1234\nf 1258/1236 1260/1237 1261/1238 1262/1239\nf 1261/1238 1260/1237 1259/1240 1263/1241\nf 1254/1229 1257/1232 1263/1242 1259/1243\nf 1262/1244 1264/1245 1265/1246 1258/1247\nf 1265/1246 1264/1245 1266/1242 1267/1243\nf 1266/1241 1256/1231 1255/1230 1267/1240\nf 1267/1248 1255/1235 1258/1234 1265/1249\ng Mesh403 Spacer9 Group4\nv 68.750000 68.750000 -74.999992\nv 68.750000 68.750000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 81.250000 68.750000 -74.999992\nv 81.250000 75.000015 -81.250000\nv 68.750000 75.000015 -81.250000\nv 81.250000 81.250000 -74.999985\nv 68.750000 81.250000 -74.999985\nv 68.750000 81.250000 -68.750000\nv 81.250000 81.250000 -68.750000\nv 81.250000 75.000008 -68.750000\nv 68.750000 75.000008 -68.750000\nv 81.250000 75.000015 -74.999985\nv 68.750000 75.000015 -74.999985\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1268/1250 1269/1251 1270/1252 1271/1253\nf 1272/1254 1270/1252 1269/1251 1273/1255\nf 1274/1256 1272/1254 1273/1255 1275/1257\nf 1275/1257 1276/1258 1277/1259 1274/1256\nf 1278/1260 1277/1259 1276/1258 1279/1261\nf 1280/1262 1278/1260 1279/1261 1281/1263\nf 1281/1264 1268/1250 1271/1253 1280/1265\ng Mesh18 Mount_S_U\nv 43.750000 81.250000 -25.000002\nv 43.750000 75.000000 -18.750000\nv 43.750000 75.000000 0.000000\nv 43.750000 81.250000 0.000001\nv 56.250000 75.000000 -18.750000\nv 56.250000 75.000000 0.000000\nv 56.250000 81.250000 0.000001\nv 56.250000 81.250000 -25.000002\nv 48.000000 81.250000 -25.000002\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.080000\nvt 0.860000 0.080000\nvt 0.860000 0.180000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.930000 0.170000\nvt 0.930000 0.190000\nf 1282/1266 1283/1267 1284/1268 1285/1269\nf 1283/1267 1286/1270 1287/1271 1284/1268\nf 1288/1272 1287/1273 1286/1274 1289/1275\nf 1285/1276 1284/1277 1287/1271 1288/1272\nf 1290/1278 1282/1279 1285/1280\nf 1289/1269 1290/1278 1285/1280\nf 1288/1266 1289/1269 1285/1280\nf 1290/1281 1282/1282 1283/1279\nf 1289/1276 1290/1281 1283/1279\nf 1286/1277 1289/1276 1283/1279\ng Mesh95 Side_Texture_Plate90 Side_Texture_Plate_Mirror45 Texture_Side_D2\nv 31.250000 18.750000 -81.250000\nv 31.250000 0.000007 -81.250000\nv 68.750000 0.000007 -81.250000\nv 68.750000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 1291/1283 1292/1283 1293/1283 1294/1283\ng Mesh337 Side_BC_S\nv 75.000000 31.250000 0.000001\nv 75.000000 50.000000 0.000000\nv 75.000000 50.000000 -3.000000\nv 75.000000 31.250000 -3.000000\nv 50.000000 25.000000 0.000000\nv 68.750000 25.000000 0.000000\nv 68.750000 25.000000 -3.000000\nv 50.000000 25.000000 -3.000000\nv 75.000000 25.000000 0.000000\nv 75.000000 31.250000 -9.999999\nv 75.000000 25.000002 -10.000000\nv 68.750000 25.000002 -10.000000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.580000 0.430000\nvt 0.250000 0.430000\nvt 0.210000 0.480000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.130000 0.430000\nvt 0.210000 0.430000\nf 1295/1284 1296/1285 1297/1286 1298/1287\nf 1299/1288 1300/1289 1301/1287 1302/1286\nf 1303/1284 1295/1287 1298/1290\nf 1303/1284 1298/1290 1304/1291\nf 1303/1284 1304/1291 1305/1292\nf 1305/1291 1306/1293 1301/1294\nf 1303/1287 1305/1291 1301/1294\nf 1301/1294 1300/1289 1303/1287\ng Mesh91 Side_BC_N\nv 68.750000 25.000002 -99.999992\nv 50.000000 25.000002 -99.999992\nv 50.000000 25.000000 -96.999992\nv 68.750000 25.000000 -96.999992\nv 75.000000 50.000000 -99.999992\nv 75.000000 31.250000 -99.999992\nv 75.000000 31.250000 -96.999992\nv 75.000000 50.000000 -96.999992\nv 75.000000 25.000002 -99.999992\nv 75.000000 25.000000 -89.999992\nv 68.750000 25.000000 -89.999992\nv 75.000000 31.250000 -89.999992\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.220000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.430000\nvt 0.130000 0.530000\nvt 0.210000 0.480000\nf 1307/1295 1308/1296 1309/1297 1310/1298\nf 1311/1297 1312/1298 1313/1299 1314/1300\nf 1315/1298 1307/1299 1310/1301\nf 1316/1302 1315/1298 1310/1301\nf 1316/1302 1310/1301 1317/1303\nf 1316/1304 1318/1302 1313/1305\nf 1313/1305 1312/1298 1316/1304\nf 1316/1304 1312/1298 1315/1295\ng Mesh451 Inner_BC_Side2 Side_BC_N\nv 75.000000 68.750000 -96.999992\nv 75.000000 50.000000 -96.999992\nv 75.000000 50.000000 -99.999992\nv 75.000000 68.750000 -99.999992\nv 50.000000 74.999985 -99.999985\nv 50.000000 74.999985 -96.999985\nv 68.750000 74.999985 -96.999985\nv 68.750000 74.999985 -99.999985\nv 68.750000 75.000015 -81.250000\nv 68.750000 74.999985 -89.999985\nv 75.000000 74.999985 -89.999985\nv 75.000000 75.000015 -81.250000\nv 68.750000 81.250000 -81.250000\nv 75.000000 81.250000 -81.250000\nv 81.250000 75.000015 -81.250000\nv 75.000000 68.750000 -89.999992\nv 81.250000 68.750000 -81.250000\nv 75.000000 68.750000 -81.250000\nv 75.000000 74.999985 -99.999985\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.220000 0.580000\nvt 0.000000 0.000000\nf 1319/1306 1320/1307 1321/1308 1322/1309\nf 1323/1307 1324/1310 1325/1311 1326/1306\nf 1327/1312 1328/1313 1329/1314 1330/1315\nf 1331/1308 1328/1316 1327/1317\nf 1329/1318 1328/1319 1331/1320 1332/1321\nf 1329/1322 1332/1323 1333/1308\nf 1334/1324 1329/1318 1333/1321 1335/1325\nf 1330/1324 1329/1325 1334/1313 1336/1312\nf 1334/1308 1335/1316 1336/1310\nf 1337/1311 1326/1306 1325/1326\nf 1329/1319 1337/1311 1325/1326\nf 1329/1319 1325/1326 1328/1318\nf 1337/1306 1329/1318 1334/1324\nf 1322/1309 1337/1306 1334/1324\nf 1334/1327 1319/1327 1322/1327\ng Mesh562 Side_Texture_Plate_Side51 Texture_Side_W\nv 18.750000 31.250000 -24.999998\nv 18.750000 31.250000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 18.750000 68.750000 -24.999996\nvt 0.000000 1.000000\nf 1338/1328 1339/1328 1340/1328 1341/1328\ng Mesh325 Side_Texture_Plate58 Side_Texture_Plate_Mirror29 Texture_Side_W2\nv 18.750000 68.750000 -81.250000\nv 0.000000 68.750000 -81.250000\nv 0.000000 31.250000 -81.250000\nv 18.750000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 1342/1329 1343/1329 1344/1329 1345/1329\ng Mesh523 Side_BC_S\nv 68.750000 75.000000 0.000000\nv 50.000000 75.000000 0.000000\nv 50.000000 75.000000 -3.000000\nv 68.750000 75.000000 -3.000000\nv 75.000000 50.000000 0.000000\nv 75.000000 68.750000 -0.000001\nv 75.000000 68.750000 -3.000000\nv 75.000000 50.000000 -3.000000\nv 68.750000 75.000000 -9.999999\nv 75.000000 75.000000 -9.999999\nv 75.000000 75.000000 0.000000\nv 75.000000 68.750000 -10.000000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.220000 0.480000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.130000 0.430000\nvt 0.000000 0.000000\nf 1346/1330 1347/1331 1348/1332 1349/1333\nf 1350/1332 1351/1333 1352/1334 1353/1335\nf 1349/1336 1354/1337 1355/1338\nf 1349/1336 1355/1338 1356/1334\nf 1346/1333 1349/1336 1356/1334\nf 1351/1330 1356/1333 1355/1337\nf 1351/1330 1355/1337 1357/1339\nf 1352/1340 1351/1340 1357/1340\ng Mesh570 Side_Texture_Plate57 Side_Texture_Plate_Mirror29 Texture_Side_W2\nv 18.750000 31.250000 -81.250000\nv 0.000000 31.250000 -81.250000\nv 0.000000 68.750000 -81.250000\nv 18.750000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 1358/1341 1359/1341 1360/1341 1361/1341\ng Mesh210 Mount_N_W\nv 18.750000 43.750000 -99.999992\nv 25.000000 43.750000 -99.999992\nv 25.000000 43.750000 -81.250000\nv 18.750000 43.750000 -74.999992\nv 18.750000 56.250000 -99.999992\nv 25.000000 56.250000 -99.999992\nv 18.750000 56.250000 -74.999992\nv 25.000000 56.250000 -81.250000\nv 18.750000 47.999996 -74.999992\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.190000\nvt 0.860000 0.190000\nvt 0.860000 0.090000\nvt 0.930000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.860000 0.000000\nvt 0.700000 0.000000\nvt 0.860000 0.140000\nvt 0.650000 0.190000\nf 1362/1342 1363/1343 1364/1344 1365/1345\nf 1363/1346 1362/1347 1366/1348 1367/1349\nf 1368/1350 1369/1351 1367/1352 1366/1353\nf 1363/1354 1367/1352 1369/1351 1364/1355\nf 1370/1356 1368/1347 1366/1357\nf 1366/1357 1362/1350 1370/1356\nf 1370/1356 1362/1350 1365/1353\nf 1370/1352 1368/1354 1369/1342\nf 1370/1352 1369/1342 1364/1349\nf 1365/1348 1370/1352 1364/1349\ng Mesh242 Corner_I_D_SW2\nv 31.250000 31.250000 -25.000002\nv 31.250000 31.250000 -18.750000\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 -24.999996\nv 18.750000 31.250000 -25.000002\nv 18.750000 31.250000 -18.750000\nv 25.000000 24.999998 -31.250000\nv 25.000000 24.999996 -25.000004\nv 25.000000 18.750000 -24.999996\nv 25.000000 18.750000 -31.250000\nv 18.750000 24.999998 -31.250000\nv 18.750000 24.999996 -25.000004\nv 18.750000 18.750000 -31.250000\nv 25.000000 18.750000 -18.750000\nv 18.750000 25.000004 -18.750000\nv 18.750000 18.750000 -24.999996\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1371/1358 1372/1359 1373/1360 1374/1361\nf 1372/1359 1371/1358 1375/1362 1376/1363\nf 1377/1364 1378/1365 1379/1366 1380/1367\nf 1378/1366 1377/1368 1381/1369 1382/1367\nf 1383/1364 1381/1370 1377/1371 1380/1365\nf 1384/1372 1385/1373 1386/1369\nf 1372/1374 1376/1375 1385/1376\nf 1373/1371 1372/1374 1385/1376\nf 1373/1371 1385/1376 1384/1377\nf 1375/1366 1371/1375 1382/1368\nf 1382/1368 1371/1375 1378/1372\nf 1378/1372 1371/1375 1374/1378\nf 1379/1379 1378/1372 1374/1378\ng Mesh307 Texture_Connector_Plate51 Texture_Connector_Plate_Mirror26 Texture_Connector_W_U\nv 18.750000 81.250000 -68.750000\nv 18.750000 81.250000 -31.250000\nv 18.750000 68.750000 -31.250000\nv 18.750000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 1387/1380 1388/1380 1389/1380 1390/1380\ng Mesh224 Group1 Side_BC_N\nv 31.250000 74.999985 -99.999985\nv 49.999992 74.999992 -99.999985\nv 49.999992 74.999992 -96.999985\nv 31.250000 74.999985 -96.999985\nv 24.999994 50.000004 -99.999992\nv 24.999992 68.750000 -99.999992\nv 24.999992 68.750000 -96.999992\nv 24.999994 50.000004 -96.999992\nv 24.999990 74.999985 -99.999985\nv 24.999990 74.999985 -89.999985\nv 31.250000 74.999985 -89.999985\nv 24.999992 68.750000 -89.999992\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.130000 0.480000\nvt 0.210000 0.430000\nvt 0.130000 0.430000\nvt 0.130000 0.530000\nvt 0.000000 0.000000\nf 1391/1381 1392/1382 1393/1383 1394/1384\nf 1395/1383 1396/1384 1397/1385 1398/1386\nf 1399/1384 1391/1385 1400/1387\nf 1400/1387 1391/1385 1394/1388\nf 1400/1387 1394/1388 1401/1389\nf 1399/1381 1400/1390 1402/1387\nf 1396/1384 1399/1381 1402/1387\nf 1396/1391 1402/1391 1397/1391\ng Mesh294 Corner_I3_D_SE\nv 68.750000 25.000004 -18.750000\nv 68.750000 24.999996 -25.000004\nv 68.750000 18.750000 -24.999996\nv 68.750000 18.750000 -18.750000\nv 75.000000 25.000004 -18.750000\nv 75.000000 24.999996 -25.000004\nv 75.000000 31.250000 -18.750000\nv 75.000000 31.250000 -25.000002\nv 81.250000 31.250000 -25.000002\nv 81.250000 31.250000 -18.750000\nv 81.250000 24.999996 -25.000004\nv 81.250000 24.999998 -31.250000\nv 75.000000 24.999998 -31.250000\nv 81.250000 18.750000 -31.250000\nv 75.000000 18.750000 -31.250000\nv 75.000000 18.750000 -24.999996\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 1403/1392 1404/1393 1405/1394 1406/1395\nf 1404/1396 1403/1397 1407/1398 1408/1399\nf 1407/1400 1409/1399 1410/1398 1408/1401\nf 1411/1392 1410/1395 1409/1402 1412/1401\nf 1411/1401 1413/1402 1408/1403 1410/1400\nf 1414/1393 1415/1392 1408/1404 1413/1405\nf 1416/1406 1417/1405 1415/1404 1414/1407\nf 1415/1404 1417/1392 1418/1401 1408/1398\nf 1405/1404 1404/1398 1408/1397 1418/1407\ng Mesh376 Side_Texture_Plate89 Side_Texture_Plate_Mirror45 Texture_Side_D2\nv 68.750000 18.750000 -81.250000\nv 68.750000 0.000007 -81.250000\nv 31.250000 0.000007 -81.250000\nv 31.250000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 1419/1408 1420/1408 1421/1408 1422/1408\ng Mesh316 Corner_I_U_SW1\nv 25.000000 68.750000 -31.250000\nv 18.750000 68.750000 -31.250000\nv 18.750000 81.250000 -31.250000\nv 25.000000 81.250000 -31.250000\nv 25.000000 68.750000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 31.250000 75.000008 -25.000004\nv 25.000000 75.000008 -25.000004\nv 25.000000 81.250000 -25.000002\nv 31.250000 81.250000 -25.000002\nv 31.250000 75.000000 -18.750000\nv 25.000000 75.000000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 18.750000 81.250000 -25.000002\nv 18.750000 75.000000 -18.750000\nv 25.000000 81.250000 -18.750000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1423/1409 1424/1410 1425/1411 1426/1412\nf 1424/1410 1423/1409 1427/1413 1428/1414\nf 1429/1415 1430/1416 1431/1417 1432/1418\nf 1430/1418 1429/1417 1433/1419 1434/1420\nf 1435/1420 1433/1419 1429/1421 1432/1422\nf 1436/1416 1437/1423 1438/1424\nf 1437/1425 1436/1426 1425/1422\nf 1437/1425 1425/1422 1424/1427\nf 1428/1428 1437/1425 1424/1427\nf 1426/1429 1431/1430 1430/1423\nf 1423/1428 1426/1429 1430/1423\nf 1430/1423 1434/1415 1427/1418\nf 1423/1428 1430/1423 1427/1418\ng Mesh417 Texture_Connector_Plate30 Texture_Connector_Plate_Mirror15 Texture_Connector_N_W\nv 31.250000 68.750000 -74.999992\nv 31.250000 31.250000 -74.999992\nv 18.750000 31.250000 -74.999992\nv 18.750000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 1439/1431 1440/1431 1441/1431 1442/1431\ng Mesh514 Spacer12 Group4\nv 68.750000 24.999996 -68.750000\nv 68.750000 18.750000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 24.999996 -68.750000\nv 81.250000 18.750000 -75.000000\nv 68.750000 18.750000 -75.000000\nv 81.250000 24.999998 -81.250000\nv 68.750000 24.999998 -81.250000\nv 68.750000 31.250000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 81.250000 31.250000 -74.999992\nv 68.750000 31.250000 -74.999992\nv 81.250000 24.999996 -74.999992\nv 68.750000 24.999996 -74.999992\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1443/1432 1444/1433 1445/1434 1446/1435\nf 1447/1436 1445/1434 1444/1433 1448/1437\nf 1449/1438 1447/1436 1448/1437 1450/1439\nf 1450/1439 1451/1440 1452/1441 1449/1438\nf 1453/1442 1452/1441 1451/1440 1454/1443\nf 1455/1444 1453/1442 1454/1443 1456/1445\nf 1456/1446 1443/1432 1446/1435 1455/1447\ng Mesh440 Texture_Connector_Plate78 Texture_Connector_Plate_Mirror39 Texture_Connector_U_S\nv 68.750000 75.000008 -31.250000\nv 31.250000 75.000008 -31.250000\nv 31.250000 75.000000 -18.750000\nv 68.750000 75.000000 -18.750000\nvt 0.000000 1.000000\nf 1457/1448 1458/1448 1459/1448 1460/1448\ng Mesh214 Side_Texture_Plate_Side38 Texture_Side_S1\nv 31.250000 75.000000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 68.750000 75.000000 -18.750000\nvt 0.000000 1.000000\nf 1461/1449 1462/1449 1463/1449 1464/1449\ng Mesh602 Corner_I_U_SE2\nv 68.750000 68.750000 -25.000004\nv 68.750000 68.750000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 68.750000 81.250000 -25.000002\nv 81.250000 68.750000 -25.000004\nv 81.250000 68.750000 -18.750000\nv 75.000000 75.000008 -31.250000\nv 75.000000 75.000008 -25.000004\nv 75.000000 81.250000 -25.000002\nv 75.000000 81.250000 -31.250000\nv 81.250000 75.000008 -31.250000\nv 81.250000 75.000008 -25.000004\nv 81.250000 81.250000 -31.250000\nv 75.000000 81.250000 -18.750000\nv 81.250000 75.000000 -18.750000\nv 81.250000 81.250000 -25.000002\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1465/1450 1466/1451 1467/1452 1468/1453\nf 1466/1451 1465/1450 1469/1454 1470/1455\nf 1471/1456 1472/1457 1473/1458 1474/1459\nf 1472/1458 1471/1460 1475/1461 1476/1459\nf 1477/1456 1475/1462 1471/1463 1474/1457\nf 1478/1464 1479/1465 1480/1461\nf 1478/1466 1467/1463 1466/1467\nf 1479/1468 1478/1466 1466/1467\nf 1470/1469 1479/1468 1466/1467\nf 1465/1469 1468/1470 1473/1471\nf 1465/1469 1473/1471 1472/1464\nf 1465/1469 1472/1464 1476/1460\nf 1465/1469 1476/1460 1469/1458\ng Mesh127 Support_U_U\nv 43.750000 81.250000 -31.250000\nv 43.750000 81.250000 -68.750000\nv 43.750000 77.000008 -68.750000\nv 43.750000 77.000008 -31.250000\nv 56.250000 81.250000 -31.250000\nv 56.250000 81.250000 -68.750000\nv 56.250000 77.000008 -31.250000\nv 56.250000 77.000008 -68.750000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 1481/1472 1482/1473 1483/1474 1484/1475\nf 1482/1476 1481/1477 1485/1478 1486/1479\nf 1486/1480 1485/1481 1487/1475 1488/1474\nf 1488/1479 1487/1478 1484/1482 1483/1483\ng Mesh113 Corner_I_U_NW2\nv 18.750000 68.750000 -74.999992\nv 18.750000 68.750000 -81.250000\nv 31.250000 68.750000 -81.250000\nv 31.250000 68.750000 -74.999992\nv 18.750000 81.250000 -74.999985\nv 25.000000 81.250000 -81.250000\nv 18.750000 75.000015 -81.250000\nv 31.250000 81.250000 -81.250000\nv 31.250000 81.250000 -74.999985\nv 25.000000 81.250000 -74.999985\nv 25.000000 81.250000 -68.750000\nv 25.000000 75.000008 -68.750000\nv 25.000000 75.000015 -74.999985\nv 18.750000 75.000008 -68.750000\nv 18.750000 81.250000 -68.750000\nv 18.750000 75.000015 -74.999985\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.330000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nf 1489/1484 1490/1485 1491/1486 1492/1487\nf 1493/1488 1494/1489 1495/1490\nf 1496/1485 1497/1484 1492/1491 1491/1492\nf 1498/1493 1499/1494 1500/1490 1501/1495\nf 1502/1496 1500/1497 1499/1498 1503/1499\nf 1502/1493 1504/1495 1501/1496 1500/1499\nf 1497/1500 1498/1501 1501/1488\nf 1492/1502 1497/1500 1501/1488\nf 1504/1494 1489/1493 1501/1488\nf 1501/1488 1489/1493 1492/1502\nf 1495/1503 1494/1504 1496/1498\nf 1495/1503 1496/1498 1491/1505\nf 1490/1502 1495/1503 1491/1505\ng Mesh117 Inner_Plate_W\nv 25.000000 68.750000 -31.250000\nv 25.000000 68.750000 -68.750000\nv 25.000000 31.250000 -68.750000\nv 25.000000 31.250000 -31.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 1505/1506 1506/1507 1507/1508 1508/1509\ng Mesh143 Support_N_S\nv 68.750000 56.250000 -81.250000\nv 31.250000 56.250000 -81.250000\nv 31.250000 56.250000 -76.999992\nv 68.750000 56.250000 -76.999992\nv 68.750000 43.750000 -81.250000\nv 31.250000 43.750000 -81.250000\nv 68.750000 43.750000 -76.999992\nv 31.250000 43.750000 -76.999992\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 1509/1510 1510/1511 1511/1512 1512/1513\nf 1510/1514 1509/1515 1513/1516 1514/1517\nf 1514/1518 1513/1519 1515/1513 1516/1512\nf 1516/1517 1515/1516 1512/1520 1511/1521\ng Mesh99 Side_Texture_Plate2 Side_Texture_Plate_Mirror1 Texture_Side_N\nv 31.250000 81.250000 -81.250000\nv 31.250000 81.250000 -99.999985\nv 68.750000 81.250000 -99.999985\nv 68.750000 81.250000 -81.250000\nvt 0.000000 1.000000\nf 1517/1522 1518/1522 1519/1522 1520/1522\ng Mesh544 Side_Texture_Plate_Side1 Texture_Side_N\nv 68.750000 75.000000 -99.999985\nv 68.750000 81.250000 -99.999985\nv 31.250000 81.250000 -99.999985\nv 31.250000 75.000000 -99.999985\nvt 0.000000 1.000000\nf 1521/1523 1522/1523 1523/1523 1524/1523\ng Mesh185 Side_Texture_Plate45 Side_Texture_Plate_Mirror23 Texture_Side_S3\nv 68.750000 18.750000 -18.750000\nv 68.750000 18.750000 0.000001\nv 31.250000 18.750000 0.000001\nv 31.250000 18.750000 -18.750000\nvt 0.000000 1.000000\nf 1525/1524 1526/1524 1527/1524 1528/1524\ng Mesh546 Texture_Connector_Plate33 Texture_Connector_Plate_Mirror17 Texture_Connector_N_E\nv 81.250000 31.250000 -74.999992\nv 81.250000 68.750000 -74.999992\nv 68.750000 68.750000 -74.999992\nv 68.750000 31.250000 -74.999992\nvt 0.000000 1.000000\nf 1529/1525 1530/1525 1531/1525 1532/1525\ng Mesh587 Side_BC_D\nv 75.000000 -0.000001 -68.750000\nv 75.000000 0.000000 -50.000000\nv 75.000000 3.000000 -50.000000\nv 75.000000 3.000000 -68.750000\nv 50.000000 0.000000 -75.000000\nv 68.750000 0.000000 -75.000000\nv 68.750000 3.000000 -75.000000\nv 50.000000 3.000000 -75.000000\nv 75.000000 10.000000 -68.750000\nv 75.000000 10.000001 -75.000000\nv 75.000000 0.000000 -75.000000\nv 68.750000 10.000001 -75.000000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.210000 0.480000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.130000 0.430000\nvt 0.210000 0.430000\nf 1533/1526 1534/1527 1535/1528 1536/1529\nf 1537/1528 1538/1529 1539/1530 1540/1531\nf 1536/1532 1541/1533 1542/1534\nf 1536/1532 1542/1534 1543/1530\nf 1533/1529 1536/1532 1543/1530\nf 1542/1533 1544/1535 1539/1536\nf 1543/1529 1542/1533 1539/1536\nf 1539/1536 1538/1526 1543/1529\ng Mesh69 Inner_Plate_D1\nv 31.250000 24.999998 -31.250000\nv 68.750000 24.999998 -31.250000\nv 68.750000 24.999996 -68.750000\nv 31.250000 24.999996 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 1545/1537 1546/1538 1547/1539 1548/1540\ng Mesh98 Side_Texture_Plate31 Side_Texture_Plate_Mirror16 Texture_Side_E3\nv 81.250000 25.000004 -68.750000\nv 100.000000 25.000004 -68.750000\nv 100.000000 25.000002 -31.250000\nv 81.250000 25.000002 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1549/1541 1550/1542 1551/1543 1552/1544\ng Mesh347 Side_Texture_Plate_Side68 Texture_Side_U\nv 25.000000 100.000008 -68.750000\nv 18.750000 100.000008 -68.750000\nv 18.750000 100.000008 -31.250000\nv 25.000000 100.000008 -31.250000\nvt 0.000000 1.000000\nf 1553/1545 1554/1545 1555/1545 1556/1545\ng Mesh384 Side_Texture_Plate_Side72 Texture_Side_U1\nv 31.250000 100.000008 -24.999990\nv 31.250000 100.000000 -18.750000\nv 68.750000 100.000000 -18.750000\nv 68.750000 100.000008 -24.999990\nvt 0.000000 1.000000\nf 1557/1546 1558/1546 1559/1546 1560/1546\ng Mesh344 Side_Texture_Plate60 Side_Texture_Plate_Mirror30 Texture_Side_W2\nv 18.750000 68.750000 -74.999992\nv 0.000000 68.750000 -74.999992\nv 0.000000 31.250000 -74.999992\nv 18.750000 31.250000 -74.999992\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1561/1547 1562/1548 1563/1549 1564/1550\ng Mesh64 Spacer22 Group7\nv 75.000000 68.750000 -68.750000\nv 81.250000 68.750000 -68.750000\nv 81.250000 81.250000 -68.750000\nv 75.000000 81.250000 -68.750000\nv 81.250000 81.250000 -74.999985\nv 81.250000 68.750000 -74.999992\nv 75.000000 81.250000 -81.250000\nv 75.000000 68.750000 -81.250000\nv 68.750000 68.750000 -81.250000\nv 68.750000 81.250000 -81.250000\nv 68.750000 81.250000 -74.999985\nv 68.750000 68.750000 -74.999992\nv 75.000000 81.250000 -74.999985\nv 75.000000 68.750000 -74.999992\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1565/1551 1566/1552 1567/1553 1568/1554\nf 1569/1555 1567/1553 1566/1552 1570/1556\nf 1571/1557 1569/1555 1570/1556 1572/1558\nf 1572/1558 1573/1559 1574/1560 1571/1557\nf 1575/1561 1574/1560 1573/1559 1576/1562\nf 1577/1563 1575/1561 1576/1562 1578/1564\nf 1578/1565 1565/1551 1568/1554 1577/1566\ng Mesh372 Side_Texture_Plate_Side22 Texture_Side_E1\nv 81.250000 75.000008 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 81.250000 -68.750000\nv 81.250000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 1579/1567 1580/1567 1581/1567 1582/1567\ng Mesh16 Edge_Side1 Side_N\nv 81.250000 74.999985 -99.999985\nv 75.000000 81.250000 -99.999985\nv 75.000000 81.250000 -81.250000\nv 81.250000 75.000015 -81.250000\nv 75.000000 74.999985 -99.999985\nv 81.250000 68.750000 -99.999992\nv 75.000000 68.750000 -99.999992\nv 75.000000 68.750000 -81.250000\nv 75.000000 75.000015 -81.250000\nv 81.250000 68.750000 -81.250000\nv 68.750000 75.000015 -81.250000\nv 68.750000 74.999985 -99.999985\nv 68.750000 81.250000 -81.250000\nv 68.750000 81.250000 -99.999985\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 1583/1568 1584/1569 1585/1570 1586/1571\nf 1583/1572 1587/1573 1584/1574\nf 1583/1572 1588/1575 1589/1576 1587/1573\nf 1587/1575 1589/1576 1590/1577 1591/1578\nf 1590/1577 1589/1576 1588/1579 1592/1580\nf 1583/1568 1586/1571 1592/1581 1588/1582\nf 1591/1583 1593/1584 1594/1585 1587/1586\nf 1594/1585 1593/1584 1595/1581 1596/1582\nf 1595/1580 1585/1570 1584/1569 1596/1579\nf 1596/1587 1584/1574 1587/1573 1594/1588\ng Mesh139 Texture_Connector_Plate87 Texture_Connector_Plate_Mirror44 Texture_Connector_D_N\nv 31.250000 18.750000 -68.750000\nv 68.750000 18.750000 -68.750000\nv 68.750000 18.750000 -81.250000\nv 31.250000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 1597/1589 1598/1589 1599/1589 1600/1589\ng Mesh295 Side_Texture_Plate_Side69 Texture_Side_U1\nv 68.750000 100.000008 -24.999990\nv 68.750000 100.000000 -18.750000\nv 31.250000 100.000000 -18.750000\nv 31.250000 100.000008 -24.999990\nvt 0.000000 1.000000\nf 1601/1590 1602/1590 1603/1590 1604/1590\ng Mesh284 Support_S_U\nv 56.250000 68.750000 -18.750000\nv 56.250000 31.250000 -18.750000\nv 56.250000 31.250000 -23.000002\nv 56.250000 68.750000 -23.000004\nv 43.750000 68.750000 -18.750000\nv 43.750000 31.250000 -18.750000\nv 43.750000 68.750000 -23.000004\nv 43.750000 31.250000 -23.000002\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 1605/1591 1606/1592 1607/1593 1608/1594\nf 1606/1595 1605/1596 1609/1597 1610/1598\nf 1610/1599 1609/1600 1611/1594 1612/1593\nf 1612/1598 1611/1597 1608/1601 1607/1602\ng Mesh275 Corner_M_U_SE\nv 81.250000 68.750000 -25.000004\nv 81.250000 68.750000 -31.250000\nv 81.250000 75.000008 -31.250000\nv 81.250000 75.000008 -25.000004\nv 75.000000 81.250000 -25.000002\nv 75.000000 81.250000 -31.250000\nv 75.000000 75.000000 -18.750000\nv 68.750000 81.250000 -25.000002\nv 68.750000 75.000000 -18.750000\nv 68.750000 68.750000 -18.750000\nv 75.000000 68.750000 -18.750000\nv 68.750000 81.250000 -31.250000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 1613/1603 1614/1604 1615/1605 1616/1606\nf 1617/1607 1616/1606 1615/1605 1618/1608\nf 1616/1609 1617/1610 1619/1611\nf 1620/1612 1621/1613 1619/1606 1617/1607\nf 1621/1613 1622/1614 1623/1603 1619/1606\nf 1623/1615 1613/1616 1616/1617 1619/1611\nf 1624/1603 1620/1614 1617/1618 1618/1619\ng Mesh434 Side_Texture_Plate74 Side_Texture_Plate_Mirror37 Texture_Side_U2\nv 68.750000 81.250000 -81.250000\nv 68.750000 100.000015 -81.250000\nv 31.250000 100.000015 -81.250000\nv 31.250000 81.250000 -81.250000\nvt 0.000000 1.000000\nf 1625/1620 1626/1620 1627/1620 1628/1620\ng Mesh515 Texture_Connector_Plate14 Texture_Connector_Plate_Mirror7 Texture_Connector_E_S\nv 75.000000 31.250000 -31.250000\nv 75.000000 68.750000 -31.250000\nv 75.000000 68.750000 -18.750000\nv 75.000000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 1629/1621 1630/1621 1631/1621 1632/1621\ng Mesh68 Texture_Connector_Plate4 Texture_Connector_Plate_Mirror2 Texture_Connector_U_N\nv 31.250000 75.000015 -81.250000\nv 68.750000 75.000015 -81.250000\nv 68.750000 75.000008 -68.750000\nv 31.250000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 1633/1622 1634/1622 1635/1622 1636/1622\ng Mesh3 Side_Texture_Plate_Side6 Texture_Side_N1\nv 25.000000 68.750000 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 25.000000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 1637/1623 1638/1623 1639/1623 1640/1623\ng Mesh504 Texture_Connector_Plate7 Texture_Connector_Plate_Mirror4 Texture_Connector_E_N\nv 81.250000 68.750000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 81.250000 31.250000 -68.750000\nv 81.250000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 1641/1624 1642/1624 1643/1624 1644/1624\ng Mesh315 Texture_Connector_Plate43 Texture_Connector_Plate_Mirror22 Texture_Connector_W_S\nv 18.750000 31.250000 -31.250000\nv 18.750000 68.750000 -31.250000\nv 18.750000 68.750000 -18.750000\nv 18.750000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 1645/1625 1646/1625 1647/1625 1648/1625\ng Mesh552 Corner_I3_D_SW\nv 18.750000 24.999998 -31.250000\nv 25.000000 24.999998 -31.250000\nv 25.000000 18.750000 -31.250000\nv 18.750000 18.750000 -31.250000\nv 18.750000 24.999996 -25.000004\nv 25.000000 24.999996 -25.000004\nv 18.750000 31.250000 -25.000002\nv 25.000000 31.250000 -25.000002\nv 25.000000 31.250000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 25.000000 25.000004 -18.750000\nv 31.250000 25.000004 -18.750000\nv 31.250000 24.999996 -25.000004\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 -24.999996\nv 25.000000 18.750000 -24.999996\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 1649/1626 1650/1627 1651/1628 1652/1629\nf 1650/1630 1649/1631 1653/1632 1654/1633\nf 1653/1634 1655/1633 1656/1632 1654/1635\nf 1657/1626 1656/1629 1655/1636 1658/1635\nf 1657/1635 1659/1636 1654/1637 1656/1634\nf 1660/1627 1661/1626 1654/1638 1659/1639\nf 1662/1640 1663/1639 1661/1638 1660/1641\nf 1661/1638 1663/1626 1664/1635 1654/1632\nf 1651/1638 1650/1632 1654/1631 1664/1641\ng Mesh236 Spacer16 Group5\nv 31.250000 24.999998 -31.250000\nv 31.250000 18.750000 -31.250000\nv 18.750000 18.750000 -31.250000\nv 18.750000 24.999998 -31.250000\nv 18.750000 18.750000 -24.999996\nv 31.250000 18.750000 -24.999996\nv 18.750000 25.000004 -18.750000\nv 31.250000 25.000004 -18.750000\nv 31.250000 31.250000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 18.750000 31.250000 -25.000002\nv 31.250000 31.250000 -25.000002\nv 18.750000 24.999996 -25.000004\nv 31.250000 24.999996 -25.000004\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1665/1642 1666/1643 1667/1644 1668/1645\nf 1669/1646 1667/1644 1666/1643 1670/1647\nf 1671/1648 1669/1646 1670/1647 1672/1649\nf 1672/1649 1673/1650 1674/1651 1671/1648\nf 1675/1652 1674/1651 1673/1650 1676/1653\nf 1677/1654 1675/1652 1676/1653 1678/1655\nf 1678/1656 1665/1642 1668/1645 1677/1657\ng Mesh12 Spacer17 Group6\nv 68.750000 31.250000 -74.999992\nv 68.750000 31.250000 -81.250000\nv 68.750000 18.750000 -81.250000\nv 68.750000 18.750000 -75.000000\nv 75.000000 18.750000 -81.250000\nv 75.000000 31.250000 -81.250000\nv 81.250000 18.750000 -75.000000\nv 81.250000 31.250000 -74.999992\nv 81.250000 31.250000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 75.000000 18.750000 -68.750000\nv 75.000000 31.250000 -68.750000\nv 75.000000 18.750000 -75.000000\nv 75.000000 31.250000 -74.999992\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1679/1658 1680/1659 1681/1660 1682/1661\nf 1683/1662 1681/1660 1680/1659 1684/1663\nf 1685/1664 1683/1662 1684/1663 1686/1665\nf 1686/1665 1687/1666 1688/1667 1685/1664\nf 1689/1668 1688/1667 1687/1666 1690/1669\nf 1691/1670 1689/1668 1690/1669 1692/1671\nf 1692/1672 1679/1658 1682/1661 1691/1673\ng Mesh2 Side_Texture_Plate40 Side_Texture_Plate_Mirror20 Texture_Side_S1\nv 68.750000 75.000000 -18.750000\nv 68.750000 75.000000 0.000006\nv 31.250000 75.000000 0.000006\nv 31.250000 75.000000 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1693/1674 1694/1675 1695/1676 1696/1677\ng Mesh479 Texture_Connector_Plate15 Texture_Connector_Plate_Mirror8 Texture_Connector_E_S\nv 81.250000 68.750000 -31.250000\nv 81.250000 31.250000 -31.250000\nv 81.250000 31.250000 -18.750000\nv 81.250000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 1697/1678 1698/1678 1699/1678 1700/1678\ng Mesh489 Texture_Plate_W1\nv 18.750000 68.750000 -68.750000\nv 18.750000 68.750000 -31.250000\nv 18.750000 31.250000 -31.250000\nv 18.750000 31.250000 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 1701/1679 1702/1680 1703/1681 1704/1682\ng Mesh487 Spacer20 Group6\nv 25.000000 31.250000 -68.750000\nv 18.750000 31.250000 -68.750000\nv 18.750000 18.750000 -68.750000\nv 25.000000 18.750000 -68.750000\nv 18.750000 18.750000 -75.000000\nv 18.750000 31.250000 -74.999992\nv 25.000000 18.750000 -81.250000\nv 25.000000 31.250000 -81.250000\nv 31.250000 31.250000 -81.250000\nv 31.250000 18.750000 -81.250000\nv 31.250000 18.750000 -75.000000\nv 31.250000 31.250000 -74.999992\nv 25.000000 18.750000 -75.000000\nv 25.000000 31.250000 -74.999992\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1705/1683 1706/1684 1707/1685 1708/1686\nf 1709/1687 1707/1685 1706/1684 1710/1688\nf 1711/1689 1709/1687 1710/1688 1712/1690\nf 1712/1690 1713/1691 1714/1692 1711/1689\nf 1715/1693 1714/1692 1713/1691 1716/1694\nf 1717/1695 1715/1693 1716/1694 1718/1696\nf 1718/1697 1705/1683 1708/1686 1717/1698\ng Mesh334 Texture_Connector_Plate76 Texture_Connector_Plate_Mirror38 Texture_Connector_U_E\nv 68.750000 81.250000 -68.750000\nv 68.750000 81.250000 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 1719/1699 1720/1699 1721/1699 1722/1699\ng Mesh341 Side_BC_W\nv 0.000000 68.750000 -74.999992\nv 0.000000 49.999996 -74.999992\nv 3.000000 49.999996 -74.999992\nv 3.000000 68.750000 -74.999992\nv 0.000000 75.000008 -50.000004\nv 0.000000 75.000008 -68.750000\nv 3.000000 75.000008 -68.750000\nv 3.000000 75.000008 -50.000004\nv 0.000000 75.000015 -74.999985\nv 10.000000 75.000015 -74.999985\nv 10.000000 68.750000 -74.999992\nv 10.000000 75.000008 -68.750000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.130000 0.480000\nvt 0.130000 0.430000\nvt 0.000000 0.000000\nvt 0.130000 0.530000\nf 1723/1700 1724/1701 1725/1702 1726/1703\nf 1727/1704 1728/1705 1729/1703 1730/1702\nf 1731/1703 1723/1700 1732/1706\nf 1732/1706 1723/1700 1733/1707\nf 1733/1708 1723/1708 1726/1708\nf 1728/1703 1731/1705 1732/1709\nf 1728/1703 1732/1709 1734/1706\nf 1729/1708 1728/1708 1734/1708\ng Mesh395 Side_Texture_Plate_Side96 Texture_Side_D3\nv 75.000000 0.000005 -68.750000\nv 81.250000 0.000005 -68.750000\nv 81.250000 0.000003 -31.250000\nv 75.000000 0.000003 -31.250000\nvt 0.000000 1.000000\nf 1735/1710 1736/1710 1737/1710 1738/1710\ng Mesh184 Side_Texture_Plate96 Side_Texture_Plate_Mirror48 Texture_Side_D3\nv 75.000000 18.750000 -68.750000\nv 75.000000 0.000005 -68.750000\nv 75.000000 0.000003 -31.250000\nv 75.000000 18.750000 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1739/1711 1740/1712 1741/1713 1742/1714\ng Mesh589 Corner_I3_D_SE\nv 81.250000 25.000004 -18.750000\nv 75.000000 18.750000 -18.750000\nv 81.250000 18.750000 -24.999996\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 1743/1715 1744/1716 1745/1717\ng Mesh361 Corner_I_U_SE1\nv 75.000000 81.250000 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 68.750000 -31.250000\nv 75.000000 68.750000 -31.250000\nv 75.000000 81.250000 -18.750000\nv 81.250000 75.000000 -18.750000\nv 81.250000 81.250000 -25.000002\nv 81.250000 68.750000 -18.750000\nv 75.000000 68.750000 -18.750000\nv 75.000000 75.000000 -18.750000\nv 68.750000 75.000000 -18.750000\nv 68.750000 75.000008 -25.000004\nv 75.000000 75.000008 -25.000004\nv 68.750000 81.250000 -25.000002\nv 68.750000 81.250000 -18.750000\nv 75.000000 81.250000 -25.000002\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nf 1746/1718 1747/1719 1748/1720 1749/1721\nf 1750/1722 1751/1723 1752/1724\nf 1753/1721 1754/1720 1749/1725 1748/1726\nf 1755/1727 1756/1728 1757/1729 1758/1724\nf 1759/1730 1757/1731 1756/1732 1760/1733\nf 1759/1728 1761/1727 1758/1730 1757/1733\nf 1761/1729 1746/1728 1758/1722\nf 1758/1722 1746/1728 1749/1734\nf 1754/1735 1755/1736 1758/1722\nf 1754/1735 1758/1722 1749/1734\nf 1747/1734 1752/1737 1751/1738\nf 1748/1739 1747/1734 1751/1738\nf 1748/1739 1751/1738 1753/1732\ng Mesh533 Side_Texture_Plate_Side57 Texture_Side_W2\nv 0.000000 31.250000 -74.999992\nv 0.000000 31.250000 -81.250000\nv 0.000000 68.750000 -81.250000\nv 0.000000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 1762/1740 1763/1740 1764/1740 1765/1740\ng Mesh191 Side_Texture_Plate_Side71 Texture_Side_U1\nv 31.250000 81.250000 -24.999994\nv 31.250000 81.250000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 68.750000 81.250000 -24.999994\nvt 0.000000 1.000000\nf 1766/1741 1767/1741 1768/1741 1769/1741\ng Mesh150 Corner_I_D_SE2\nv 68.750000 31.250000 -25.000002\nv 68.750000 31.250000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 81.250000 31.250000 -25.000002\nv 68.750000 18.750000 -24.999996\nv 68.750000 18.750000 -18.750000\nv 75.000000 24.999998 -31.250000\nv 75.000000 24.999996 -25.000004\nv 81.250000 24.999996 -25.000004\nv 81.250000 24.999998 -31.250000\nv 75.000000 18.750000 -31.250000\nv 75.000000 18.750000 -24.999996\nv 81.250000 18.750000 -31.250000\nv 81.250000 25.000004 -18.750000\nv 75.000000 18.750000 -18.750000\nv 81.250000 18.750000 -24.999996\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.750000 0.390000\nvt 0.690000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1770/1742 1771/1743 1772/1744 1773/1745\nf 1771/1743 1770/1742 1774/1746 1775/1747\nf 1776/1748 1777/1749 1778/1750 1779/1751\nf 1777/1750 1776/1752 1780/1753 1781/1751\nf 1782/1748 1780/1754 1776/1755 1779/1749\nf 1783/1756 1784/1757 1785/1753\nf 1772/1755 1771/1758 1775/1759\nf 1783/1760 1772/1755 1775/1759\nf 1784/1761 1783/1760 1775/1759\nf 1774/1750 1770/1759 1777/1756\nf 1777/1756 1770/1759 1773/1762\nf 1777/1756 1773/1762 1778/1763\nf 1774/1750 1777/1756 1781/1752\ng Mesh371 Side_Texture_Plate3 Side_Texture_Plate_Mirror2 Texture_Side_N\nv 68.750000 75.000015 -81.250000\nv 68.750000 75.000000 -99.999985\nv 31.250000 75.000000 -99.999985\nv 31.250000 75.000015 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1786/1764 1787/1765 1788/1766 1789/1767\ng Mesh359 Inner_BC_Side5 Side_BC_E\nv 97.000000 68.750000 -25.000004\nv 97.000000 50.000004 -25.000000\nv 100.000000 50.000004 -25.000000\nv 100.000000 68.750000 -25.000004\nv 100.000000 75.000008 -50.000004\nv 97.000000 75.000008 -50.000004\nv 97.000000 75.000008 -31.250000\nv 100.000000 75.000008 -31.250000\nv 81.250000 75.000008 -31.250000\nv 90.000000 75.000008 -31.250000\nv 90.000000 75.000008 -25.000004\nv 81.250000 75.000008 -25.000004\nv 81.250000 81.250000 -31.250000\nv 81.250000 81.250000 -25.000002\nv 81.250000 75.000000 -18.750000\nv 90.000000 68.750000 -25.000004\nv 81.250000 68.750000 -18.750000\nv 81.250000 68.750000 -25.000004\nv 100.000000 75.000008 -25.000004\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.530000\nf 1790/1768 1791/1769 1792/1770 1793/1771\nf 1794/1769 1795/1772 1796/1773 1797/1768\nf 1798/1774 1799/1775 1800/1776 1801/1777\nf 1802/1770 1799/1778 1798/1779\nf 1800/1780 1799/1781 1802/1782 1803/1783\nf 1800/1784 1803/1785 1804/1770\nf 1805/1786 1800/1780 1804/1783 1806/1787\nf 1801/1786 1800/1787 1805/1775 1807/1774\nf 1805/1770 1806/1778 1807/1772\nf 1796/1788 1799/1786 1800/1780\nf 1797/1771 1796/1788 1800/1780\nf 1808/1768 1797/1771 1800/1780\nf 1808/1773 1800/1781 1805/1780\nf 1793/1768 1808/1773 1805/1780\nf 1805/1781 1790/1781 1793/1781\ng Mesh412 Corner_I_U_SW2\nv 31.250000 68.750000 -25.000004\nv 31.250000 68.750000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 18.750000 68.750000 -25.000004\nv 31.250000 81.250000 -25.000002\nv 31.250000 81.250000 -18.750000\nv 25.000000 75.000008 -31.250000\nv 25.000000 75.000008 -25.000004\nv 18.750000 75.000008 -25.000004\nv 18.750000 75.000008 -31.250000\nv 25.000000 81.250000 -31.250000\nv 25.000000 81.250000 -25.000002\nv 18.750000 81.250000 -31.250000\nv 18.750000 75.000000 -18.750000\nv 25.000000 81.250000 -18.750000\nv 18.750000 81.250000 -25.000002\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1809/1789 1810/1790 1811/1791 1812/1792\nf 1810/1790 1809/1789 1813/1793 1814/1794\nf 1815/1795 1816/1796 1817/1797 1818/1798\nf 1816/1797 1815/1799 1819/1800 1820/1798\nf 1821/1795 1819/1801 1815/1802 1818/1796\nf 1822/1803 1823/1804 1824/1800\nf 1814/1805 1823/1806 1822/1807\nf 1810/1808 1814/1805 1822/1807\nf 1810/1808 1822/1807 1811/1802\nf 1816/1803 1820/1799 1813/1797\nf 1813/1797 1809/1805 1816/1803\nf 1812/1809 1817/1810 1816/1803\nf 1816/1803 1809/1805 1812/1809\ng Mesh486 Texture_Connector_Plate6 Texture_Connector_Plate_Mirror3 Texture_Connector_E_N\nv 75.000000 31.250000 -81.250000\nv 75.000000 68.750000 -81.250000\nv 75.000000 68.750000 -68.750000\nv 75.000000 31.250000 -68.750000\nvt 0.000000 1.000000\nf 1825/1811 1826/1811 1827/1811 1828/1811\ng Mesh416 Texture_Connector_Plate41 Texture_Connector_Plate_Mirror21 Texture_Connector_W_S\nv 25.000000 31.250000 -31.250000\nv 25.000000 68.750000 -31.250000\nv 25.000000 68.750000 -18.750000\nv 25.000000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 1829/1812 1830/1812 1831/1812 1832/1812\ng Mesh19 Corner_I_U_SW\nv 31.250000 75.000008 -31.250000\nv 31.250000 81.250000 -31.250000\nv 31.250000 81.250000 -18.750000\nv 31.250000 75.000000 -18.750000\nv 18.750000 75.000008 -31.250000\nv 18.750000 81.250000 -31.250000\nv 25.000000 68.750000 -25.000004\nv 25.000000 75.000008 -25.000004\nv 25.000000 75.000000 -18.750000\nv 25.000000 68.750000 -18.750000\nv 18.750000 68.750000 -25.000004\nv 18.750000 75.000008 -25.000004\nv 18.750000 68.750000 -18.750000\nv 25.000000 81.250000 -18.750000\nv 18.750000 81.250000 -25.000002\nv 18.750000 75.000000 -18.750000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.750000 0.330000\nvt 0.800000 0.330000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 1833/1813 1834/1814 1835/1815 1836/1816\nf 1834/1817 1833/1818 1837/1814 1838/1813\nf 1839/1819 1840/1820 1841/1821 1842/1822\nf 1840/1819 1839/1823 1843/1824 1844/1820\nf 1845/1821 1843/1825 1839/1826 1842/1822\nf 1846/1826 1847/1827 1848/1828\nf 1834/1829 1838/1830 1847/1831\nf 1835/1824 1834/1829 1847/1831\nf 1835/1824 1847/1831 1846/1832\nf 1837/1821 1833/1830 1844/1825\nf 1844/1825 1833/1830 1840/1827\nf 1840/1827 1833/1830 1836/1833\nf 1841/1834 1840/1827 1836/1833\ng Mesh186 Side_Texture_Plate_Side61 Texture_Side_W3\nv 0.000000 75.000008 -68.750000\nv 0.000000 81.250000 -68.750000\nv 0.000000 81.250000 -31.250000\nv 0.000000 75.000008 -31.250000\nvt 0.000000 1.000000\nf 1849/1835 1850/1835 1851/1835 1852/1835\ng Mesh556 Inner_BC_Side21 Side_BC_D\nv 31.250000 3.000000 -75.000000\nv 50.000000 3.000000 -75.000000\nv 50.000000 0.000000 -75.000000\nv 31.250000 0.000000 -75.000000\nv 25.000000 0.000000 -50.000000\nv 25.000000 3.000000 -50.000000\nv 25.000000 3.000000 -68.750000\nv 25.000000 -0.000001 -68.750000\nv 25.000000 18.750000 -68.750000\nv 25.000000 10.000000 -68.750000\nv 25.000000 10.000001 -75.000000\nv 25.000000 18.750000 -75.000000\nv 18.750000 18.750000 -68.750000\nv 18.750000 18.750000 -75.000000\nv 25.000000 18.750000 -81.250000\nv 31.250000 10.000001 -75.000000\nv 31.250000 18.750000 -81.250000\nv 31.250000 18.750000 -75.000000\nv 25.000000 0.000000 -75.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.530000\nvt 0.210000 0.580000\nf 1853/1836 1854/1837 1855/1838 1856/1839\nf 1857/1837 1858/1840 1859/1841 1860/1836\nf 1861/1842 1862/1843 1863/1844 1864/1845\nf 1865/1838 1862/1846 1861/1847\nf 1863/1848 1862/1849 1865/1850 1866/1851\nf 1863/1852 1866/1853 1867/1838\nf 1868/1854 1863/1848 1867/1851 1869/1855\nf 1864/1854 1863/1855 1868/1843 1870/1842\nf 1868/1838 1869/1846 1870/1840\nf 1859/1856 1862/1854 1863/1848\nf 1859/1856 1863/1848 1871/1836\nf 1860/1839 1859/1856 1871/1836\nf 1871/1841 1863/1849 1868/1848\nf 1868/1848 1853/1857 1871/1841\nf 1871/1841 1853/1857 1856/1836\ng Mesh154 Texture_Connector_Plate80 Texture_Connector_Plate_Mirror40 Texture_Connector_U_S\nv 68.750000 81.250000 -31.250000\nv 31.250000 81.250000 -31.250000\nv 31.250000 81.250000 -18.750000\nv 68.750000 81.250000 -18.750000\nvt 0.000000 1.000000\nf 1872/1858 1873/1858 1874/1858 1875/1858\ng Mesh464 Side_Texture_Plate_Side12 Texture_Side_N2\nv 68.750000 25.000010 -99.999992\nv 68.750000 18.750000 -100.000000\nv 31.250000 18.750000 -100.000000\nv 31.250000 25.000010 -99.999992\nvt 0.000000 1.000000\nf 1876/1859 1877/1859 1878/1859 1879/1859\ng Mesh50 Texture_Connector_Plate19 Texture_Connector_Plate_Mirror10 Texture_Connector_E_D\nv 81.250000 31.250000 -31.250000\nv 81.250000 31.250000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 1880/1860 1881/1860 1882/1860 1883/1860\ng Mesh460 Side_Texture_Plate35 Side_Texture_Plate_Mirror18 Texture_Side_S\nv 25.000000 31.250000 -18.750000\nv 25.000000 31.250000 0.000003\nv 25.000000 68.750000 0.000005\nv 25.000000 68.750000 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1884/1861 1885/1862 1886/1863 1887/1864\ng Mesh190 Side_Texture_Plate_Side42 Texture_Side_S2\nv 75.000000 68.750000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 75.000000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 1888/1865 1889/1865 1890/1865 1891/1865\ng Mesh51 Side_BC_D\nv 31.250000 0.000000 -75.000000\nv 50.000000 0.000000 -75.000000\nv 50.000000 3.000000 -75.000000\nv 31.250000 3.000000 -75.000000\nv 25.000000 0.000000 -50.000000\nv 25.000000 -0.000001 -68.750000\nv 25.000000 3.000000 -68.750000\nv 25.000000 3.000000 -50.000000\nv 31.250000 10.000001 -75.000000\nv 25.000000 10.000001 -75.000000\nv 25.000000 0.000000 -75.000000\nv 25.000000 10.000000 -68.750000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.130000 0.430000\nvt 0.130000 0.480000\nvt 0.210000 0.430000\nvt 0.130000 0.530000\nvt 0.210000 0.480000\nf 1892/1866 1893/1867 1894/1868 1895/1869\nf 1896/1868 1897/1869 1898/1870 1899/1871\nf 1900/1872 1901/1873 1902/1869\nf 1895/1874 1900/1872 1902/1869\nf 1892/1866 1895/1874 1902/1869\nf 1901/1875 1903/1873 1898/1876\nf 1902/1870 1901/1875 1898/1876\nf 1898/1876 1897/1869 1902/1870\ng Mesh424 Side_Texture_Plate_Side47 Texture_Side_S3\nv 31.250000 25.000004 -18.750000\nv 31.250000 18.750000 -18.750000\nv 68.750000 18.750000 -18.750000\nv 68.750000 25.000004 -18.750000\nvt 0.000000 1.000000\nf 1904/1877 1905/1877 1906/1877 1907/1877\ng Mesh522 Corner_M_D_SE\nv 81.250000 24.999998 -31.250000\nv 81.250000 31.250000 -31.250000\nv 81.250000 31.250000 -25.000002\nv 81.250000 24.999996 -25.000004\nv 75.000000 25.000004 -18.750000\nv 75.000000 31.250000 -18.750000\nv 75.000000 18.750000 -24.999996\nv 68.750000 25.000004 -18.750000\nv 68.750000 18.750000 -24.999996\nv 68.750000 18.750000 -31.250000\nv 75.000000 18.750000 -31.250000\nv 68.750000 31.250000 -18.750000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 1908/1878 1909/1879 1910/1880 1911/1881\nf 1912/1882 1911/1881 1910/1880 1913/1883\nf 1911/1884 1912/1885 1914/1886\nf 1915/1887 1916/1888 1914/1881 1912/1882\nf 1916/1888 1917/1889 1918/1878 1914/1881\nf 1918/1890 1908/1891 1911/1892 1914/1886\nf 1919/1878 1915/1889 1912/1893 1913/1894\ng Mesh10 Side_Texture_Plate63 Side_Texture_Plate_Mirror32 Texture_Side_W3\nv 18.750000 75.000008 -68.750000\nv 0.000000 75.000008 -68.750000\nv 0.000000 75.000008 -31.250000\nv 18.750000 75.000008 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1920/1895 1921/1896 1922/1897 1923/1898\ng Mesh276 Side_BC_W\nv 0.000000 31.250000 -25.000002\nv 0.000000 50.000004 -25.000000\nv 3.000000 50.000004 -25.000000\nv 3.000000 31.250000 -25.000002\nv 0.000000 25.000000 -49.999996\nv 0.000000 24.999998 -31.250000\nv 3.000000 24.999998 -31.250000\nv 3.000000 25.000000 -49.999996\nv 0.000000 24.999996 -25.000004\nv 10.000000 31.250000 -25.000002\nv 10.000000 24.999996 -25.000004\nv 10.000000 24.999998 -31.250000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.210000 0.430000\nvt 0.130000 0.430000\nvt 0.130000 0.480000\nvt 0.210000 0.480000\nvt 0.130000 0.530000\nf 1924/1899 1925/1900 1926/1901 1927/1902\nf 1928/1903 1929/1904 1930/1902 1931/1901\nf 1932/1902 1924/1899 1927/1905\nf 1932/1902 1927/1905 1933/1906\nf 1932/1902 1933/1906 1934/1907\nf 1930/1908 1929/1902 1932/1904\nf 1935/1907 1930/1908 1932/1904\nf 1934/1909 1935/1907 1932/1904\ng Mesh203 Mount_D_E\nv 81.250000 0.000001 -56.250000\nv 75.000000 0.000001 -56.250000\nv 75.000000 18.750000 -56.250000\nv 81.250000 25.000002 -56.250000\nv 81.250000 -0.000000 -43.750000\nv 75.000000 -0.000000 -43.750000\nv 81.250000 25.000000 -43.750000\nv 75.000000 18.750000 -43.750000\nv 81.250000 25.000000 -51.999996\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.080000\nvt 0.860000 0.080000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.140000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.930000 0.110000\nvt 0.930000 0.190000\nf 1936/1910 1937/1911 1938/1912 1939/1913\nf 1937/1914 1936/1910 1940/1915 1941/1916\nf 1942/1917 1943/1918 1941/1919 1940/1920\nf 1937/1914 1941/1919 1943/1918 1938/1921\nf 1944/1922 1942/1923 1940/1924\nf 1939/1920 1944/1922 1940/1924\nf 1936/1917 1939/1920 1940/1924\nf 1943/1923 1938/1916 1939/1915\nf 1943/1923 1939/1915 1944/1925\nf 1943/1923 1944/1925 1942/1926\ng Mesh183 Side_Texture_Plate39 Side_Texture_Plate_Mirror20 Texture_Side_S1\nv 31.250000 75.000000 -18.750000\nv 31.250000 75.000000 0.000006\nv 68.750000 75.000000 0.000006\nv 68.750000 75.000000 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1945/1927 1946/1928 1947/1929 1948/1930\ng Mesh582 Side_Texture_Plate64 Side_Texture_Plate_Mirror32 Texture_Side_W3\nv 18.750000 75.000008 -31.250000\nv 0.000000 75.000008 -31.250000\nv 0.000000 75.000008 -68.750000\nv 18.750000 75.000008 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 1949/1931 1950/1932 1951/1933 1952/1934\ng Mesh22 Texture_Connector_Plate10 Texture_Connector_Plate_Mirror5 Texture_Connector_E_U\nv 75.000000 81.250000 -68.750000\nv 75.000000 81.250000 -31.250000\nv 75.000000 68.750000 -31.250000\nv 75.000000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 1953/1935 1954/1935 1955/1935 1956/1935\ng Mesh547 Edge_Side_S_DN Side_E\nv 100.000000 24.999998 -81.250000\nv 100.000000 18.750000 -75.000000\nv 81.250000 18.750000 -75.000000\nv 81.250000 24.999998 -81.250000\nv 100.000000 24.999996 -74.999992\nv 100.000000 31.250000 -81.250000\nv 100.000000 31.250000 -74.999992\nv 81.250000 31.250000 -74.999992\nv 81.250000 24.999996 -74.999992\nv 81.250000 31.250000 -81.250000\nv 81.250000 24.999996 -68.750000\nv 100.000000 24.999996 -68.750000\nv 81.250000 18.750000 -68.750000\nv 100.000000 18.750000 -68.750000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 1957/1936 1958/1937 1959/1938 1960/1939\nf 1957/1940 1961/1941 1958/1942\nf 1957/1940 1962/1943 1963/1944 1961/1941\nf 1961/1943 1963/1944 1964/1945 1965/1946\nf 1964/1945 1963/1944 1962/1947 1966/1948\nf 1957/1936 1960/1939 1966/1949 1962/1950\nf 1965/1951 1967/1952 1968/1953 1961/1954\nf 1968/1953 1967/1952 1969/1949 1970/1950\nf 1969/1948 1959/1938 1958/1937 1970/1947\nf 1970/1955 1958/1942 1961/1941 1968/1956\ng Mesh313 Edge_M_U_S\nv 68.750000 75.000000 -18.750000\nv 68.750000 81.250000 -25.000002\nv 31.250000 81.250000 -25.000002\nv 31.250000 75.000000 -18.750000\nv 31.250000 81.250000 -31.250000\nv 68.750000 81.250000 -31.250000\nv 68.750000 75.000008 -31.250000\nv 31.250000 75.000008 -31.250000\nv 31.250000 75.000008 -25.000004\nv 68.750000 75.000008 -25.000004\nv 68.750000 68.750000 -25.000004\nv 31.250000 68.750000 -25.000004\nv 68.750000 68.750000 -18.750000\nv 31.250000 68.750000 -18.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 1971/1957 1972/1958 1973/1959 1974/1960\nf 1975/1961 1973/1959 1972/1958 1976/1962\nf 1977/1962 1978/1961 1975/1963 1976/1964\nf 1979/1965 1978/1963 1977/1964 1980/1966\nf 1980/1967 1981/1968 1982/1969 1979/1970\nf 1982/1970 1981/1967 1983/1971 1984/1972\nf 1971/1957 1974/1960 1984/1972 1983/1971\ng Mesh343 Texture_Connector_Plate13 Texture_Connector_Plate_Mirror7 Texture_Connector_E_S\nv 75.000000 68.750000 -31.250000\nv 75.000000 31.250000 -31.250000\nv 75.000000 31.250000 -18.750000\nv 75.000000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 1985/1973 1986/1973 1987/1973 1988/1973\ng Mesh11 Inner_Plate_U1\nv 68.750000 75.000008 -31.250000\nv 31.250000 75.000008 -31.250000\nv 31.250000 75.000008 -68.750000\nv 68.750000 75.000008 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 1989/1974 1990/1975 1991/1976 1992/1977\ng Mesh296 Side_Texture_Plate17 Side_Texture_Plate_Mirror9 Texture_Side_E\nv 81.250000 31.250000 -18.750000\nv 100.000000 31.250000 -18.750000\nv 100.000000 68.750000 -18.750000\nv 81.250000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 1993/1978 1994/1978 1995/1978 1996/1978\ng Mesh112 Spacer7 Group3\nv 25.000000 31.250000 -31.250000\nv 18.750000 31.250000 -31.250000\nv 18.750000 31.250000 -18.750000\nv 25.000000 31.250000 -18.750000\nv 18.750000 25.000004 -18.750000\nv 18.750000 24.999998 -31.250000\nv 25.000000 18.750000 -18.750000\nv 25.000000 18.750000 -31.250000\nv 31.250000 18.750000 -31.250000\nv 31.250000 18.750000 -18.750000\nv 31.250000 25.000004 -18.750000\nv 31.250000 24.999998 -31.250000\nv 25.000000 25.000004 -18.750000\nv 25.000000 24.999998 -31.250000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 1997/1979 1998/1980 1999/1981 2000/1982\nf 2001/1983 1999/1981 1998/1980 2002/1984\nf 2003/1985 2001/1983 2002/1984 2004/1986\nf 2004/1986 2005/1987 2006/1988 2003/1985\nf 2007/1989 2006/1988 2005/1987 2008/1990\nf 2009/1991 2007/1989 2008/1990 2010/1992\nf 2010/1993 1997/1979 2000/1982 2009/1994\ng Mesh600 Inner_Plate_N1\nv 68.750000 68.750000 -74.999992\nv 31.250000 68.750000 -74.999992\nv 31.250000 31.250000 -74.999992\nv 68.750000 31.250000 -74.999992\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2011/1995 2012/1996 2013/1997 2014/1998\ng Mesh75 Texture_Connector_Plate54 Texture_Connector_Plate_Mirror27 Texture_Connector_S_U\nv 68.750000 81.250000 -25.000002\nv 31.250000 81.250000 -25.000002\nv 31.250000 68.750000 -25.000004\nv 68.750000 68.750000 -25.000004\nvt 0.000000 1.000000\nf 2015/1999 2016/1999 2017/1999 2018/1999\ng Mesh373 Texture_Connector_Plate52 Texture_Connector_Plate_Mirror26 Texture_Connector_W_U\nv 18.750000 81.250000 -31.250000\nv 18.750000 81.250000 -68.750000\nv 18.750000 68.750000 -68.750000\nv 18.750000 68.750000 -31.250000\nvt 0.000000 1.000000\nf 2019/2000 2020/2000 2021/2000 2022/2000\ng Mesh415 Inner_BC_Side13 Side_BC_U\nv 68.750000 97.000015 -75.000015\nv 50.000000 97.000015 -75.000015\nv 50.000000 100.000015 -75.000015\nv 68.750000 100.000015 -75.000015\nv 75.000000 100.000008 -50.000000\nv 75.000000 97.000008 -50.000000\nv 75.000000 97.000008 -68.750000\nv 75.000000 100.000008 -68.750000\nv 75.000000 81.250000 -68.750000\nv 75.000000 90.000008 -68.750000\nv 75.000000 90.000015 -75.000015\nv 75.000000 81.250000 -74.999985\nv 81.250000 81.250000 -68.750000\nv 81.250000 81.250000 -74.999985\nv 75.000000 81.250000 -81.250000\nv 68.750000 90.000015 -75.000015\nv 68.750000 81.250000 -81.250000\nv 68.750000 81.250000 -74.999985\nv 75.000000 100.000015 -75.000015\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 2023/2001 2024/2002 2025/2003 2026/2004\nf 2027/2002 2028/2005 2029/2006 2030/2001\nf 2031/2007 2032/2008 2033/2009 2034/2010\nf 2035/2003 2032/2011 2031/2012\nf 2033/2013 2032/2014 2035/2015 2036/2016\nf 2033/2017 2036/2018 2037/2003\nf 2038/2019 2033/2013 2037/2016 2039/2020\nf 2034/2019 2033/2020 2038/2008 2040/2007\nf 2038/2003 2039/2011 2040/2005\nf 2041/2006 2030/2001 2029/2021\nf 2033/2014 2041/2006 2029/2021\nf 2033/2014 2029/2021 2032/2013\nf 2023/2022 2026/2004 2041/2001\nf 2023/2022 2041/2001 2033/2013\nf 2038/2019 2023/2022 2033/2013\ng Mesh330 Side_Texture_Plate47 Side_Texture_Plate_Mirror24 Texture_Side_S3\nv 68.750000 25.000004 -18.750000\nv 68.750000 25.000000 0.000002\nv 31.250000 25.000000 0.000002\nv 31.250000 25.000004 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2042/2023 2043/2024 2044/2025 2045/2026\ng Mesh280 Texture_Plate_D\nv 31.250000 18.750000 -68.750000\nv 68.750000 18.750000 -68.750000\nv 68.750000 18.750000 -31.250000\nv 31.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2046/2027 2047/2028 2048/2029 2049/2030\ng Mesh423 Side_Texture_Plate_Side76 Texture_Side_U2\nv 68.750000 100.000015 -75.000000\nv 68.750000 100.000015 -81.250000\nv 31.250000 100.000015 -81.250000\nv 31.250000 100.000015 -75.000000\nvt 0.000000 1.000000\nf 2050/2031 2051/2031 2052/2031 2053/2031\ng Mesh437 Side_Texture_Plate16 Side_Texture_Plate_Mirror8 Texture_Side_N3\nv 75.000000 68.750000 -81.250000\nv 75.000000 68.750000 -99.999992\nv 75.000000 31.250000 -99.999992\nv 75.000000 31.250000 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2054/2032 2055/2033 2056/2034 2057/2035\ng Mesh506 Spacer6 Group3\nv 31.250000 75.000008 -31.250000\nv 31.250000 81.250000 -31.250000\nv 31.250000 81.250000 -18.750000\nv 31.250000 75.000000 -18.750000\nv 25.000000 81.250000 -18.750000\nv 25.000000 81.250000 -31.250000\nv 18.750000 75.000000 -18.750000\nv 18.750000 75.000008 -31.250000\nv 18.750000 68.750000 -31.250000\nv 18.750000 68.750000 -18.750000\nv 25.000000 68.750000 -18.750000\nv 25.000000 68.750000 -31.250000\nv 25.000000 75.000000 -18.750000\nv 25.000000 75.000008 -31.250000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 2058/2036 2059/2037 2060/2038 2061/2039\nf 2062/2040 2060/2038 2059/2037 2063/2041\nf 2064/2042 2062/2040 2063/2041 2065/2043\nf 2065/2043 2066/2044 2067/2045 2064/2042\nf 2068/2046 2067/2045 2066/2044 2069/2047\nf 2070/2048 2068/2046 2069/2047 2071/2049\nf 2071/2050 2058/2036 2061/2039 2070/2051\ng Mesh338 Mount_E_N\nv 100.000000 43.750000 -81.250000\nv 100.000000 43.750000 -74.999992\nv 81.250000 43.750000 -74.999992\nv 75.000000 43.750000 -81.250000\nv 100.000000 56.250000 -81.250000\nv 100.000000 56.250000 -74.999992\nv 75.000000 56.250000 -81.250000\nv 81.250000 56.250000 -74.999992\nv 75.000000 47.999996 -81.250000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.140000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.860000 0.160000\nvt 0.930000 0.180000\nvt 0.860000 0.180000\nf 2072/2052 2073/2053 2074/2054 2075/2055\nf 2073/2056 2072/2057 2076/2058 2077/2052\nf 2078/2059 2079/2060 2077/2061 2076/2062\nf 2073/2060 2077/2063 2079/2058 2074/2061\nf 2080/2064 2078/2065 2076/2066\nf 2076/2066 2072/2059 2080/2064\nf 2080/2064 2072/2059 2075/2062\nf 2080/2067 2078/2057 2079/2056\nf 2080/2067 2079/2056 2074/2068\nf 2075/2069 2080/2067 2074/2068\ng Mesh27 Side_Texture_Plate83 Side_Texture_Plate_Mirror42 Texture_Side_D\nv 25.000000 18.750000 -68.750000\nv 25.000000 0.000005 -68.750000\nv 25.000000 0.000003 -31.250000\nv 25.000000 18.750000 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2081/2070 2082/2071 2083/2072 2084/2073\ng Mesh362 Side_Texture_Plate6 Side_Texture_Plate_Mirror3 Texture_Side_N1\nv 18.750000 31.250000 -81.250000\nv 18.750000 31.250000 -99.999992\nv 18.750000 68.750000 -99.999992\nv 18.750000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 2085/2074 2086/2074 2087/2074 2088/2074\ng Mesh21 Texture_Connector_Plate79 Texture_Connector_Plate_Mirror40 Texture_Connector_U_S\nv 31.250000 81.250000 -31.250000\nv 68.750000 81.250000 -31.250000\nv 68.750000 81.250000 -18.750000\nv 31.250000 81.250000 -18.750000\nvt 0.000000 1.000000\nf 2089/2075 2090/2075 2091/2075 2092/2075\ng Mesh528 Edge_Side3 Side_N\nv 75.000000 18.750000 -100.000000\nv 81.250000 25.000002 -99.999992\nv 81.250000 24.999998 -81.250000\nv 75.000000 18.750000 -81.250000\nv 75.000000 25.000002 -99.999992\nv 68.750000 18.750000 -100.000000\nv 68.750000 25.000002 -99.999992\nv 68.750000 24.999998 -81.250000\nv 75.000000 24.999998 -81.250000\nv 68.750000 18.750000 -81.250000\nv 75.000000 31.250000 -81.250000\nv 75.000000 31.250000 -99.999992\nv 81.250000 31.250000 -81.250000\nv 81.250000 31.250000 -99.999992\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 2093/2076 2094/2077 2095/2078 2096/2079\nf 2093/2080 2097/2081 2094/2082\nf 2093/2080 2098/2083 2099/2084 2097/2081\nf 2097/2083 2099/2084 2100/2085 2101/2086\nf 2100/2085 2099/2084 2098/2087 2102/2088\nf 2093/2076 2096/2079 2102/2089 2098/2090\nf 2101/2091 2103/2092 2104/2093 2097/2094\nf 2104/2093 2103/2092 2105/2089 2106/2090\nf 2105/2088 2095/2078 2094/2077 2106/2087\nf 2106/2095 2094/2082 2097/2081 2104/2096\ng Mesh102 Side_Texture_Plate_Side95 Texture_Side_D3\nv 75.000000 18.750000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 18.750000 -31.250000\nv 75.000000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 2107/2097 2108/2097 2109/2097 2110/2097\ng Mesh94 Texture_Connector_Plate26 Texture_Connector_Plate_Mirror13 Texture_Connector_N_U\nv 31.250000 81.250000 -74.999985\nv 68.750000 81.250000 -74.999985\nv 68.750000 68.750000 -74.999992\nv 31.250000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 2111/2098 2112/2098 2113/2098 2114/2098\ng Mesh231 Mount_W_U\nv 25.000000 81.250000 -56.250000\nv 18.750000 75.000008 -56.250000\nv 0.000000 75.000008 -56.250000\nv 0.000000 81.250000 -56.250000\nv 18.750000 75.000008 -43.750000\nv 0.000000 75.000008 -43.750000\nv 0.000000 81.250000 -43.750000\nv 25.000000 81.250000 -43.750000\nv 25.000000 81.250000 -52.000004\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.860000 0.000000\nvt 0.700000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.110000\nvt 0.860000 0.110000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.860000 0.180000\nvt 0.930000 0.190000\nvt 0.860000 0.130000\nf 2115/2099 2116/2100 2117/2101 2118/2102\nf 2116/2103 2119/2101 2120/2100 2117/2104\nf 2121/2105 2120/2106 2119/2107 2122/2108\nf 2118/2103 2117/2105 2120/2109 2121/2110\nf 2115/2111 2118/2112 2121/2099\nf 2123/2113 2115/2111 2121/2099\nf 2122/2102 2123/2113 2121/2099\nf 2115/2110 2116/2109 2119/2114\nf 2123/2115 2115/2110 2119/2114\nf 2122/2111 2123/2115 2119/2114\ng Mesh592 Texture_Connector_Plate36 Texture_Connector_Plate_Mirror18 Texture_Connector_N_E\nv 81.250000 68.750000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 68.750000 31.250000 -81.250000\nv 68.750000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 2124/2116 2125/2116 2126/2116 2127/2116\ng Mesh263 Side_Texture_Plate93 Side_Texture_Plate_Mirror47 Texture_Side_D3\nv 81.250000 18.750000 -31.250000\nv 81.250000 0.000003 -31.250000\nv 81.250000 0.000005 -68.750000\nv 81.250000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 2128/2117 2129/2117 2130/2117 2131/2117\ng Mesh202 Texture_Connector_Plate2 Texture_Connector_Plate_Mirror1 Texture_Connector_U_N\nv 31.250000 81.250000 -81.250000\nv 68.750000 81.250000 -81.250000\nv 68.750000 81.250000 -68.750000\nv 31.250000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 2132/2118 2133/2118 2134/2118 2135/2118\ng Mesh565 Side_Texture_Plate_Side27 Texture_Side_E2\nv 81.250000 31.250000 -74.999992\nv 81.250000 31.250000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 81.250000 68.750000 -74.999992\nvt 0.000000 1.000000\nf 2136/2119 2137/2119 2138/2119 2139/2119\ng Mesh195 Side_Texture_Plate_Side7 Texture_Side_N1\nv 25.000000 31.250000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 18.750000 68.750000 -81.250000\nv 25.000000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 2140/2120 2141/2120 2142/2120 2143/2120\ng Mesh381 Side_BC_E\nv 100.000000 31.250000 -74.999992\nv 100.000000 49.999996 -74.999992\nv 97.000000 49.999996 -74.999992\nv 97.000000 31.250000 -74.999992\nv 100.000000 25.000000 -49.999996\nv 100.000000 24.999996 -68.750000\nv 97.000000 24.999996 -68.750000\nv 97.000000 25.000000 -49.999996\nv 90.000000 31.250000 -74.999992\nv 90.000000 24.999996 -74.999992\nv 100.000000 24.999996 -74.999992\nv 90.000000 24.999996 -68.750000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.220000 0.480000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.130000 0.430000\nvt 0.000000 0.000000\nf 2144/2121 2145/2122 2146/2123 2147/2124\nf 2148/2123 2149/2124 2150/2125 2151/2126\nf 2147/2127 2152/2128 2153/2129\nf 2144/2124 2147/2127 2153/2129\nf 2154/2125 2144/2124 2153/2129\nf 2154/2124 2153/2128 2155/2130\nf 2149/2121 2154/2124 2155/2130\nf 2149/2131 2155/2131 2150/2131\ng Mesh267 Side_Texture_Plate14 Side_Texture_Plate_Mirror7 Texture_Side_N3\nv 81.250000 68.750000 -81.250000\nv 81.250000 68.750000 -99.999992\nv 81.250000 31.250000 -99.999992\nv 81.250000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 2156/2132 2157/2132 2158/2132 2159/2132\ng Mesh93 Texture_Connector_Plate68 Texture_Connector_Plate_Mirror34 Texture_Connector_S_W\nv 18.750000 68.750000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 31.250000 31.250000 -18.750000\nv 31.250000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 2160/2133 2161/2133 2162/2133 2163/2133\ng Mesh161 Side_Texture_Plate70 Side_Texture_Plate_Mirror35 Texture_Side_U1\nv 31.250000 81.250000 -18.750000\nv 31.250000 100.000000 -18.750000\nv 68.750000 100.000000 -18.750000\nv 68.750000 81.250000 -18.750000\nvt 0.000000 1.000000\nf 2164/2134 2165/2134 2166/2134 2167/2134\ng Mesh243 Texture_Connector_Plate64 Texture_Connector_Plate_Mirror32 Texture_Connector_S_E\nv 68.750000 68.750000 -18.750000\nv 68.750000 31.250000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 81.250000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 2168/2135 2169/2135 2170/2135 2171/2135\ng Mesh261 Side_Texture_Plate41 Side_Texture_Plate_Mirror21 Texture_Side_S2\nv 81.250000 68.750000 -18.750000\nv 81.250000 68.750000 0.000005\nv 81.250000 31.250000 0.000003\nv 81.250000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 2172/2136 2173/2136 2174/2136 2175/2136\ng Mesh353 Side_Texture_Plate_Side93 Texture_Side_D3\nv 75.000000 0.000003 -31.250000\nv 81.250000 0.000003 -31.250000\nv 81.250000 0.000005 -68.750000\nv 75.000000 0.000005 -68.750000\nvt 0.000000 1.000000\nf 2176/2137 2177/2137 2178/2137 2179/2137\ng Mesh287 Texture_Connector_Plate20 Texture_Connector_Plate_Mirror10 Texture_Connector_E_D\nv 81.250000 31.250000 -68.750000\nv 81.250000 31.250000 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 2180/2138 2181/2138 2182/2138 2183/2138\ng Mesh189 Side_Texture_Plate_Side73 Texture_Side_U2\nv 31.250000 100.000015 -75.000000\nv 31.250000 100.000015 -81.250000\nv 68.750000 100.000015 -81.250000\nv 68.750000 100.000015 -75.000000\nvt 0.000000 1.000000\nf 2184/2139 2185/2139 2186/2139 2187/2139\ng Mesh368 Support_U_S\nv 68.750000 81.250000 -43.750000\nv 31.250000 81.250000 -43.750000\nv 31.250000 77.000008 -43.750000\nv 68.750000 77.000008 -43.750000\nv 68.750000 81.250000 -56.250000\nv 31.250000 81.250000 -56.250000\nv 68.750000 77.000008 -56.250000\nv 31.250000 77.000008 -56.250000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 2188/2140 2189/2141 2190/2142 2191/2143\nf 2189/2144 2188/2145 2192/2146 2193/2147\nf 2193/2148 2192/2149 2194/2143 2195/2142\nf 2195/2147 2194/2146 2191/2150 2190/2151\ng Mesh40 Side_Texture_Plate_Side32 Texture_Side_E3\nv 100.000000 25.000002 -31.250000\nv 100.000000 18.750000 -31.250000\nv 100.000000 18.750000 -68.750000\nv 100.000000 25.000004 -68.750000\nvt 0.000000 1.000000\nf 2196/2152 2197/2152 2198/2152 2199/2152\ng Mesh321 Inner_Plate_U\nv 31.250000 75.000008 -31.250000\nv 68.750000 75.000008 -31.250000\nv 68.750000 75.000008 -68.750000\nv 31.250000 75.000008 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2200/2153 2201/2154 2202/2155 2203/2156\ng Mesh530 Support_W_S\nv 18.750000 56.250000 -68.750000\nv 18.750000 56.250000 -31.250000\nv 23.000000 56.250000 -31.250000\nv 23.000000 56.250000 -68.750000\nv 18.750000 43.750000 -68.750000\nv 18.750000 43.750000 -31.250000\nv 23.000000 43.750000 -68.750000\nv 23.000000 43.750000 -31.250000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 2204/2157 2205/2158 2206/2159 2207/2160\nf 2205/2161 2204/2162 2208/2163 2209/2164\nf 2209/2165 2208/2166 2210/2160 2211/2159\nf 2211/2164 2210/2163 2207/2167 2206/2168\ng Mesh5 Side_Texture_Plate44 Side_Texture_Plate_Mirror22 Texture_Side_S2\nv 75.000000 31.250000 -18.750000\nv 75.000000 31.250000 0.000003\nv 75.000000 68.750000 0.000005\nv 75.000000 68.750000 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2212/2169 2213/2170 2214/2171 2215/2172\ng Mesh34 Side_Texture_Plate_Side16 Texture_Side_N3\nv 75.000000 68.750000 -99.999992\nv 81.250000 68.750000 -99.999992\nv 81.250000 31.250000 -99.999992\nv 75.000000 31.250000 -99.999992\nvt 0.000000 1.000000\nf 2216/2173 2217/2173 2218/2173 2219/2173\ng Mesh171 Texture_Connector_Plate86 Texture_Connector_Plate_Mirror43 Texture_Connector_D_N\nv 68.750000 24.999996 -68.750000\nv 31.250000 24.999996 -68.750000\nv 31.250000 24.999998 -81.250000\nv 68.750000 24.999998 -81.250000\nvt 0.000000 1.000000\nf 2220/2174 2221/2174 2222/2174 2223/2174\ng Mesh90 Side_D1 Side_D\nv 75.000000 18.750000 -81.250000\nv 81.250000 18.750000 -75.000000\nv 81.250000 0.000000 -75.000000\nv 75.000000 0.000001 -81.250000\nv 81.250000 -0.000001 -68.750000\nv 81.250000 18.750000 -68.750000\nv 75.000000 -0.000001 -68.750000\nv 75.000000 0.000000 -75.000000\nv 75.000000 18.750000 -68.750000\nv 75.000000 18.750000 -75.000000\nv 68.750000 18.750000 -75.000000\nv 68.750000 0.000000 -75.000000\nv 68.750000 18.750000 -81.250000\nv 68.750000 0.000001 -81.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.650000 0.850000\nvt 0.650000 0.780000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.650000 0.950000\nvt 0.700000 0.950000\nvt 0.700000 1.000000\nvt 0.650000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.950000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.650000 0.630000\nvt 0.650000 0.680000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.750000 0.900000\nvt 0.750000 0.950000\nvt 0.700000 0.900000\nf 2224/2175 2225/2176 2226/2177 2227/2178\nf 2228/2179 2226/2177 2225/2176 2229/2180\nf 2230/2181 2231/2182 2226/2183 2228/2184\nf 2231/2181 2230/2184 2232/2185 2233/2186\nf 2228/2179 2229/2180 2232/2186 2230/2181\nf 2233/2187 2234/2188 2235/2189 2231/2190\nf 2236/2191 2237/2192 2235/2190 2234/2187\nf 2224/2175 2227/2178 2237/2192 2236/2191\nf 2237/2193 2227/2194 2231/2182 2235/2195\nf 2226/2183 2231/2182 2227/2194\ng Mesh542 Side_Texture_Plate_Side30 Texture_Side_E3\nv 81.250000 25.000004 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 18.750000 -31.250000\nv 81.250000 25.000002 -31.250000\nvt 0.000000 1.000000\nf 2238/2196 2239/2196 2240/2196 2241/2196\ng Mesh43 Side_Texture_Plate9 Side_Texture_Plate_Mirror5 Texture_Side_N2\nv 31.250000 18.750000 -81.250000\nv 31.250000 18.750000 -100.000000\nv 68.750000 18.750000 -100.000000\nv 68.750000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 2242/2197 2243/2197 2244/2197 2245/2197\ng Mesh532 Inner_BC_Side9 Side_BC_S\nv 25.000000 68.750000 -3.000000\nv 25.000000 50.000000 -3.000000\nv 25.000000 50.000000 0.000000\nv 25.000000 68.750000 -0.000001\nv 50.000000 75.000000 0.000000\nv 50.000000 75.000000 -3.000000\nv 31.250000 75.000000 -3.000000\nv 31.250000 75.000000 0.000000\nv 31.250000 75.000000 -18.750000\nv 31.250000 75.000000 -9.999999\nv 25.000000 75.000000 -9.999999\nv 25.000000 75.000000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 25.000000 81.250000 -18.750000\nv 18.750000 75.000000 -18.750000\nv 25.000000 68.750000 -10.000000\nv 18.750000 68.750000 -18.750000\nv 25.000000 68.750000 -18.750000\nv 25.000000 75.000000 0.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.130000 0.640000\nf 2246/2198 2247/2199 2248/2200 2249/2201\nf 2250/2199 2251/2202 2252/2203 2253/2198\nf 2254/2204 2255/2205 2256/2206 2257/2207\nf 2258/2200 2255/2208 2254/2209\nf 2256/2210 2255/2211 2258/2212 2259/2213\nf 2256/2214 2259/2215 2260/2200\nf 2261/2216 2256/2210 2260/2213 2262/2217\nf 2257/2216 2256/2217 2261/2205 2263/2204\nf 2261/2200 2262/2208 2263/2202\nf 2255/2210 2256/2211 2264/2203\nf 2252/2218 2255/2210 2264/2203\nf 2253/2198 2252/2218 2264/2203\nf 2249/2201 2264/2198 2256/2210\nf 2249/2201 2256/2210 2261/2216\nf 2246/2219 2249/2219 2261/2219\ng Mesh536 Corner_I3_U_NE\nv 81.250000 81.250000 -68.750000\nv 75.000000 81.250000 -68.750000\nv 75.000000 75.000008 -68.750000\nv 81.250000 75.000008 -68.750000\nv 75.000000 81.250000 -74.999985\nv 75.000000 75.000015 -74.999985\nv 68.750000 81.250000 -74.999985\nv 68.750000 75.000015 -74.999985\nv 68.750000 75.000015 -81.250000\nv 68.750000 81.250000 -81.250000\nv 75.000000 75.000015 -81.250000\nv 75.000000 68.750000 -74.999992\nv 75.000000 68.750000 -81.250000\nv 81.250000 68.750000 -74.999992\nv 81.250000 75.000015 -74.999985\nv 81.250000 68.750000 -81.250000\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 2265/2220 2266/2221 2267/2222 2268/2223\nf 2269/2224 2270/2225 2267/2226 2266/2227\nf 2270/2228 2269/2227 2271/2226 2272/2229\nf 2273/2220 2272/2223 2271/2230 2274/2229\nf 2275/2229 2270/2230 2272/2231 2273/2228\nf 2276/2221 2270/2220 2275/2232 2277/2233\nf 2270/2234 2276/2233 2278/2232 2279/2235\nf 2280/2232 2278/2220 2276/2229 2277/2226\nf 2268/2232 2267/2226 2270/2225 2279/2235\ng Mesh601 Corner_I3_U_SE\nv 81.250000 81.250000 -25.000002\nv 75.000000 81.250000 -18.750000\nv 81.250000 75.000000 -18.750000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 2281/2236 2282/2237 2283/2238\ng Mesh194 Side_Texture_Plate_Side26 Texture_Side_E2\nv 81.250000 68.750000 -74.999992\nv 81.250000 68.750000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 81.250000 31.250000 -74.999992\nvt 0.000000 1.000000\nf 2284/2239 2285/2239 2286/2239 2287/2239\ng Mesh509 Side_BC_D\nv 68.750000 0.000000 -25.000000\nv 50.000000 0.000000 -25.000000\nv 50.000000 3.000000 -25.000000\nv 68.750000 3.000000 -25.000000\nv 75.000000 0.000000 -50.000000\nv 75.000000 0.000001 -31.250000\nv 75.000000 3.000000 -31.250000\nv 75.000000 3.000000 -50.000000\nv 68.750000 10.000000 -24.999998\nv 75.000000 10.000000 -24.999998\nv 75.000000 0.000000 -25.000000\nv 75.000000 10.000001 -31.250000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.210000 0.480000\nvt 0.130000 0.480000\nvt 0.130000 0.530000\nvt 0.130000 0.430000\nvt 0.210000 0.430000\nf 2288/2240 2289/2241 2290/2242 2291/2243\nf 2292/2242 2293/2243 2294/2244 2295/2245\nf 2291/2246 2296/2247 2297/2248\nf 2291/2246 2297/2248 2298/2244\nf 2288/2243 2291/2246 2298/2244\nf 2298/2243 2297/2247 2299/2249\nf 2298/2243 2299/2249 2294/2250\nf 2294/2250 2293/2240 2298/2243\ng Mesh174 Inner_BC_Side7 Side_BC_E\nv 97.000000 31.250000 -74.999992\nv 97.000000 49.999996 -74.999992\nv 100.000000 49.999996 -74.999992\nv 100.000000 31.250000 -74.999992\nv 100.000000 25.000000 -49.999996\nv 97.000000 25.000000 -49.999996\nv 97.000000 24.999996 -68.750000\nv 100.000000 24.999996 -68.750000\nv 81.250000 24.999996 -68.750000\nv 90.000000 24.999996 -68.750000\nv 90.000000 24.999996 -74.999992\nv 81.250000 24.999996 -74.999992\nv 81.250000 18.750000 -68.750000\nv 81.250000 18.750000 -75.000000\nv 81.250000 24.999998 -81.250000\nv 90.000000 31.250000 -74.999992\nv 81.250000 31.250000 -81.250000\nv 81.250000 31.250000 -74.999992\nv 100.000000 24.999996 -74.999992\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nf 2300/2251 2301/2252 2302/2253 2303/2254\nf 2304/2252 2305/2255 2306/2256 2307/2251\nf 2308/2257 2309/2258 2310/2259 2311/2260\nf 2312/2253 2309/2261 2308/2262\nf 2310/2263 2309/2264 2312/2265 2313/2266\nf 2310/2267 2313/2268 2314/2253\nf 2315/2269 2310/2263 2314/2266 2316/2270\nf 2311/2269 2310/2270 2315/2258 2317/2257\nf 2315/2253 2316/2261 2317/2255\nf 2309/2269 2310/2263 2318/2251\nf 2309/2269 2318/2251 2307/2254\nf 2306/2254 2309/2269 2307/2254\nf 2315/2263 2300/2271 2310/2264\nf 2310/2264 2300/2271 2303/2251\nf 2310/2264 2303/2251 2318/2256\ng Mesh383 Side_Texture_Plate_Side55 Texture_Side_W1\nv 18.750000 25.000004 -68.750000\nv 18.750000 18.750000 -68.750000\nv 18.750000 18.750000 -31.250000\nv 18.750000 25.000002 -31.250000\nvt 0.000000 1.000000\nf 2319/2272 2320/2272 2321/2272 2322/2272\ng Mesh510 Edge_Side2 Side_N\nv 25.000000 81.250000 -99.999985\nv 18.750000 74.999985 -99.999985\nv 18.750000 75.000015 -81.250000\nv 25.000000 81.250000 -81.250000\nv 25.000000 74.999985 -99.999985\nv 31.250000 81.250000 -99.999985\nv 31.250000 74.999985 -99.999985\nv 31.250000 75.000015 -81.250000\nv 25.000000 75.000015 -81.250000\nv 31.250000 81.250000 -81.250000\nv 25.000000 68.750000 -81.250000\nv 25.000000 68.750000 -99.999992\nv 18.750000 68.750000 -81.250000\nv 18.750000 68.750000 -99.999992\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 2323/2273 2324/2274 2325/2275 2326/2276\nf 2323/2277 2327/2278 2324/2279\nf 2323/2277 2328/2280 2329/2281 2327/2278\nf 2327/2280 2329/2281 2330/2282 2331/2283\nf 2330/2282 2329/2281 2328/2284 2332/2285\nf 2323/2273 2326/2276 2332/2286 2328/2287\nf 2331/2288 2333/2289 2334/2290 2327/2291\nf 2334/2290 2333/2289 2335/2286 2336/2287\nf 2335/2285 2325/2275 2324/2274 2336/2284\nf 2336/2292 2324/2279 2327/2278 2334/2293\ng Mesh104 Side_Texture_Plate8 Side_Texture_Plate_Mirror4 Texture_Side_N1\nv 25.000000 31.250000 -81.250000\nv 25.000000 31.250000 -99.999992\nv 25.000000 68.750000 -99.999992\nv 25.000000 68.750000 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2337/2294 2338/2295 2339/2296 2340/2297\ng Mesh398 Inner_Plate_S\nv 68.750000 68.750000 -25.000004\nv 31.250000 68.750000 -25.000004\nv 31.250000 31.250000 -25.000002\nv 68.750000 31.250000 -25.000002\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2341/2298 2342/2299 2343/2300 2344/2301\ng Mesh312 Texture_Connector_Plate69 Texture_Connector_Plate_Mirror35 Texture_Connector_U_W\nv 18.750000 75.000008 -31.250000\nv 18.750000 75.000008 -68.750000\nv 31.250000 75.000008 -68.750000\nv 31.250000 75.000008 -31.250000\nvt 0.000000 1.000000\nf 2345/2302 2346/2302 2347/2302 2348/2302\ng Mesh453 Corner_M_D_SW\nv 31.250000 25.000004 -18.750000\nv 31.250000 31.250000 -18.750000\nv 25.000000 31.250000 -18.750000\nv 25.000000 25.000004 -18.750000\nv 18.750000 24.999996 -25.000004\nv 18.750000 31.250000 -25.000002\nv 25.000000 18.750000 -24.999996\nv 18.750000 24.999998 -31.250000\nv 25.000000 18.750000 -31.250000\nv 31.250000 18.750000 -31.250000\nv 31.250000 18.750000 -24.999996\nv 18.750000 31.250000 -31.250000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 2349/2303 2350/2304 2351/2305 2352/2306\nf 2353/2307 2352/2306 2351/2305 2354/2308\nf 2352/2309 2353/2310 2355/2311\nf 2356/2312 2357/2313 2355/2306 2353/2307\nf 2357/2313 2358/2314 2359/2303 2355/2306\nf 2359/2315 2349/2316 2352/2317 2355/2311\nf 2360/2303 2356/2314 2353/2318 2354/2319\ng Mesh410 Texture_Connector_Plate85 Texture_Connector_Plate_Mirror43 Texture_Connector_D_N\nv 31.250000 24.999996 -68.750000\nv 68.750000 24.999996 -68.750000\nv 68.750000 24.999998 -81.250000\nv 31.250000 24.999998 -81.250000\nvt 0.000000 1.000000\nf 2361/2320 2362/2320 2363/2320 2364/2320\ng Mesh250 Texture_Connector_Plate77 Texture_Connector_Plate_Mirror39 Texture_Connector_U_S\nv 31.250000 75.000008 -31.250000\nv 68.750000 75.000008 -31.250000\nv 68.750000 75.000000 -18.750000\nv 31.250000 75.000000 -18.750000\nvt 0.000000 1.000000\nf 2365/2321 2366/2321 2367/2321 2368/2321\ng Mesh282 Corner_I3_U_SE\nv 68.750000 81.250000 -18.750000\nv 68.750000 81.250000 -25.000002\nv 68.750000 75.000008 -25.000004\nv 68.750000 75.000000 -18.750000\nv 75.000000 81.250000 -25.000002\nv 75.000000 75.000008 -25.000004\nv 75.000000 81.250000 -31.250000\nv 75.000000 75.000008 -31.250000\nv 81.250000 75.000008 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 75.000008 -25.000004\nv 75.000000 68.750000 -25.000004\nv 81.250000 68.750000 -25.000004\nv 75.000000 68.750000 -18.750000\nv 75.000000 75.000000 -18.750000\nv 81.250000 68.750000 -18.750000\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 2369/2322 2370/2323 2371/2324 2372/2325\nf 2373/2326 2374/2327 2371/2328 2370/2329\nf 2374/2330 2373/2329 2375/2328 2376/2331\nf 2377/2322 2376/2325 2375/2332 2378/2331\nf 2379/2331 2374/2332 2376/2333 2377/2330\nf 2380/2323 2374/2322 2379/2334 2381/2335\nf 2374/2336 2380/2335 2382/2334 2383/2337\nf 2384/2334 2382/2322 2380/2331 2381/2328\nf 2372/2334 2371/2328 2374/2327 2383/2337\ng Mesh317 Corner_I3_D_NW\nv 31.250000 24.999998 -81.250000\nv 31.250000 24.999996 -74.999992\nv 31.250000 18.750000 -75.000000\nv 31.250000 18.750000 -81.250000\nv 25.000000 24.999998 -81.250000\nv 25.000000 24.999996 -74.999992\nv 25.000000 31.250000 -81.250000\nv 25.000000 31.250000 -74.999992\nv 18.750000 31.250000 -74.999992\nv 18.750000 31.250000 -81.250000\nv 18.750000 24.999996 -74.999992\nv 18.750000 24.999996 -68.750000\nv 25.000000 24.999996 -68.750000\nv 18.750000 18.750000 -68.750000\nv 25.000000 18.750000 -68.750000\nv 25.000000 18.750000 -75.000000\nvt 0.750000 0.580000\nvt 0.800000 0.580000\nvt 0.800000 0.630000\nvt 0.750000 0.630000\nvt 0.650000 0.480000\nvt 0.700000 0.480000\nvt 0.700000 0.530000\nvt 0.650000 0.530000\nvt 0.650000 0.580000\nvt 0.700000 0.580000\nvt 0.700000 0.630000\nvt 0.650000 0.630000\nvt 0.750000 0.530000\nvt 0.800000 0.530000\nvt 0.800000 0.480000\nvt 0.750000 0.480000\nf 2385/2338 2386/2339 2387/2340 2388/2341\nf 2386/2342 2385/2343 2389/2344 2390/2345\nf 2389/2346 2391/2345 2392/2344 2390/2347\nf 2393/2338 2392/2341 2391/2348 2394/2347\nf 2393/2347 2395/2348 2390/2349 2392/2346\nf 2396/2339 2397/2338 2390/2350 2395/2351\nf 2398/2352 2399/2351 2397/2350 2396/2353\nf 2397/2350 2399/2338 2400/2347 2390/2344\nf 2387/2350 2386/2344 2390/2343 2400/2353\ng Mesh162 Side_Texture_Plate_Side60 Texture_Side_W2\nv 0.000000 68.750000 -74.999992\nv 0.000000 68.750000 -81.250000\nv 0.000000 31.250000 -81.250000\nv 0.000000 31.250000 -74.999992\nvt 0.000000 1.000000\nf 2401/2354 2402/2354 2403/2354 2404/2354\ng Mesh400 Spacer13 Group5\nv 31.250000 68.750000 -25.000004\nv 31.250000 68.750000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 18.750000 68.750000 -25.000004\nv 18.750000 75.000000 -18.750000\nv 31.250000 75.000000 -18.750000\nv 18.750000 81.250000 -25.000002\nv 31.250000 81.250000 -25.000002\nv 31.250000 81.250000 -31.250000\nv 18.750000 81.250000 -31.250000\nv 18.750000 75.000008 -31.250000\nv 31.250000 75.000008 -31.250000\nv 18.750000 75.000008 -25.000004\nv 31.250000 75.000008 -25.000004\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 2405/2355 2406/2356 2407/2357 2408/2358\nf 2409/2359 2407/2357 2406/2356 2410/2360\nf 2411/2361 2409/2359 2410/2360 2412/2362\nf 2412/2362 2413/2363 2414/2364 2411/2361\nf 2415/2365 2414/2364 2413/2363 2416/2366\nf 2417/2367 2415/2365 2416/2366 2418/2368\nf 2418/2369 2405/2355 2408/2358 2417/2370\ng Mesh558 Edge_M_U_W\nv 18.750000 75.000008 -31.250000\nv 25.000000 81.250000 -31.250000\nv 25.000000 81.250000 -68.750000\nv 18.750000 75.000008 -68.750000\nv 31.250000 81.250000 -68.750000\nv 31.250000 81.250000 -31.250000\nv 31.250000 75.000008 -31.250000\nv 31.250000 75.000008 -68.750000\nv 25.000000 75.000008 -68.750000\nv 25.000000 75.000008 -31.250000\nv 25.000000 68.750000 -31.250000\nv 25.000000 68.750000 -68.750000\nv 18.750000 68.750000 -31.250000\nv 18.750000 68.750000 -68.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 2419/2371 2420/2372 2421/2373 2422/2374\nf 2423/2375 2421/2373 2420/2372 2424/2376\nf 2425/2376 2426/2375 2423/2377 2424/2378\nf 2427/2379 2426/2377 2425/2378 2428/2380\nf 2428/2381 2429/2382 2430/2383 2427/2384\nf 2430/2384 2429/2381 2431/2385 2432/2386\nf 2419/2371 2422/2374 2432/2386 2431/2385\ng Mesh146 Mount_N_U\nv 56.250000 81.250000 -74.999985\nv 56.250000 75.000015 -81.250000\nv 56.250000 74.999985 -99.999985\nv 56.250000 81.250000 -99.999985\nv 43.750000 75.000015 -81.250000\nv 43.750000 74.999985 -99.999985\nv 43.750000 81.250000 -99.999985\nv 43.750000 81.250000 -74.999985\nv 52.000000 81.250000 -74.999985\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.860000 0.000000\nvt 0.700000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.070000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.930000 0.190000\nvt 0.000000 0.000000\nf 2433/2387 2434/2388 2435/2389 2436/2390\nf 2434/2391 2437/2389 2438/2388 2435/2392\nf 2439/2393 2438/2394 2437/2395 2440/2396\nf 2436/2397 2435/2389 2438/2391 2439/2393\nf 2436/2390 2439/2398 2440/2399\nf 2433/2387 2436/2390 2440/2399\nf 2434/2397 2437/2400 2440/2398\nf 2433/2389 2434/2397 2440/2398\nf 2433/2401 2440/2401 2441/2401\ng Mesh452 Side_D4 Side_D\nv 25.000000 18.750000 -18.750000\nv 18.750000 18.750000 -25.000004\nv 18.750000 -0.000011 -24.999996\nv 25.000004 -0.000009 -18.750000\nv 18.750000 -0.000013 -31.250000\nv 18.750000 18.750000 -31.250000\nv 25.000004 -0.000012 -31.250000\nv 25.000004 -0.000010 -24.999996\nv 25.000000 18.750000 -31.250000\nv 25.000000 18.750000 -25.000004\nv 31.250000 18.750000 -25.000004\nv 31.250000 -0.000010 -24.999996\nv 31.250000 18.750000 -18.750000\nv 31.250000 -0.000008 -18.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.650000 0.850000\nvt 0.650000 0.780000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.650000 0.950000\nvt 0.700000 0.950000\nvt 0.700000 1.000000\nvt 0.650000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.950000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.650000 0.630000\nvt 0.650000 0.680000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.750000 0.900000\nvt 0.750000 0.950000\nvt 0.700000 0.900000\nf 2442/2402 2443/2403 2444/2404 2445/2405\nf 2446/2406 2444/2404 2443/2403 2447/2407\nf 2448/2408 2449/2409 2444/2410 2446/2411\nf 2449/2408 2448/2411 2450/2412 2451/2413\nf 2446/2406 2447/2407 2450/2413 2448/2408\nf 2451/2414 2452/2415 2453/2416 2449/2417\nf 2454/2418 2455/2419 2453/2417 2452/2414\nf 2442/2402 2445/2405 2455/2419 2454/2418\nf 2455/2420 2445/2421 2449/2409 2453/2422\nf 2444/2410 2449/2409 2445/2421\ng Mesh495 Edge_Side_S_US Side_E\nv 100.000000 75.000000 -18.750000\nv 100.000000 81.250000 -25.000002\nv 81.250000 81.250000 -25.000002\nv 81.250000 75.000000 -18.750000\nv 100.000000 75.000008 -25.000004\nv 100.000000 68.750000 -18.750000\nv 100.000000 68.750000 -25.000004\nv 81.250000 68.750000 -25.000004\nv 81.250000 75.000008 -25.000004\nv 81.250000 68.750000 -18.750000\nv 81.250000 75.000008 -31.250000\nv 100.000000 75.000008 -31.250000\nv 81.250000 81.250000 -31.250000\nv 100.000000 81.250000 -31.250000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 2456/2423 2457/2424 2458/2425 2459/2426\nf 2456/2427 2460/2428 2457/2429\nf 2456/2427 2461/2430 2462/2431 2460/2428\nf 2460/2430 2462/2431 2463/2432 2464/2433\nf 2463/2432 2462/2431 2461/2434 2465/2435\nf 2456/2423 2459/2426 2465/2436 2461/2437\nf 2464/2438 2466/2439 2467/2440 2460/2441\nf 2467/2440 2466/2439 2468/2436 2469/2437\nf 2468/2435 2458/2425 2457/2424 2469/2434\nf 2469/2442 2457/2429 2460/2428 2467/2443\ng Mesh265 Side_Texture_Plate_Side4 Texture_Side_N\nv 31.250000 75.000000 -99.999985\nv 31.250000 81.250000 -99.999985\nv 68.750000 81.250000 -99.999985\nv 68.750000 75.000000 -99.999985\nvt 0.000000 1.000000\nf 2470/2444 2471/2444 2472/2444 2473/2444\ng Mesh445 Side_2 Side_W\nv 0.000000 25.000004 -18.750000\nv 0.000000 18.750000 -24.999996\nv 18.750000 18.750000 -24.999996\nv 18.750000 25.000004 -18.750000\nv 0.000000 24.999996 -25.000004\nv 0.000000 31.250000 -18.750000\nv 0.000000 31.250000 -25.000002\nv 18.750000 31.250000 -25.000002\nv 18.750000 24.999996 -25.000004\nv 18.750000 31.250000 -18.750000\nv 18.750000 24.999998 -31.250000\nv 0.000000 24.999998 -31.250000\nv 18.750000 18.750000 -31.250000\nv 0.000000 18.750000 -31.250000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 2474/2445 2475/2446 2476/2447 2477/2448\nf 2474/2449 2478/2450 2475/2451\nf 2474/2449 2479/2452 2480/2453 2478/2450\nf 2478/2452 2480/2453 2481/2454 2482/2455\nf 2481/2454 2480/2453 2479/2456 2483/2457\nf 2474/2445 2477/2448 2483/2458 2479/2459\nf 2482/2460 2484/2461 2485/2462 2478/2463\nf 2485/2462 2484/2461 2486/2458 2487/2459\nf 2486/2457 2476/2447 2475/2446 2487/2456\nf 2487/2464 2475/2451 2478/2450 2485/2465\ng Mesh561 Side_Texture_Plate_Side74 Texture_Side_U2\nv 31.250000 81.250000 -74.999985\nv 31.250000 81.250000 -81.250000\nv 68.750000 81.250000 -81.250000\nv 68.750000 81.250000 -74.999985\nvt 0.000000 1.000000\nf 2488/2466 2489/2466 2490/2466 2491/2466\ng Mesh71 Corner_I_U_NW1\nv 25.000000 68.750000 -68.750000\nv 18.750000 68.750000 -68.750000\nv 18.750000 68.750000 -81.250000\nv 25.000000 68.750000 -81.250000\nv 25.000000 81.250000 -68.750000\nv 18.750000 81.250000 -68.750000\nv 31.250000 75.000015 -74.999985\nv 25.000000 75.000015 -74.999985\nv 25.000000 75.000015 -81.250000\nv 31.250000 75.000015 -81.250000\nv 31.250000 81.250000 -74.999985\nv 25.000000 81.250000 -74.999985\nv 31.250000 81.250000 -81.250000\nv 18.750000 75.000015 -81.250000\nv 18.750000 81.250000 -74.999985\nv 25.000000 81.250000 -81.250000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.700000 0.230000\nvt 0.650000 0.230000\nf 2492/2467 2493/2468 2494/2469 2495/2470\nf 2493/2468 2492/2467 2496/2471 2497/2472\nf 2498/2473 2499/2474 2500/2475 2501/2476\nf 2499/2476 2498/2475 2502/2477 2503/2478\nf 2504/2478 2502/2477 2498/2479 2501/2480\nf 2505/2474 2506/2481 2507/2482\nf 2493/2483 2497/2484 2506/2485\nf 2493/2483 2506/2485 2505/2486\nf 2493/2483 2505/2486 2494/2480\nf 2496/2476 2492/2484 2503/2473\nf 2503/2473 2492/2484 2499/2481\nf 2499/2481 2492/2484 2500/2487\nf 2500/2487 2492/2484 2495/2488\ng Mesh55 Texture_Connector_Plate11 Texture_Connector_Plate_Mirror6 Texture_Connector_E_U\nv 81.250000 81.250000 -31.250000\nv 81.250000 81.250000 -68.750000\nv 81.250000 68.750000 -68.750000\nv 81.250000 68.750000 -31.250000\nvt 0.000000 1.000000\nf 2508/2489 2509/2489 2510/2489 2511/2489\ng Mesh449 Texture_Connector_Plate50 Texture_Connector_Plate_Mirror25 Texture_Connector_W_U\nv 25.000000 81.250000 -31.250000\nv 25.000000 81.250000 -68.750000\nv 25.000000 68.750000 -68.750000\nv 25.000000 68.750000 -31.250000\nvt 0.000000 1.000000\nf 2512/2490 2513/2490 2514/2490 2515/2490\ng Mesh358 Edge_M_D_N\nv 68.750000 24.999998 -81.250000\nv 68.750000 18.750000 -75.000000\nv 31.250000 18.750000 -75.000000\nv 31.250000 24.999998 -81.250000\nv 31.250000 18.750000 -68.750000\nv 68.750000 18.750000 -68.750000\nv 68.750000 24.999996 -68.750000\nv 31.250000 24.999996 -68.750000\nv 31.250000 24.999996 -74.999992\nv 68.750000 24.999996 -74.999992\nv 68.750000 31.250000 -74.999992\nv 31.250000 31.250000 -74.999992\nv 68.750000 31.250000 -81.250000\nv 31.250000 31.250000 -81.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 2516/2491 2517/2492 2518/2493 2519/2494\nf 2520/2495 2518/2493 2517/2492 2521/2496\nf 2522/2496 2523/2495 2520/2497 2521/2498\nf 2524/2499 2523/2497 2522/2498 2525/2500\nf 2525/2501 2526/2502 2527/2503 2524/2504\nf 2527/2504 2526/2501 2528/2505 2529/2506\nf 2516/2491 2519/2494 2529/2506 2528/2505\ng Mesh576 Texture_Connector_Plate90 Texture_Connector_Plate_Mirror45 Texture_Connector_D_E\nv 68.750000 24.999998 -31.250000\nv 68.750000 24.999996 -68.750000\nv 81.250000 24.999996 -68.750000\nv 81.250000 24.999998 -31.250000\nvt 0.000000 1.000000\nf 2530/2507 2531/2507 2532/2507 2533/2507\ng Mesh227 Edge_Side_S_UW Side_S\nv 18.750000 75.000000 0.000000\nv 25.000000 81.250000 0.000001\nv 25.000000 81.250000 -18.750000\nv 18.750000 75.000000 -18.750000\nv 25.000000 75.000000 0.000000\nv 18.750000 68.750000 -0.000001\nv 25.000000 68.750000 -0.000001\nv 25.000000 68.750000 -18.750000\nv 25.000000 75.000000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 31.250000 75.000000 -18.750000\nv 31.250000 75.000000 0.000000\nv 31.250000 81.250000 -18.750000\nv 31.250000 81.250000 0.000001\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 2534/2508 2535/2509 2536/2510 2537/2511\nf 2534/2512 2538/2513 2535/2514\nf 2534/2512 2539/2515 2540/2516 2538/2513\nf 2538/2515 2540/2516 2541/2517 2542/2518\nf 2541/2517 2540/2516 2539/2519 2543/2520\nf 2534/2508 2537/2511 2543/2521 2539/2522\nf 2542/2523 2544/2524 2545/2525 2538/2526\nf 2545/2525 2544/2524 2546/2521 2547/2522\nf 2546/2520 2536/2510 2535/2509 2547/2519\nf 2547/2527 2535/2514 2538/2513 2545/2528\ng Mesh30 Side_Texture_Plate_Side39 Texture_Side_S1\nv 68.750000 75.000000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 31.250000 81.250000 -18.750000\nv 31.250000 75.000000 -18.750000\nvt 0.000000 1.000000\nf 2548/2529 2549/2529 2550/2529 2551/2529\ng Mesh274 Texture_Connector_Plate57 Texture_Connector_Plate_Mirror29 Texture_Connector_S_D\nv 31.250000 31.250000 -25.000002\nv 68.750000 31.250000 -25.000002\nv 68.750000 18.750000 -24.999996\nv 31.250000 18.750000 -24.999996\nvt 0.000000 1.000000\nf 2552/2530 2553/2530 2554/2530 2555/2530\ng Mesh456 Side_Texture_Plate49 Side_Texture_Plate_Mirror25 Texture_Side_W\nv 18.750000 68.750000 -18.750000\nv 0.000000 68.750000 -18.750000\nv 0.000000 31.250000 -18.750000\nv 18.750000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 2556/2531 2557/2531 2558/2531 2559/2531\ng Mesh537 Corner_M_D_SW\nv 31.250000 24.999996 -25.000004\nv 25.000000 24.999996 -25.000004\nv 25.000000 31.250000 -25.000002\nv 31.250000 31.250000 -25.000002\nv 31.250000 24.999998 -31.250000\nv 25.000000 24.999998 -31.250000\nv 25.000000 31.250000 -31.250000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 2560/2532 2561/2533 2562/2534 2563/2535\nf 2560/2534 2564/2536 2565/2537 2561/2535\nf 2565/2536 2566/2538 2562/2539 2561/2537\ng Mesh323 Inner_Plate_E1\nv 75.000000 68.750000 -31.250000\nv 75.000000 68.750000 -68.750000\nv 75.000000 31.250000 -68.750000\nv 75.000000 31.250000 -31.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2567/2540 2568/2541 2569/2542 2570/2543\ng Mesh326 Side_Texture_Plate_Side23 Texture_Side_E1\nv 81.250000 75.000008 -68.750000\nv 81.250000 81.250000 -68.750000\nv 81.250000 81.250000 -31.250000\nv 81.250000 75.000008 -31.250000\nvt 0.000000 1.000000\nf 2571/2544 2572/2544 2573/2544 2574/2544\ng Mesh399 Texture_Connector_Plate49 Texture_Connector_Plate_Mirror25 Texture_Connector_W_U\nv 25.000000 81.250000 -68.750000\nv 25.000000 81.250000 -31.250000\nv 25.000000 68.750000 -31.250000\nv 25.000000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 2575/2545 2576/2545 2577/2545 2578/2545\ng Mesh370 Side_Texture_Plate_Side53 Texture_Side_W1\nv 0.000000 25.000002 -31.250000\nv 0.000000 18.750000 -31.250000\nv 0.000000 18.750000 -68.750000\nv 0.000000 25.000004 -68.750000\nvt 0.000000 1.000000\nf 2579/2546 2580/2546 2581/2546 2582/2546\ng Mesh458 Side_Texture_Plate32 Side_Texture_Plate_Mirror16 Texture_Side_E3\nv 81.250000 25.000002 -31.250000\nv 100.000000 25.000002 -31.250000\nv 100.000000 25.000004 -68.750000\nv 81.250000 25.000004 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2583/2547 2584/2548 2585/2549 2586/2550\ng Mesh516 Texture_Connector_Plate94 Texture_Connector_Plate_Mirror47 Texture_Connector_D_W\nv 18.750000 24.999998 -31.250000\nv 18.750000 24.999996 -68.750000\nv 31.250000 24.999996 -68.750000\nv 31.250000 24.999998 -31.250000\nvt 0.000000 1.000000\nf 2587/2551 2588/2551 2589/2551 2590/2551\ng Mesh327 Side_Texture_Plate72 Side_Texture_Plate_Mirror36 Texture_Side_U1\nv 31.250000 81.250000 -24.999994\nv 31.250000 100.000008 -24.999990\nv 68.750000 100.000008 -24.999990\nv 68.750000 81.250000 -24.999994\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2591/2552 2592/2553 2593/2554 2594/2555\ng Mesh459 Side_Texture_Plate_Side64 Texture_Side_W3\nv 0.000000 75.000008 -31.250000\nv 0.000000 81.250000 -31.250000\nv 0.000000 81.250000 -68.750000\nv 0.000000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 2595/2556 2596/2556 2597/2556 2598/2556\ng Mesh603 Corner_I3_D_SW\nv 18.750000 25.000004 -18.750000\nv 18.750000 18.750000 -24.999996\nv 25.000000 18.750000 -18.750000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 2599/2557 2600/2558 2601/2559\ng Mesh436 Side_Texture_Plate_Side29 Texture_Side_E3\nv 100.000000 25.000004 -68.750000\nv 100.000000 18.750000 -68.750000\nv 100.000000 18.750000 -31.250000\nv 100.000000 25.000002 -31.250000\nvt 0.000000 1.000000\nf 2602/2560 2603/2560 2604/2560 2605/2560\ng Mesh175 Spacer14 Group5\nv 31.250000 75.000008 -68.750000\nv 31.250000 81.250000 -68.750000\nv 18.750000 81.250000 -68.750000\nv 18.750000 75.000008 -68.750000\nv 18.750000 81.250000 -74.999985\nv 31.250000 81.250000 -74.999985\nv 18.750000 75.000015 -81.250000\nv 31.250000 75.000015 -81.250000\nv 31.250000 68.750000 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 68.750000 -74.999992\nv 31.250000 68.750000 -74.999992\nv 18.750000 75.000015 -74.999985\nv 31.250000 75.000015 -74.999985\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 2606/2561 2607/2562 2608/2563 2609/2564\nf 2610/2565 2608/2563 2607/2562 2611/2566\nf 2612/2567 2610/2565 2611/2566 2613/2568\nf 2613/2568 2614/2569 2615/2570 2612/2567\nf 2616/2571 2615/2570 2614/2569 2617/2572\nf 2618/2573 2616/2571 2617/2572 2619/2574\nf 2619/2575 2606/2561 2609/2564 2618/2576\ng Mesh155 Inner_Plate_E\nv 75.000000 68.750000 -68.750000\nv 75.000000 68.750000 -31.250000\nv 75.000000 31.250000 -31.250000\nv 75.000000 31.250000 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2620/2577 2621/2578 2622/2579 2623/2580\ng Mesh70 Texture_Connector_Plate75 Texture_Connector_Plate_Mirror38 Texture_Connector_U_E\nv 68.750000 81.250000 -31.250000\nv 68.750000 81.250000 -68.750000\nv 81.250000 81.250000 -68.750000\nv 81.250000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 2624/2581 2625/2581 2626/2581 2627/2581\ng Mesh366 Side_Texture_Plate_Side67 Texture_Side_U\nv 25.000000 81.250000 -68.750000\nv 18.750000 81.250000 -68.750000\nv 18.750000 81.250000 -31.250000\nv 25.000000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 2628/2582 2629/2582 2630/2582 2631/2582\ng Mesh426 Side_Texture_Plate_Side41 Texture_Side_S2\nv 75.000000 68.750000 0.000005\nv 81.250000 68.750000 0.000005\nv 81.250000 31.250000 0.000003\nv 75.000000 31.250000 0.000003\nvt 0.000000 1.000000\nf 2632/2583 2633/2583 2634/2583 2635/2583\ng Mesh61 Side_Texture_Plate_Side48 Texture_Side_S3\nv 31.250000 25.000000 0.000002\nv 31.250000 18.750000 0.000001\nv 68.750000 18.750000 0.000001\nv 68.750000 25.000000 0.000002\nvt 0.000000 1.000000\nf 2636/2584 2637/2584 2638/2584 2639/2584\ng Mesh87 Mount_E_S\nv 100.000000 56.250000 -18.750000\nv 100.000000 56.250000 -24.999998\nv 81.250000 56.250000 -24.999998\nv 75.000000 56.250000 -18.750000\nv 100.000000 43.750000 -18.750000\nv 100.000000 43.750000 -25.000000\nv 75.000000 43.750000 -18.750000\nv 81.250000 43.750000 -25.000000\nv 75.000000 52.000004 -18.750000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.150000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.930000 0.190000\nvt 0.860000 0.180000\nf 2640/2585 2641/2586 2642/2587 2643/2588\nf 2641/2589 2640/2585 2644/2590 2645/2591\nf 2646/2592 2647/2593 2645/2594 2644/2595\nf 2641/2593 2645/2596 2647/2589 2642/2594\nf 2640/2592 2643/2595 2648/2597\nf 2644/2598 2640/2592 2648/2597\nf 2644/2598 2648/2597 2646/2599\nf 2642/2600 2643/2599 2648/2601\nf 2647/2590 2642/2600 2648/2601\nf 2647/2590 2648/2601 2646/2591\ng Mesh433 Side_Texture_Plate_Side80 Texture_Side_U3\nv 75.000000 100.000008 -31.250000\nv 81.250000 100.000008 -31.250000\nv 81.250000 100.000008 -68.750000\nv 75.000000 100.000008 -68.750000\nvt 0.000000 1.000000\nf 2649/2602 2650/2602 2651/2602 2652/2602\ng Mesh331 Side_Texture_Plate_Side62 Texture_Side_W3\nv 18.750000 75.000008 -68.750000\nv 18.750000 81.250000 -68.750000\nv 18.750000 81.250000 -31.250000\nv 18.750000 75.000008 -31.250000\nvt 0.000000 1.000000\nf 2653/2603 2654/2603 2655/2603 2656/2603\ng Mesh47 Corner_I_D_NW2\nv 31.250000 18.750000 -75.000000\nv 31.250000 18.750000 -81.250000\nv 31.250000 31.250000 -81.250000\nv 31.250000 31.250000 -74.999992\nv 18.750000 18.750000 -75.000000\nv 18.750000 24.999998 -81.250000\nv 25.000000 18.750000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 18.750000 31.250000 -74.999992\nv 18.750000 24.999996 -74.999992\nv 18.750000 24.999996 -68.750000\nv 25.000000 24.999996 -68.750000\nv 25.000000 24.999996 -74.999992\nv 25.000000 18.750000 -68.750000\nv 18.750000 18.750000 -68.750000\nv 25.000000 18.750000 -75.000000\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.330000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nf 2657/2604 2658/2605 2659/2606 2660/2607\nf 2661/2608 2662/2609 2663/2610\nf 2664/2605 2665/2604 2660/2611 2659/2612\nf 2666/2613 2667/2614 2668/2610 2669/2615\nf 2670/2616 2668/2617 2667/2618 2671/2619\nf 2670/2613 2672/2615 2669/2616 2668/2619\nf 2660/2620 2665/2621 2666/2622\nf 2669/2608 2660/2620 2666/2622\nf 2657/2613 2660/2620 2669/2608\nf 2657/2613 2669/2608 2672/2614\nf 2662/2623 2664/2618 2659/2624\nf 2662/2623 2659/2624 2658/2620\nf 2663/2625 2662/2623 2658/2620\ng Mesh82 Side_BC_U\nv 68.750000 100.000015 -75.000015\nv 50.000000 100.000015 -75.000015\nv 50.000000 97.000015 -75.000015\nv 68.750000 97.000015 -75.000015\nv 75.000000 100.000008 -50.000000\nv 75.000000 100.000008 -68.750000\nv 75.000000 97.000008 -68.750000\nv 75.000000 97.000008 -50.000000\nv 75.000000 100.000015 -75.000015\nv 75.000000 90.000015 -75.000015\nv 68.750000 90.000015 -75.000015\nv 75.000000 90.000008 -68.750000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.210000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.430000\nvt 0.220000 0.480000\nvt 0.130000 0.530000\nf 2673/2626 2674/2627 2675/2628 2676/2629\nf 2677/2628 2678/2629 2679/2630 2680/2631\nf 2681/2629 2673/2626 2676/2632\nf 2682/2633 2681/2629 2676/2632\nf 2682/2633 2676/2632 2683/2634\nf 2679/2635 2678/2629 2681/2630\nf 2679/2635 2681/2630 2682/2636\nf 2684/2633 2679/2635 2682/2636\ng Mesh260 Side_Texture_Plate69 Side_Texture_Plate_Mirror35 Texture_Side_U1\nv 68.750000 81.250000 -18.750000\nv 68.750000 100.000000 -18.750000\nv 31.250000 100.000000 -18.750000\nv 31.250000 81.250000 -18.750000\nvt 0.000000 1.000000\nf 2685/2637 2686/2637 2687/2637 2688/2637\ng Mesh223 Inner_BC_Side14 Side_BC_U\nv 75.000000 97.000008 -31.250000\nv 75.000000 97.000008 -50.000000\nv 75.000000 100.000008 -50.000000\nv 75.000000 100.000008 -31.250000\nv 50.000000 100.000008 -24.999998\nv 50.000000 97.000008 -25.000000\nv 68.750000 97.000008 -25.000000\nv 68.750000 100.000008 -24.999998\nv 68.750000 81.250000 -25.000002\nv 68.750000 90.000008 -25.000000\nv 75.000000 90.000008 -25.000000\nv 75.000000 81.250000 -25.000002\nv 68.750000 81.250000 -18.750000\nv 75.000000 81.250000 -18.750000\nv 81.250000 81.250000 -25.000002\nv 75.000000 90.000008 -31.250000\nv 81.250000 81.250000 -31.250000\nv 75.000000 81.250000 -31.250000\nv 75.000000 100.000008 -24.999998\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.530000\nvt 0.210000 0.580000\nf 2689/2638 2690/2639 2691/2640 2692/2641\nf 2693/2639 2694/2642 2695/2643 2696/2638\nf 2697/2644 2698/2645 2699/2646 2700/2647\nf 2701/2640 2698/2648 2697/2649\nf 2699/2650 2698/2651 2701/2652 2702/2653\nf 2699/2654 2702/2655 2703/2640\nf 2704/2656 2699/2650 2703/2653 2705/2657\nf 2700/2656 2699/2657 2704/2645 2706/2644\nf 2704/2640 2705/2648 2706/2642\nf 2707/2638 2696/2641 2695/2658\nf 2699/2650 2707/2638 2695/2658\nf 2699/2650 2695/2658 2698/2656\nf 2692/2638 2707/2643 2699/2651\nf 2689/2659 2692/2638 2699/2651\nf 2704/2650 2689/2659 2699/2651\ng Mesh57 Mount_U_E\nv 81.250000 100.000008 -43.750000\nv 75.000000 100.000008 -43.750000\nv 75.000000 81.250000 -43.750000\nv 81.250000 75.000008 -43.750000\nv 81.250000 100.000008 -56.250000\nv 75.000000 100.000008 -56.250000\nv 81.250000 75.000008 -56.250000\nv 75.000000 81.250000 -56.250000\nv 81.250000 75.000008 -48.000004\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.070000\nvt 0.860000 0.070000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.000000 0.000000\nvt 0.930000 0.190000\nvt 0.930000 0.100000\nf 2708/2660 2709/2661 2710/2662 2711/2663\nf 2709/2664 2708/2660 2712/2665 2713/2666\nf 2714/2667 2715/2668 2713/2666 2712/2669\nf 2709/2668 2713/2670 2715/2664 2710/2666\nf 2712/2671 2708/2667 2711/2669\nf 2714/2672 2712/2671 2711/2669\nf 2714/2673 2711/2673 2716/2673\nf 2714/2674 2715/2672 2710/2666\nf 2716/2675 2714/2674 2710/2666\nf 2711/2665 2716/2675 2710/2666\ng Mesh234 Corner_M_U_NE\nv 75.000000 68.750000 -74.999992\nv 75.000000 75.000015 -74.999985\nv 68.750000 75.000015 -74.999985\nv 68.750000 68.750000 -74.999992\nv 75.000000 68.750000 -68.750000\nv 75.000000 75.000008 -68.750000\nv 68.750000 75.000008 -68.750000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 2717/2676 2718/2677 2719/2678 2720/2679\nf 2717/2678 2721/2680 2722/2681 2718/2679\nf 2722/2680 2723/2682 2719/2683 2718/2681\ng Mesh60 Spacer5 Group3\nv 75.000000 68.750000 -31.250000\nv 81.250000 68.750000 -31.250000\nv 81.250000 68.750000 -18.750000\nv 75.000000 68.750000 -18.750000\nv 81.250000 75.000000 -18.750000\nv 81.250000 75.000008 -31.250000\nv 75.000000 81.250000 -18.750000\nv 75.000000 81.250000 -31.250000\nv 68.750000 81.250000 -31.250000\nv 68.750000 81.250000 -18.750000\nv 68.750000 75.000000 -18.750000\nv 68.750000 75.000008 -31.250000\nv 75.000000 75.000000 -18.750000\nv 75.000000 75.000008 -31.250000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 2724/2684 2725/2685 2726/2686 2727/2687\nf 2728/2688 2726/2686 2725/2685 2729/2689\nf 2730/2690 2728/2688 2729/2689 2731/2691\nf 2731/2691 2732/2692 2733/2693 2730/2690\nf 2734/2694 2733/2693 2732/2692 2735/2695\nf 2736/2696 2734/2694 2735/2695 2737/2697\nf 2737/2698 2724/2684 2727/2687 2736/2699\ng Mesh409 Texture_Connector_Plate45 Texture_Connector_Plate_Mirror23 Texture_Connector_W_D\nv 25.000000 31.250000 -68.750000\nv 25.000000 31.250000 -31.250000\nv 25.000000 18.750000 -31.250000\nv 25.000000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 2738/2700 2739/2700 2740/2700 2741/2700\ng Mesh205 Texture_Connector_Plate83 Texture_Connector_Plate_Mirror42 Texture_Connector_D_S\nv 31.250000 18.750000 -18.750000\nv 68.750000 18.750000 -18.750000\nv 68.750000 18.750000 -31.250000\nv 31.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 2742/2701 2743/2701 2744/2701 2745/2701\ng Mesh408 Spacer3 Group2\nv 75.000000 31.250000 -68.750000\nv 81.250000 31.250000 -68.750000\nv 81.250000 31.250000 -81.250000\nv 75.000000 31.250000 -81.250000\nv 81.250000 24.999998 -81.250000\nv 81.250000 24.999996 -68.750000\nv 75.000000 18.750000 -81.250000\nv 75.000000 18.750000 -68.750000\nv 68.750000 18.750000 -68.750000\nv 68.750000 18.750000 -81.250000\nv 68.750000 24.999998 -81.250000\nv 68.750000 24.999996 -68.750000\nv 75.000000 24.999998 -81.250000\nv 75.000000 24.999996 -68.750000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 2746/2702 2747/2703 2748/2704 2749/2705\nf 2750/2706 2748/2704 2747/2703 2751/2707\nf 2752/2708 2750/2706 2751/2707 2753/2709\nf 2753/2709 2754/2710 2755/2711 2752/2708\nf 2756/2712 2755/2711 2754/2710 2757/2713\nf 2758/2714 2756/2712 2757/2713 2759/2715\nf 2759/2716 2746/2702 2749/2705 2758/2717\ng Mesh482 Texture_Plate_S1\nv 31.250000 68.750000 -18.750000\nv 68.750000 68.750000 -18.750000\nv 68.750000 31.250000 -18.750000\nv 31.250000 31.250000 -18.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2760/2718 2761/2719 2762/2720 2763/2721\ng Mesh425 Side_Texture_Plate_Side87 Texture_Side_D1\nv 68.750000 18.750000 -24.999996\nv 68.750000 18.750000 -18.750000\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 -24.999996\nvt 0.000000 1.000000\nf 2764/2722 2765/2722 2766/2722 2767/2722\ng Mesh100 Side_Texture_Plate76 Side_Texture_Plate_Mirror38 Texture_Side_U2\nv 68.750000 81.250000 -74.999985\nv 68.750000 100.000015 -75.000000\nv 31.250000 100.000015 -75.000000\nv 31.250000 81.250000 -74.999985\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2768/2723 2769/2724 2770/2725 2771/2726\ng Mesh262 Side_Texture_Plate12 Side_Texture_Plate_Mirror6 Texture_Side_N2\nv 68.750000 25.000006 -81.250000\nv 68.750000 25.000010 -99.999992\nv 31.250000 25.000010 -99.999992\nv 31.250000 25.000006 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2772/2727 2773/2728 2774/2729 2775/2730\ng Mesh126 Support_D_S\nv 31.250000 18.750000 -43.750000\nv 68.750000 18.750000 -43.750000\nv 68.750000 23.000000 -43.750000\nv 31.250000 23.000000 -43.750000\nv 31.250000 18.750000 -56.250000\nv 68.750000 18.750000 -56.250000\nv 31.250000 23.000002 -56.250000\nv 68.750000 23.000002 -56.250000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 2776/2731 2777/2732 2778/2733 2779/2734\nf 2777/2735 2776/2736 2780/2737 2781/2738\nf 2781/2739 2780/2740 2782/2734 2783/2733\nf 2783/2738 2782/2737 2779/2741 2778/2742\ng Mesh209 Texture_Connector_Plate16 Texture_Connector_Plate_Mirror8 Texture_Connector_E_S\nv 81.250000 31.250000 -31.250000\nv 81.250000 68.750000 -31.250000\nv 81.250000 68.750000 -18.750000\nv 81.250000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 2784/2743 2785/2743 2786/2743 2787/2743\ng Mesh187 Side_Texture_Plate50 Side_Texture_Plate_Mirror25 Texture_Side_W\nv 18.750000 31.250000 -18.750000\nv 0.000000 31.250000 -18.750000\nv 0.000000 68.750000 -18.750000\nv 18.750000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 2788/2744 2789/2744 2790/2744 2791/2744\ng Mesh163 Side_Texture_Plate26 Side_Texture_Plate_Mirror13 Texture_Side_E2\nv 81.250000 31.250000 -81.250000\nv 100.000000 31.250000 -81.250000\nv 100.000000 68.750000 -81.250000\nv 81.250000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 2792/2745 2793/2745 2794/2745 2795/2745\ng Mesh249 Texture_Connector_Plate28 Texture_Connector_Plate_Mirror14 Texture_Connector_N_U\nv 31.250000 81.250000 -81.250000\nv 68.750000 81.250000 -81.250000\nv 68.750000 68.750000 -81.250000\nv 31.250000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 2796/2746 2797/2746 2798/2746 2799/2746\ng Mesh342 Corner_M_U_SW\nv 25.000000 68.750000 -25.000004\nv 25.000000 75.000008 -25.000004\nv 31.250000 75.000008 -25.000004\nv 31.250000 68.750000 -25.000004\nv 25.000000 68.750000 -31.250000\nv 25.000000 75.000008 -31.250000\nv 31.250000 75.000008 -31.250000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 2800/2747 2801/2748 2802/2749 2803/2750\nf 2800/2749 2804/2751 2805/2752 2801/2750\nf 2805/2751 2806/2753 2802/2754 2801/2752\ng Mesh329 Side_Texture_Plate56 Side_Texture_Plate_Mirror28 Texture_Side_W1\nv 18.750000 25.000004 -68.750000\nv 0.000000 25.000004 -68.750000\nv 0.000000 25.000002 -31.250000\nv 18.750000 25.000002 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2807/2755 2808/2756 2809/2757 2810/2758\ng Mesh471 Corner_I_D_NE\nv 68.750000 24.999998 -81.250000\nv 68.750000 18.750000 -81.250000\nv 68.750000 18.750000 -68.750000\nv 68.750000 24.999996 -68.750000\nv 81.250000 24.999998 -81.250000\nv 81.250000 18.750000 -75.000000\nv 75.000000 18.750000 -81.250000\nv 81.250000 18.750000 -68.750000\nv 81.250000 24.999996 -68.750000\nv 81.250000 24.999996 -74.999992\nv 81.250000 31.250000 -74.999992\nv 75.000000 31.250000 -74.999992\nv 75.000000 24.999996 -74.999992\nv 75.000000 31.250000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 75.000000 24.999998 -81.250000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.700000 0.280000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.380000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.650000 0.330000\nvt 0.700000 0.230000\nvt 0.650000 0.230000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nf 2811/2759 2812/2760 2813/2761 2814/2762\nf 2815/2763 2816/2764 2817/2765\nf 2818/2766 2819/2767 2814/2760 2813/2759\nf 2820/2768 2821/2769 2822/2770 2823/2771\nf 2824/2772 2822/2773 2821/2774 2825/2764\nf 2824/2769 2826/2772 2823/2773 2822/2768\nf 2826/2774 2811/2773 2814/2775\nf 2823/2765 2826/2774 2814/2775\nf 2820/2776 2823/2765 2814/2775\nf 2819/2777 2820/2776 2814/2775\nf 2813/2778 2812/2775 2817/2779\nf 2813/2778 2817/2779 2816/2780\nf 2813/2778 2816/2780 2818/2771\ng Mesh380 Side_Texture_Plate84 Side_Texture_Plate_Mirror42 Texture_Side_D\nv 25.000000 18.750000 -31.250000\nv 25.000000 0.000003 -31.250000\nv 25.000000 0.000005 -68.750000\nv 25.000000 18.750000 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2827/2781 2828/2782 2829/2783 2830/2784\ng Mesh141 Texture_Connector_Plate29 Texture_Connector_Plate_Mirror15 Texture_Connector_N_W\nv 31.250000 31.250000 -74.999992\nv 31.250000 68.750000 -74.999992\nv 18.750000 68.750000 -74.999992\nv 18.750000 31.250000 -74.999992\nvt 0.000000 1.000000\nf 2831/2785 2832/2785 2833/2785 2834/2785\ng Mesh38 Side_Texture_Plate94 Side_Texture_Plate_Mirror47 Texture_Side_D3\nv 81.250000 18.750000 -68.750000\nv 81.250000 0.000005 -68.750000\nv 81.250000 0.000003 -31.250000\nv 81.250000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 2835/2786 2836/2786 2837/2786 2838/2786\ng Mesh526 Texture_Connector_Plate48 Texture_Connector_Plate_Mirror24 Texture_Connector_W_D\nv 18.750000 31.250000 -31.250000\nv 18.750000 31.250000 -68.750000\nv 18.750000 18.750000 -68.750000\nv 18.750000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 2839/2787 2840/2787 2841/2787 2842/2787\ng Mesh553 Texture_Plate_U1\nv 31.250000 81.250000 -31.250000\nv 68.750000 81.250000 -31.250000\nv 68.750000 81.250000 -68.750000\nv 31.250000 81.250000 -68.750000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nvt 0.000000 1.000000\nf 2843/2788 2844/2789 2845/2790 2846/2791\ng Mesh450 Texture_Connector_Plate95 Texture_Connector_Plate_Mirror48 Texture_Connector_D_W\nv 18.750000 18.750000 -68.750000\nv 18.750000 18.750000 -31.250000\nv 31.250000 18.750000 -31.250000\nv 31.250000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 2847/2792 2848/2792 2849/2792 2850/2792\ng Mesh320 Texture_Connector_Plate21 Texture_Connector_Plate_Mirror11 Texture_Connector_N_D\nv 68.750000 31.250000 -74.999992\nv 31.250000 31.250000 -74.999992\nv 31.250000 18.750000 -75.000000\nv 68.750000 18.750000 -75.000000\nvt 0.000000 1.000000\nf 2851/2793 2852/2793 2853/2793 2854/2793\ng Mesh65 Texture_Connector_Plate1 Texture_Connector_Plate_Mirror1 Texture_Connector_U_N\nv 68.750000 81.250000 -81.250000\nv 31.250000 81.250000 -81.250000\nv 31.250000 81.250000 -68.750000\nv 68.750000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 2855/2794 2856/2794 2857/2794 2858/2794\ng Mesh345 Side_Texture_Plate51 Side_Texture_Plate_Mirror26 Texture_Side_W\nv 18.750000 68.750000 -24.999996\nv 0.000000 68.750000 -24.999996\nv 0.000000 31.250000 -24.999998\nv 18.750000 31.250000 -24.999998\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 2859/2795 2860/2796 2861/2797 2862/2798\ng Mesh46 Edge_M_S_NW\nv 18.750000 68.750000 -74.999992\nv 25.000010 68.750000 -81.250000\nv 25.000010 31.250000 -81.250000\nv 18.750000 31.250000 -74.999992\nv 31.250000 31.250000 -81.250000\nv 31.250000 68.750000 -81.250000\nv 31.250000 68.750000 -74.999992\nv 31.250000 31.250000 -74.999992\nv 25.000010 31.250000 -74.999992\nv 25.000010 68.750000 -74.999992\nv 25.000008 68.750000 -68.750000\nv 25.000008 31.250000 -68.750000\nv 18.750000 68.750000 -68.750000\nv 18.750000 31.250000 -68.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 2863/2799 2864/2800 2865/2801 2866/2802\nf 2867/2803 2865/2801 2864/2800 2868/2804\nf 2869/2804 2870/2803 2867/2805 2868/2806\nf 2871/2807 2870/2805 2869/2806 2872/2808\nf 2872/2809 2873/2810 2874/2811 2871/2812\nf 2874/2812 2873/2809 2875/2813 2876/2814\nf 2863/2799 2866/2802 2876/2814 2875/2813\ng Mesh176 Mount_U_W\nv 18.750000 100.000008 -56.250000\nv 25.000000 100.000008 -56.250000\nv 25.000000 81.250000 -56.250000\nv 18.750000 75.000008 -56.250000\nv 18.750000 100.000008 -43.750000\nv 25.000000 100.000008 -43.750000\nv 18.750000 75.000008 -43.750000\nv 25.000000 81.250000 -43.750000\nv 18.750000 75.000008 -52.000004\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.000000 0.000000\nvt 0.930000 0.190000\nvt 0.860000 0.170000\nf 2877/2815 2878/2816 2879/2817 2880/2818\nf 2878/2819 2877/2820 2881/2821 2882/2815\nf 2883/2822 2884/2823 2882/2824 2881/2825\nf 2878/2823 2882/2826 2884/2821 2879/2824\nf 2881/2827 2877/2822 2883/2828\nf 2883/2828 2877/2822 2880/2825\nf 2885/2829 2883/2829 2880/2829\nf 2879/2830 2880/2828 2885/2831\nf 2884/2819 2879/2830 2885/2831\nf 2884/2819 2885/2831 2883/2820\ng Mesh256 Side_Texture_Plate_Side46 Texture_Side_S3\nv 68.750000 25.000004 -18.750000\nv 68.750000 18.750000 -18.750000\nv 31.250000 18.750000 -18.750000\nv 31.250000 25.000004 -18.750000\nvt 0.000000 1.000000\nf 2886/2832 2887/2832 2888/2832 2889/2832\ng Mesh201 Mount_W_D\nv 0.000000 18.750000 -56.250000\nv 0.000000 25.000002 -56.250000\nv 18.750000 25.000002 -56.250000\nv 25.000000 18.750000 -56.250000\nv 0.000000 18.750000 -43.750000\nv 0.000000 25.000000 -43.750000\nv 25.000000 18.750000 -43.750000\nv 18.750000 25.000000 -43.750000\nv 25.000000 18.750000 -51.999996\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.130000\nvt 0.860000 0.190000\nvt 0.930000 0.110000\nvt 0.930000 0.190000\nf 2890/2833 2891/2834 2892/2835 2893/2836\nf 2891/2837 2890/2833 2894/2838 2895/2839\nf 2896/2840 2897/2841 2895/2842 2894/2843\nf 2891/2841 2895/2844 2897/2837 2892/2842\nf 2894/2845 2890/2840 2893/2843\nf 2894/2845 2893/2846 2898/2843\nf 2894/2845 2898/2846 2896/2847\nf 2897/2847 2892/2839 2893/2838\nf 2897/2847 2893/2838 2898/2848\nf 2897/2847 2898/2848 2896/2849\ng Mesh435 Side_Texture_Plate_Side8 Texture_Side_N1\nv 25.000000 31.250000 -99.999992\nv 18.750000 31.250000 -99.999992\nv 18.750000 68.750000 -99.999992\nv 25.000000 68.750000 -99.999992\nvt 0.000000 1.000000\nf 2899/2850 2900/2850 2901/2850 2902/2850\ng Mesh283 Inner_Plate_N\nv 31.250000 68.750000 -74.999992\nv 68.750000 68.750000 -74.999992\nv 68.750000 31.250000 -74.999992\nv 31.250000 31.250000 -74.999992\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2903/2851 2904/2852 2905/2853 2906/2854\ng Mesh519 Texture_Plate_N\nv 31.250000 68.750000 -81.250000\nv 68.750000 68.750000 -81.250000\nv 68.750000 31.250000 -81.250000\nv 31.250000 31.250000 -81.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 2907/2855 2908/2856 2909/2857 2910/2858\ng Mesh166 Mount_U_S\nv 43.750000 100.000000 -18.750000\nv 43.750000 100.000008 -24.999998\nv 43.750000 81.250000 -25.000002\nv 43.750000 75.000000 -18.750000\nv 56.250000 100.000000 -18.750000\nv 56.250000 100.000008 -24.999998\nv 56.250000 75.000000 -18.750000\nv 56.250000 81.250000 -25.000002\nv 48.000000 75.000000 -18.750000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.070000\nvt 0.860000 0.070000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.930000 0.190000\nvt 0.000000 0.000000\nf 2911/2859 2912/2860 2913/2861 2914/2862\nf 2912/2863 2911/2859 2915/2864 2916/2865\nf 2917/2866 2918/2867 2916/2865 2915/2868\nf 2912/2867 2916/2869 2918/2863 2913/2865\nf 2915/2870 2911/2866 2914/2868\nf 2917/2871 2915/2870 2914/2868\nf 2918/2871 2913/2865 2914/2864\nf 2917/2872 2918/2871 2914/2864\nf 2917/2873 2914/2873 2919/2873\ng Mesh235 Side_D2 Side_D\nv 81.250000 18.750000 -24.999996\nv 75.000000 18.750000 -18.750000\nv 75.000000 -0.000001 -18.750000\nv 81.250000 0.000000 -25.000000\nv 68.750000 -0.000001 -18.750000\nv 68.750000 18.750000 -18.750000\nv 68.750000 0.000000 -25.000000\nv 75.000000 0.000000 -25.000000\nv 68.750000 18.750000 -24.999996\nv 75.000000 18.750000 -24.999996\nv 75.000000 18.750000 -31.250000\nv 75.000000 0.000001 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 0.000001 -31.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.650000 0.850000\nvt 0.650000 0.780000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.650000 0.950000\nvt 0.700000 0.950000\nvt 0.700000 1.000000\nvt 0.650000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.950000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.650000 0.630000\nvt 0.650000 0.680000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.750000 0.900000\nvt 0.750000 0.950000\nvt 0.700000 0.900000\nf 2920/2874 2921/2875 2922/2876 2923/2877\nf 2924/2878 2922/2876 2921/2875 2925/2879\nf 2926/2880 2927/2881 2922/2882 2924/2883\nf 2927/2880 2926/2883 2928/2884 2929/2885\nf 2924/2878 2925/2879 2928/2885 2926/2880\nf 2929/2886 2930/2887 2931/2888 2927/2889\nf 2932/2890 2933/2891 2931/2889 2930/2886\nf 2920/2874 2923/2877 2933/2891 2932/2890\nf 2933/2892 2923/2893 2927/2881 2931/2894\nf 2922/2882 2927/2881 2923/2893\ng Mesh505 Edge_M_U_N\nv 31.250000 75.000015 -81.250000\nv 31.250000 81.250000 -74.999985\nv 68.750000 81.250000 -74.999985\nv 68.750000 75.000015 -81.250000\nv 68.750000 81.250000 -68.750000\nv 31.250000 81.250000 -68.750000\nv 31.250000 75.000008 -68.750000\nv 68.750000 75.000008 -68.750000\nv 68.750000 75.000015 -74.999985\nv 31.250000 75.000015 -74.999985\nv 31.250000 68.750000 -74.999992\nv 68.750000 68.750000 -74.999992\nv 31.250000 68.750000 -81.250000\nv 68.750000 68.750000 -81.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 2934/2895 2935/2896 2936/2897 2937/2898\nf 2938/2899 2936/2897 2935/2896 2939/2900\nf 2940/2900 2941/2899 2938/2901 2939/2902\nf 2942/2903 2941/2901 2940/2902 2943/2904\nf 2943/2905 2944/2906 2945/2907 2942/2908\nf 2945/2908 2944/2905 2946/2909 2947/2910\nf 2934/2895 2937/2898 2947/2910 2946/2909\ng Mesh604 Corner_M_U_NE\nv 75.000000 68.750000 -81.250000\nv 68.750000 68.750000 -81.250000\nv 68.750000 75.000015 -81.250000\nv 75.000000 75.000015 -81.250000\nv 75.000000 81.250000 -74.999985\nv 68.750000 81.250000 -74.999985\nv 81.250000 75.000015 -74.999985\nv 75.000000 81.250000 -68.750000\nv 81.250000 75.000008 -68.750000\nv 81.250000 68.750000 -68.750000\nv 81.250000 68.750000 -74.999992\nv 68.750000 81.250000 -68.750000\nvt 0.850000 0.500000\nvt 0.900000 0.500000\nvt 0.900000 0.550000\nvt 0.850000 0.550000\nvt 0.850000 0.630000\nvt 0.900000 0.630000\nvt 0.750000 0.730000\nvt 0.700000 0.820000\nvt 0.650000 0.730000\nvt 0.800000 0.630000\nvt 0.800000 0.550000\nvt 0.800000 0.500000\nvt 0.650000 0.650000\nvt 0.700000 0.650000\nvt 0.700000 0.730000\nvt 0.800000 0.450000\nvt 0.850000 0.450000\nf 2948/2911 2949/2912 2950/2913 2951/2914\nf 2952/2915 2951/2914 2950/2913 2953/2916\nf 2951/2917 2952/2918 2954/2919\nf 2955/2920 2956/2921 2954/2914 2952/2915\nf 2956/2921 2957/2922 2958/2911 2954/2914\nf 2958/2923 2948/2924 2951/2925 2954/2919\nf 2959/2911 2955/2922 2952/2926 2953/2927\ng Mesh206 Edge_Side_U_SW Side_U\nv 25.000000 100.000000 -18.750000\nv 18.750000 100.000008 -24.999998\nv 18.750000 81.250000 -25.000002\nv 25.000000 81.250000 -18.750000\nv 25.000000 100.000008 -24.999998\nv 31.250000 100.000000 -18.750000\nv 31.250000 100.000008 -24.999998\nv 31.250000 81.250000 -25.000002\nv 25.000000 81.250000 -25.000002\nv 31.250000 81.250000 -18.750000\nv 25.000000 81.250000 -31.250000\nv 25.000000 100.000008 -31.250000\nv 18.750000 81.250000 -31.250000\nv 18.750000 100.000008 -31.250000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 2960/2928 2961/2929 2962/2930 2963/2931\nf 2960/2932 2964/2933 2961/2934\nf 2960/2932 2965/2935 2966/2936 2964/2933\nf 2964/2935 2966/2936 2967/2937 2968/2938\nf 2967/2937 2966/2936 2965/2939 2969/2940\nf 2960/2928 2963/2931 2969/2941 2965/2942\nf 2968/2943 2970/2944 2971/2945 2964/2946\nf 2971/2945 2970/2944 2972/2941 2973/2942\nf 2972/2940 2962/2930 2961/2929 2973/2939\nf 2973/2947 2961/2934 2964/2933 2971/2948\ng Mesh394 Corner_I_U_NE2\nv 68.750000 81.250000 -74.999985\nv 68.750000 81.250000 -81.250000\nv 68.750000 68.750000 -81.250000\nv 68.750000 68.750000 -74.999992\nv 81.250000 81.250000 -74.999985\nv 81.250000 75.000015 -81.250000\nv 75.000000 81.250000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 81.250000 68.750000 -74.999992\nv 81.250000 75.000015 -74.999985\nv 81.250000 75.000008 -68.750000\nv 75.000000 75.000008 -68.750000\nv 75.000000 75.000015 -74.999985\nv 75.000000 81.250000 -68.750000\nv 81.250000 81.250000 -68.750000\nv 75.000000 81.250000 -74.999985\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.330000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.700000 0.230000\nvt 0.650000 0.230000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nf 2974/2949 2975/2950 2976/2951 2977/2952\nf 2978/2953 2979/2954 2980/2955\nf 2981/2950 2982/2949 2977/2956 2976/2957\nf 2983/2958 2984/2959 2985/2955 2986/2960\nf 2987/2961 2985/2962 2984/2963 2988/2964\nf 2987/2958 2989/2960 2986/2961 2985/2964\nf 2989/2959 2974/2958 2977/2965\nf 2986/2953 2989/2959 2977/2965\nf 2983/2966 2986/2953 2977/2965\nf 2982/2967 2983/2966 2977/2965\nf 2976/2968 2975/2965 2980/2969\nf 2976/2968 2980/2969 2979/2970\nf 2976/2968 2979/2970 2981/2963\ng Mesh339 Support_D_U\nv 43.750000 18.750000 -68.750000\nv 43.750000 18.750000 -31.250000\nv 43.750000 22.999998 -31.250000\nv 43.750000 22.999996 -68.750000\nv 56.250000 18.750000 -68.750000\nv 56.250000 18.750000 -31.250000\nv 56.250000 22.999996 -68.750000\nv 56.250000 22.999998 -31.250000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 2990/2971 2991/2972 2992/2973 2993/2974\nf 2991/2975 2990/2976 2994/2977 2995/2978\nf 2995/2979 2994/2980 2996/2974 2997/2973\nf 2997/2978 2996/2977 2993/2981 2992/2982\ng Mesh148 Corner_I_D_NW1\nv 25.000000 31.250000 -68.750000\nv 18.750000 31.250000 -68.750000\nv 18.750000 18.750000 -68.750000\nv 25.000000 18.750000 -68.750000\nv 25.000000 31.250000 -81.250000\nv 18.750000 31.250000 -81.250000\nv 31.250000 24.999996 -74.999992\nv 25.000000 24.999996 -74.999992\nv 25.000000 18.750000 -75.000000\nv 31.250000 18.750000 -75.000000\nv 31.250000 24.999998 -81.250000\nv 25.000000 24.999998 -81.250000\nv 31.250000 18.750000 -81.250000\nv 18.750000 18.750000 -75.000000\nv 18.750000 24.999998 -81.250000\nv 25.000000 18.750000 -81.250000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 2998/2983 2999/2984 3000/2985 3001/2986\nf 2999/2984 2998/2983 3002/2987 3003/2988\nf 3004/2989 3005/2990 3006/2991 3007/2992\nf 3005/2992 3004/2991 3008/2993 3009/2994\nf 3010/2994 3008/2993 3004/2995 3007/2996\nf 3011/2990 3012/2997 3013/2998\nf 3000/2996 2999/2999 3003/3000\nf 3000/2996 3003/3000 3012/3001\nf 3000/2996 3012/3001 3011/3002\nf 3005/2997 2998/3000 3001/3003\nf 3002/2992 2998/3000 3005/2997\nf 3009/2989 3002/2992 3005/2997\nf 3006/3004 3005/2997 3001/3003\ng Mesh7 Edge_Side_U_NW Side_U\nv 18.750000 100.000015 -75.000015\nv 25.000000 100.000015 -81.250000\nv 25.000000 81.250000 -81.250000\nv 18.750000 81.250000 -74.999985\nv 25.000000 100.000015 -75.000015\nv 18.750000 100.000008 -68.750000\nv 25.000000 100.000008 -68.750000\nv 25.000000 81.250000 -68.750000\nv 25.000000 81.250000 -74.999985\nv 18.750000 81.250000 -68.750000\nv 31.250000 81.250000 -74.999985\nv 31.250000 100.000015 -75.000015\nv 31.250000 81.250000 -81.250000\nv 31.250000 100.000015 -81.250000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 3014/3005 3015/3006 3016/3007 3017/3008\nf 3014/3009 3018/3010 3015/3011\nf 3014/3009 3019/3012 3020/3013 3018/3010\nf 3018/3012 3020/3013 3021/3014 3022/3015\nf 3021/3014 3020/3013 3019/3016 3023/3017\nf 3014/3005 3017/3008 3023/3018 3019/3019\nf 3022/3020 3024/3021 3025/3022 3018/3023\nf 3025/3022 3024/3021 3026/3018 3027/3019\nf 3026/3017 3016/3007 3015/3006 3027/3016\nf 3027/3024 3015/3011 3018/3010 3025/3025\ng Mesh379 Side_Texture_Plate_Side82 Texture_Side_D\nv 25.000000 18.750000 -68.750000\nv 18.750000 18.750000 -68.750000\nv 18.750000 18.750000 -31.250000\nv 25.000000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 3028/3026 3029/3026 3030/3026 3031/3026\ng Mesh188 Side_Texture_Plate_Side25 Texture_Side_E2\nv 100.000000 68.750000 -74.999992\nv 100.000000 68.750000 -81.250000\nv 100.000000 31.250000 -81.250000\nv 100.000000 31.250000 -74.999992\nvt 0.000000 1.000000\nf 3032/3027 3033/3027 3034/3027 3035/3027\ng Mesh529 Texture_Connector_Plate74 Texture_Connector_Plate_Mirror37 Texture_Connector_U_E\nv 68.750000 75.000008 -68.750000\nv 68.750000 75.000008 -31.250000\nv 81.250000 75.000008 -31.250000\nv 81.250000 75.000008 -68.750000\nvt 0.000000 1.000000\nf 3036/3028 3037/3028 3038/3028 3039/3028\ng Mesh252 Side_Texture_Plate34 Side_Texture_Plate_Mirror17 Texture_Side_S\nv 18.750000 68.750000 -18.750000\nv 18.750000 68.750000 0.000005\nv 18.750000 31.250000 0.000003\nv 18.750000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 3040/3029 3041/3029 3042/3029 3043/3029\ng Mesh220 Support_N_U\nv 43.750000 68.750000 -81.250000\nv 43.750000 31.250000 -81.250000\nv 43.750000 31.250000 -76.999992\nv 43.750000 68.750000 -76.999992\nv 56.250000 68.750000 -81.250000\nv 56.250000 31.250000 -81.250000\nv 56.250000 68.750000 -76.999992\nv 56.250000 31.250000 -76.999992\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 3044/3030 3045/3031 3046/3032 3047/3033\nf 3045/3034 3044/3035 3048/3036 3049/3037\nf 3049/3038 3048/3039 3050/3033 3051/3032\nf 3051/3037 3050/3036 3047/3040 3046/3041\ng Mesh138 Edge_Side_U_SE Side_U\nv 81.250000 100.000008 -24.999998\nv 75.000000 100.000000 -18.750000\nv 75.000000 81.250000 -18.750000\nv 81.250000 81.250000 -25.000002\nv 75.000000 100.000008 -24.999998\nv 81.250000 100.000008 -31.250000\nv 75.000000 100.000008 -31.250000\nv 75.000000 81.250000 -31.250000\nv 75.000000 81.250000 -25.000002\nv 81.250000 81.250000 -31.250000\nv 68.750000 81.250000 -25.000002\nv 68.750000 100.000008 -24.999998\nv 68.750000 81.250000 -18.750000\nv 68.750000 100.000000 -18.750000\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 3052/3042 3053/3043 3054/3044 3055/3045\nf 3052/3046 3056/3047 3053/3048\nf 3052/3046 3057/3049 3058/3050 3056/3047\nf 3056/3049 3058/3050 3059/3051 3060/3052\nf 3059/3051 3058/3050 3057/3053 3061/3054\nf 3052/3042 3055/3045 3061/3055 3057/3056\nf 3060/3057 3062/3058 3063/3059 3056/3060\nf 3063/3059 3062/3058 3064/3055 3065/3056\nf 3064/3054 3054/3044 3053/3043 3065/3053\nf 3065/3061 3053/3048 3056/3047 3063/3062\ng Mesh569 Side_Texture_Plate66 Side_Texture_Plate_Mirror33 Texture_Side_U\nv 18.750000 81.250000 -68.750000\nv 18.750000 100.000008 -68.750000\nv 18.750000 100.000008 -31.250000\nv 18.750000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 3066/3063 3067/3063 3068/3063 3069/3063\ng Mesh237 Mount_E_U\nv 75.000000 81.250000 -43.750000\nv 81.250000 75.000008 -43.750000\nv 100.000000 75.000008 -43.750000\nv 100.000000 81.250000 -43.750000\nv 81.250000 75.000008 -56.250000\nv 100.000000 75.000008 -56.250000\nv 100.000000 81.250000 -56.250000\nv 75.000000 81.250000 -56.250000\nv 75.000000 81.250000 -48.000004\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.070000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.650000 0.140000\nvt 0.930000 0.190000\nvt 0.860000 0.100000\nf 3070/3064 3071/3065 3072/3066 3073/3067\nf 3071/3065 3074/3068 3075/3069 3072/3066\nf 3076/3070 3075/3071 3074/3072 3077/3073\nf 3073/3069 3072/3070 3075/3074 3076/3066\nf 3076/3075 3077/3076 3078/3077\nf 3073/3067 3076/3075 3078/3077\nf 3078/3077 3070/3064 3073/3067\nf 3074/3078 3077/3075 3078/3079\nf 3071/3074 3074/3078 3078/3079\nf 3078/3079 3070/3066 3071/3074\ng Mesh518 Inner_BC_Side8 Side_BC_E\nv 97.000000 24.999998 -31.250000\nv 97.000000 25.000000 -49.999996\nv 100.000000 25.000000 -49.999996\nv 100.000000 24.999998 -31.250000\nv 100.000000 50.000004 -25.000000\nv 97.000000 50.000004 -25.000000\nv 97.000000 31.250000 -25.000002\nv 100.000000 31.250000 -25.000002\nv 81.250000 31.250000 -25.000002\nv 90.000000 31.250000 -25.000002\nv 90.000000 24.999996 -25.000004\nv 81.250000 24.999996 -25.000004\nv 81.250000 31.250000 -18.750000\nv 81.250000 25.000004 -18.750000\nv 81.250000 18.750000 -24.999996\nv 90.000000 24.999998 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 24.999998 -31.250000\nv 100.000000 24.999996 -25.000004\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 3079/3080 3080/3081 3081/3082 3082/3083\nf 3083/3081 3084/3084 3085/3085 3086/3080\nf 3087/3086 3088/3087 3089/3088 3090/3089\nf 3091/3082 3088/3090 3087/3091\nf 3089/3092 3088/3093 3091/3094 3092/3095\nf 3089/3096 3092/3097 3093/3082\nf 3094/3098 3089/3092 3093/3095 3095/3099\nf 3090/3098 3089/3099 3094/3087 3096/3086\nf 3094/3082 3095/3090 3096/3084\nf 3085/3100 3088/3092 3089/3093\nf 3086/3080 3085/3100 3089/3093\nf 3097/3085 3086/3080 3089/3093\nf 3094/3098 3079/3101 3089/3092\nf 3089/3092 3079/3101 3082/3083\nf 3089/3092 3082/3083 3097/3080\ng Mesh39 Side_Texture_Plate88 Side_Texture_Plate_Mirror44 Texture_Side_D1\nv 68.750000 18.750000 -24.999996\nv 68.750000 0.000002 -25.000000\nv 31.250000 0.000002 -25.000000\nv 31.250000 18.750000 -24.999996\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3098/3102 3099/3103 3100/3104 3101/3105\ng Mesh216 Side_Texture_Plate_Side15 Texture_Side_N3\nv 75.000000 68.750000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 81.250000 31.250000 -81.250000\nv 75.000000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 3102/3106 3103/3106 3104/3106 3105/3106\ng Mesh86 Edge_Side_S_DE Side_S\nv 81.250000 25.000000 0.000000\nv 75.000000 18.750000 -0.000001\nv 75.000000 18.750000 -18.750000\nv 81.250000 25.000004 -18.750000\nv 75.000000 25.000000 0.000000\nv 81.250000 31.250000 0.000001\nv 75.000000 31.250000 0.000001\nv 75.000000 31.250000 -18.750000\nv 75.000000 25.000004 -18.750000\nv 81.250000 31.250000 -18.750000\nv 68.750000 25.000004 -18.750000\nv 68.750000 25.000000 0.000000\nv 68.750000 18.750000 -18.750000\nv 68.750000 18.750000 -0.000001\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 3106/3107 3107/3108 3108/3109 3109/3110\nf 3106/3111 3110/3112 3107/3113\nf 3106/3111 3111/3114 3112/3115 3110/3112\nf 3110/3114 3112/3115 3113/3116 3114/3117\nf 3113/3116 3112/3115 3111/3118 3115/3119\nf 3106/3107 3109/3110 3115/3120 3111/3121\nf 3114/3122 3116/3123 3117/3124 3110/3125\nf 3117/3124 3116/3123 3118/3120 3119/3121\nf 3118/3119 3108/3109 3107/3108 3119/3118\nf 3119/3126 3107/3113 3110/3112 3117/3127\ng Mesh391 Side_BC_E\nv 100.000000 68.750000 -25.000004\nv 100.000000 50.000004 -25.000000\nv 97.000000 50.000004 -25.000000\nv 97.000000 68.750000 -25.000004\nv 100.000000 75.000008 -50.000004\nv 100.000000 75.000008 -31.250000\nv 97.000000 75.000008 -31.250000\nv 97.000000 75.000008 -50.000004\nv 90.000000 68.750000 -25.000004\nv 90.000000 75.000008 -25.000004\nv 100.000000 75.000008 -25.000004\nv 90.000000 75.000008 -31.250000\nvt 0.250000 0.480000\nvt 0.580000 0.480000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.130000 0.430000\nvt 0.130000 0.480000\nvt 0.000000 0.000000\nvt 0.130000 0.530000\nvt 0.210000 0.480000\nf 3120/3128 3121/3129 3122/3130 3123/3131\nf 3124/3129 3125/3128 3126/3132 3127/3133\nf 3128/3134 3129/3135 3130/3128\nf 3130/3128 3120/3132 3128/3134\nf 3128/3136 3120/3136 3123/3136\nf 3129/3137 3131/3135 3126/3138\nf 3126/3138 3125/3128 3129/3137\nf 3129/3137 3125/3128 3130/3131\ng Mesh500 Inner_BC_Side17 Side_BC_W\nv 3.000000 68.750000 -74.999992\nv 3.000000 49.999996 -74.999992\nv 0.000000 49.999996 -74.999992\nv 0.000000 68.750000 -74.999992\nv 0.000000 75.000008 -50.000004\nv 3.000000 75.000008 -50.000004\nv 3.000000 75.000008 -68.750000\nv 0.000000 75.000008 -68.750000\nv 18.750000 75.000008 -68.750000\nv 10.000000 75.000008 -68.750000\nv 10.000000 75.000015 -74.999985\nv 18.750000 75.000015 -74.999985\nv 18.750000 81.250000 -68.750000\nv 18.750000 81.250000 -74.999985\nv 18.750000 75.000015 -81.250000\nv 10.000000 68.750000 -74.999992\nv 18.750000 68.750000 -81.250000\nv 18.750000 68.750000 -74.999992\nv 0.000000 75.000015 -74.999985\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.130000 0.640000\nf 3132/3139 3133/3140 3134/3141 3135/3142\nf 3136/3140 3137/3143 3138/3144 3139/3139\nf 3140/3145 3141/3146 3142/3147 3143/3148\nf 3144/3141 3141/3149 3140/3150\nf 3142/3151 3141/3152 3144/3153 3145/3154\nf 3142/3155 3145/3156 3146/3141\nf 3147/3157 3142/3151 3146/3154 3148/3158\nf 3143/3157 3142/3158 3147/3146 3149/3145\nf 3147/3141 3148/3149 3149/3143\nf 3142/3152 3150/3144 3139/3139\nf 3141/3151 3142/3152 3139/3139\nf 3141/3159 3139/3159 3138/3159\nf 3135/3142 3150/3139 3142/3151\nf 3135/3142 3142/3151 3147/3157\nf 3132/3159 3135/3159 3147/3159\ng Mesh310 Side_BC_U\nv 25.000000 100.000008 -68.750000\nv 25.000000 100.000008 -50.000000\nv 25.000000 97.000008 -50.000000\nv 25.000000 97.000008 -68.750000\nv 50.000000 100.000015 -75.000015\nv 31.250000 100.000015 -75.000015\nv 31.250000 97.000015 -75.000015\nv 50.000000 97.000015 -75.000015\nv 25.000000 100.000015 -75.000015\nv 25.000000 90.000015 -75.000015\nv 25.000000 90.000008 -68.750000\nv 31.250000 90.000015 -75.000015\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.210000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.430000\nvt 0.130000 0.530000\nvt 0.210000 0.480000\nf 3151/3160 3152/3161 3153/3162 3154/3163\nf 3155/3162 3156/3163 3157/3164 3158/3165\nf 3159/3163 3151/3160 3154/3166\nf 3160/3167 3159/3163 3154/3166\nf 3160/3167 3154/3166 3161/3168\nf 3156/3163 3159/3164 3160/3169\nf 3157/3170 3156/3163 3160/3169\nf 3162/3167 3157/3170 3160/3169\ng Mesh211 Mount_S_E\nv 81.250000 43.750000 -0.000000\nv 75.000000 43.750000 -0.000000\nv 75.000000 43.750000 -18.750000\nv 81.250000 43.750000 -25.000000\nv 81.250000 56.250000 0.000001\nv 75.000000 56.250000 0.000001\nv 81.250000 56.250000 -24.999998\nv 75.000000 56.250000 -18.750000\nv 81.250000 48.000004 -25.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.860000 0.150000\nvt 0.930000 0.190000\nvt 0.860000 0.180000\nf 3163/3171 3164/3172 3165/3173 3166/3174\nf 3164/3175 3163/3176 3167/3177 3168/3171\nf 3169/3178 3170/3179 3168/3180 3167/3181\nf 3164/3177 3168/3180 3170/3179 3165/3182\nf 3167/3183 3163/3178 3169/3184\nf 3169/3184 3163/3178 3171/3185\nf 3171/3185 3163/3178 3166/3181\nf 3169/3176 3170/3175 3165/3186\nf 3171/3187 3169/3176 3165/3186\nf 3166/3184 3171/3187 3165/3186\ng Mesh264 Side_Texture_Plate79 Side_Texture_Plate_Mirror40 Texture_Side_U3\nv 75.000000 81.250000 -68.750000\nv 75.000000 100.000008 -68.750000\nv 75.000000 100.000008 -31.250000\nv 75.000000 81.250000 -31.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3172/3188 3173/3189 3174/3190 3175/3191\ng Mesh66 Side_BC_D\nv 25.000000 0.000001 -31.250000\nv 25.000000 0.000000 -50.000000\nv 25.000000 3.000000 -50.000000\nv 25.000000 3.000000 -31.250000\nv 50.000000 0.000000 -25.000000\nv 31.250000 0.000000 -25.000000\nv 31.250000 3.000000 -25.000000\nv 50.000000 3.000000 -25.000000\nv 25.000000 10.000001 -31.250000\nv 25.000000 10.000000 -24.999998\nv 25.000000 0.000000 -25.000000\nv 31.250000 10.000000 -24.999998\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.130000 0.480000\nvt 0.130000 0.540000\nvt 0.250000 0.540000\nvt 0.210000 0.480000\nvt 0.130000 0.430000\nvt 0.210000 0.430000\nf 3176/3192 3177/3193 3178/3194 3179/3195\nf 3180/3194 3181/3195 3182/3196 3183/3197\nf 3184/3198 3185/3199 3186/3200\nf 3179/3201 3184/3198 3186/3200\nf 3176/3195 3179/3201 3186/3200\nf 3186/3195 3185/3198 3187/3202\nf 3186/3195 3187/3202 3182/3203\nf 3182/3203 3181/3192 3186/3195\ng Mesh85 Texture_Connector_Plate9 Texture_Connector_Plate_Mirror5 Texture_Connector_E_U\nv 75.000000 81.250000 -31.250000\nv 75.000000 81.250000 -68.750000\nv 75.000000 68.750000 -68.750000\nv 75.000000 68.750000 -31.250000\nvt 0.000000 1.000000\nf 3188/3204 3189/3204 3190/3204 3191/3204\ng Mesh257 Side_Texture_Plate95 Side_Texture_Plate_Mirror48 Texture_Side_D3\nv 75.000000 18.750000 -31.250000\nv 75.000000 0.000003 -31.250000\nv 75.000000 0.000005 -68.750000\nv 75.000000 18.750000 -68.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3192/3205 3193/3206 3194/3207 3195/3208\ng Mesh573 Spacer8 Group3\nv 68.750000 24.999998 -31.250000\nv 68.750000 18.750000 -31.250000\nv 68.750000 18.750000 -18.750000\nv 68.750000 25.000004 -18.750000\nv 75.000000 18.750000 -18.750000\nv 75.000000 18.750000 -31.250000\nv 81.250000 25.000004 -18.750000\nv 81.250000 24.999998 -31.250000\nv 81.250000 31.250000 -31.250000\nv 81.250000 31.250000 -18.750000\nv 75.000000 31.250000 -18.750000\nv 75.000000 31.250000 -31.250000\nv 75.000000 25.000004 -18.750000\nv 75.000000 24.999998 -31.250000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3196/3209 3197/3210 3198/3211 3199/3212\nf 3200/3213 3198/3211 3197/3210 3201/3214\nf 3202/3215 3200/3213 3201/3214 3203/3216\nf 3203/3216 3204/3217 3205/3218 3202/3215\nf 3206/3219 3205/3218 3204/3217 3207/3220\nf 3208/3221 3206/3219 3207/3220 3209/3222\nf 3209/3223 3196/3209 3199/3212 3208/3224\ng Mesh349 Side_Texture_Plate86 Side_Texture_Plate_Mirror43 Texture_Side_D1\nv 68.750000 18.750000 -18.750000\nv 68.750000 0.000001 -18.750000\nv 31.250000 0.000001 -18.750000\nv 31.250000 18.750000 -18.750000\nvt 0.000000 1.000000\nf 3210/3225 3211/3225 3212/3225 3213/3225\ng Mesh292 Texture_Plate_E\nv 81.250000 68.750000 -68.750000\nv 81.250000 68.750000 -31.250000\nv 81.250000 31.250000 -31.250000\nv 81.250000 31.250000 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 3214/3226 3215/3227 3216/3228 3217/3229\ng Mesh28 Side_Texture_Plate65 Side_Texture_Plate_Mirror33 Texture_Side_U\nv 18.750000 81.250000 -31.250000\nv 18.750000 100.000008 -31.250000\nv 18.750000 100.000008 -68.750000\nv 18.750000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 3218/3230 3219/3230 3220/3230 3221/3230\ng Mesh158 Side_Texture_Plate36 Side_Texture_Plate_Mirror18 Texture_Side_S\nv 25.000000 68.750000 -18.750000\nv 25.000000 68.750000 0.000005\nv 25.000000 31.250000 0.000003\nv 25.000000 31.250000 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3222/3231 3223/3232 3224/3233 3225/3234\ng Mesh293 Spacer11 Group4\nv 68.750000 31.250000 -25.000002\nv 68.750000 31.250000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 81.250000 31.250000 -25.000002\nv 81.250000 25.000004 -18.750000\nv 68.750000 25.000004 -18.750000\nv 81.250000 18.750000 -24.999996\nv 68.750000 18.750000 -24.999996\nv 68.750000 18.750000 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 24.999998 -31.250000\nv 68.750000 24.999998 -31.250000\nv 81.250000 24.999996 -25.000004\nv 68.750000 24.999996 -25.000004\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3226/3235 3227/3236 3228/3237 3229/3238\nf 3230/3239 3228/3237 3227/3236 3231/3240\nf 3232/3241 3230/3239 3231/3240 3233/3242\nf 3233/3242 3234/3243 3235/3244 3232/3241\nf 3236/3245 3235/3244 3234/3243 3237/3246\nf 3238/3247 3236/3245 3237/3246 3239/3248\nf 3239/3249 3226/3235 3229/3238 3238/3250\ng Mesh240 Spacer4 Group2\nv 31.250000 24.999996 -68.750000\nv 31.250000 18.750000 -68.750000\nv 31.250000 18.750000 -81.250000\nv 31.250000 24.999998 -81.250000\nv 25.000000 18.750000 -81.250000\nv 25.000000 18.750000 -68.750000\nv 18.750000 24.999998 -81.250000\nv 18.750000 24.999996 -68.750000\nv 18.750000 31.250000 -68.750000\nv 18.750000 31.250000 -81.250000\nv 25.000000 31.250000 -81.250000\nv 25.000000 31.250000 -68.750000\nv 25.000000 24.999998 -81.250000\nv 25.000000 24.999996 -68.750000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3240/3251 3241/3252 3242/3253 3243/3254\nf 3244/3255 3242/3253 3241/3252 3245/3256\nf 3246/3257 3244/3255 3245/3256 3247/3258\nf 3247/3258 3248/3259 3249/3260 3246/3257\nf 3250/3261 3249/3260 3248/3259 3251/3262\nf 3252/3263 3250/3261 3251/3262 3253/3264\nf 3253/3265 3240/3251 3243/3254 3252/3266\ng Mesh319 Inner_BC_Side11 Side_BC_S\nv 75.000000 31.250000 -3.000000\nv 75.000000 50.000000 -3.000000\nv 75.000000 50.000000 0.000000\nv 75.000000 31.250000 0.000001\nv 50.000000 25.000000 0.000000\nv 50.000000 25.000000 -3.000000\nv 68.750000 25.000000 -3.000000\nv 68.750000 25.000000 0.000000\nv 68.750000 25.000004 -18.750000\nv 68.750000 25.000002 -10.000000\nv 75.000000 25.000002 -10.000000\nv 75.000000 25.000004 -18.750000\nv 68.750000 18.750000 -18.750000\nv 75.000000 18.750000 -18.750000\nv 81.250000 25.000004 -18.750000\nv 75.000000 31.250000 -9.999999\nv 81.250000 31.250000 -18.750000\nv 75.000000 31.250000 -18.750000\nv 75.000000 25.000000 0.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 3254/3267 3255/3268 3256/3269 3257/3270\nf 3258/3268 3259/3271 3260/3272 3261/3267\nf 3262/3273 3263/3274 3264/3275 3265/3276\nf 3266/3269 3263/3277 3262/3278\nf 3264/3279 3263/3280 3266/3281 3267/3282\nf 3264/3283 3267/3284 3268/3269\nf 3269/3285 3264/3279 3268/3282 3270/3286\nf 3265/3285 3264/3286 3269/3274 3271/3273\nf 3269/3269 3270/3277 3271/3271\nf 3260/3287 3263/3279 3264/3280\nf 3260/3287 3264/3280 3272/3272\nf 3261/3267 3260/3287 3272/3272\nf 3254/3288 3257/3270 3272/3267\nf 3269/3285 3254/3288 3272/3267\nf 3264/3279 3269/3285 3272/3267\ng Mesh213 Side_BC_E\nv 100.000000 75.000008 -68.750000\nv 100.000000 75.000008 -50.000004\nv 97.000000 75.000008 -50.000004\nv 97.000000 75.000008 -68.750000\nv 100.000000 49.999996 -74.999992\nv 100.000000 68.750000 -74.999992\nv 97.000000 68.750000 -74.999992\nv 97.000000 49.999996 -74.999992\nv 90.000000 75.000008 -68.750000\nv 90.000000 75.000015 -74.999985\nv 100.000000 75.000015 -74.999985\nv 90.000000 68.750000 -74.999992\nvt 0.250000 0.480000\nvt 0.580000 0.480000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.140000 0.430000\nvt 0.140000 0.480000\nvt 0.000000 0.000000\nvt 0.140000 0.530000\nf 3273/3289 3274/3290 3275/3291 3276/3292\nf 3277/3290 3278/3289 3279/3293 3280/3294\nf 3281/3295 3282/3296 3283/3289\nf 3283/3289 3273/3293 3281/3295\nf 3281/3297 3273/3297 3276/3297\nf 3283/3292 3282/3298 3284/3296\nf 3278/3289 3283/3292 3284/3296\nf 3278/3297 3284/3297 3279/3297\ng Mesh270 Texture_Connector_Plate55 Texture_Connector_Plate_Mirror28 Texture_Connector_S_U\nv 31.250000 81.250000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 68.750000 68.750000 -18.750000\nv 31.250000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 3285/3299 3286/3299 3287/3299 3288/3299\ng Mesh207 Spacer2 Group2\nv 68.750000 75.000008 -68.750000\nv 68.750000 81.250000 -68.750000\nv 68.750000 81.250000 -81.250000\nv 68.750000 75.000015 -81.250000\nv 75.000000 81.250000 -81.250000\nv 75.000000 81.250000 -68.750000\nv 81.250000 75.000015 -81.250000\nv 81.250000 75.000008 -68.750000\nv 81.250000 68.750000 -68.750000\nv 81.250000 68.750000 -81.250000\nv 75.000000 68.750000 -81.250000\nv 75.000000 68.750000 -68.750000\nv 75.000000 75.000015 -81.250000\nv 75.000000 75.000008 -68.750000\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3289/3300 3290/3301 3291/3302 3292/3303\nf 3293/3304 3291/3302 3290/3301 3294/3305\nf 3295/3306 3293/3304 3294/3305 3296/3307\nf 3296/3307 3297/3308 3298/3309 3295/3306\nf 3299/3310 3298/3309 3297/3308 3300/3311\nf 3301/3312 3299/3310 3300/3311 3302/3313\nf 3302/3314 3289/3300 3292/3303 3301/3315\ng Mesh389 Mount_E_D\nv 100.000000 18.750000 -43.750000\nv 100.000000 25.000000 -43.750000\nv 81.250000 25.000000 -43.750000\nv 75.000000 18.750000 -43.750000\nv 100.000000 18.750000 -56.250000\nv 100.000000 25.000002 -56.250000\nv 75.000000 18.750000 -56.250000\nv 81.250000 25.000002 -56.250000\nv 75.000000 18.750000 -47.999996\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.180000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.930000 0.110000\nvt 0.930000 0.190000\nf 3303/3316 3304/3317 3305/3318 3306/3319\nf 3304/3320 3303/3316 3307/3321 3308/3322\nf 3309/3323 3310/3324 3308/3325 3307/3326\nf 3304/3320 3308/3325 3310/3324 3305/3327\nf 3311/3328 3309/3323 3307/3326\nf 3307/3326 3303/3329 3311/3328\nf 3311/3328 3303/3329 3306/3330\nf 3311/3331 3309/3332 3310/3329\nf 3311/3331 3310/3329 3305/3322\nf 3306/3321 3311/3331 3305/3322\ng Mesh152 Inner_Plate_D\nv 31.250000 24.999996 -68.750000\nv 68.750000 24.999996 -68.750000\nv 68.750000 24.999998 -31.250000\nv 31.250000 24.999998 -31.250000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 3312/3333 3313/3334 3314/3335 3315/3336\ng Mesh545 Side_Texture_Plate13 Side_Texture_Plate_Mirror7 Texture_Side_N3\nv 81.250000 31.250000 -81.250000\nv 81.250000 31.250000 -99.999992\nv 81.250000 68.750000 -99.999992\nv 81.250000 68.750000 -81.250000\nvt 0.000000 1.000000\nf 3316/3337 3317/3337 3318/3337 3319/3337\ng Mesh8 Side_Texture_Plate_Side17 Texture_Side_E\nv 100.000000 31.250000 -24.999998\nv 100.000000 31.250000 -18.750000\nv 100.000000 68.750000 -18.750000\nv 100.000000 68.750000 -24.999996\nvt 0.000000 1.000000\nf 3320/3338 3321/3338 3322/3338 3323/3338\ng Mesh551 Edge_Side_S_UE Side_S\nv 75.000000 81.250000 0.000001\nv 81.250000 75.000000 0.000000\nv 81.250000 75.000000 -18.750000\nv 75.000000 81.250000 -18.750000\nv 75.000000 75.000000 0.000000\nv 68.750000 81.250000 0.000001\nv 68.750000 75.000000 0.000000\nv 68.750000 75.000000 -18.750000\nv 75.000000 75.000000 -18.750000\nv 68.750000 81.250000 -18.750000\nv 75.000000 68.750000 -18.750000\nv 75.000000 68.750000 -0.000001\nv 81.250000 68.750000 -18.750000\nv 81.250000 68.750000 -0.000001\nvt 0.650000 0.780000\nvt 0.650000 0.850000\nvt 0.400000 0.850000\nvt 0.400000 0.780000\nvt 0.700000 1.000000\nvt 0.700000 0.950000\nvt 0.750000 0.950000\nvt 0.650000 1.000000\nvt 0.650000 0.950000\nvt 0.400000 0.950000\nvt 0.400000 1.000000\nvt 0.650000 0.900000\nvt 0.400000 0.900000\nvt 0.400000 0.730000\nvt 0.650000 0.730000\nvt 0.400000 0.630000\nvt 0.400000 0.680000\nvt 0.650000 0.680000\nvt 0.650000 0.630000\nvt 0.750000 0.900000\nvt 0.700000 0.900000\nf 3324/3339 3325/3340 3326/3341 3327/3342\nf 3324/3343 3328/3344 3325/3345\nf 3324/3343 3329/3346 3330/3347 3328/3344\nf 3328/3346 3330/3347 3331/3348 3332/3349\nf 3331/3348 3330/3347 3329/3350 3333/3351\nf 3324/3339 3327/3342 3333/3352 3329/3353\nf 3332/3354 3334/3355 3335/3356 3328/3357\nf 3335/3356 3334/3355 3336/3352 3337/3353\nf 3336/3351 3326/3341 3325/3340 3337/3350\nf 3337/3358 3325/3345 3328/3344 3335/3359\ng Mesh97 Side_Texture_Plate_Side50 Texture_Side_W\nv 18.750000 68.750000 -24.999996\nv 18.750000 68.750000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 18.750000 31.250000 -24.999998\nvt 0.000000 1.000000\nf 3338/3360 3339/3360 3340/3360 3341/3360\ng Mesh145 Side_BC_U\nv 31.250000 100.000008 -24.999998\nv 50.000000 100.000008 -24.999998\nv 50.000000 97.000008 -25.000000\nv 31.250000 97.000008 -25.000000\nv 25.000000 100.000008 -50.000000\nv 25.000000 100.000008 -31.250000\nv 25.000000 97.000008 -31.250000\nv 25.000000 97.000008 -50.000000\nv 25.000000 100.000008 -24.999998\nv 25.000000 90.000008 -25.000000\nv 31.250000 90.000008 -25.000000\nv 25.000000 90.000008 -31.250000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.130000 0.530000\nvt 0.220000 0.480000\nvt 0.130000 0.480000\nvt 0.220000 0.430000\nvt 0.130000 0.430000\nf 3342/3361 3343/3362 3344/3363 3345/3364\nf 3346/3363 3347/3364 3348/3365 3349/3366\nf 3350/3365 3342/3364 3351/3367\nf 3351/3367 3342/3364 3345/3368\nf 3351/3367 3345/3368 3352/3369\nf 3347/3361 3350/3364 3351/3369\nf 3348/3370 3347/3361 3351/3369\nf 3353/3371 3348/3370 3351/3369\ng Mesh444 Corner_I_U_NE1\nv 75.000000 68.750000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 81.250000 68.750000 -68.750000\nv 75.000000 68.750000 -68.750000\nv 75.000000 81.250000 -81.250000\nv 81.250000 81.250000 -74.999985\nv 81.250000 75.000015 -81.250000\nv 81.250000 81.250000 -68.750000\nv 75.000000 81.250000 -68.750000\nv 75.000000 81.250000 -74.999985\nv 68.750000 81.250000 -74.999985\nv 68.750000 75.000015 -74.999985\nv 75.000000 75.000015 -74.999985\nv 68.750000 75.000015 -81.250000\nv 68.750000 81.250000 -81.250000\nv 75.000000 75.000015 -81.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nf 3354/3372 3355/3373 3356/3374 3357/3375\nf 3358/3376 3359/3377 3360/3378\nf 3361/3375 3362/3374 3357/3379 3356/3380\nf 3363/3381 3364/3382 3365/3383 3366/3378\nf 3367/3384 3365/3385 3364/3386 3368/3387\nf 3367/3382 3369/3381 3366/3384 3365/3387\nf 3357/3388 3362/3389 3363/3390\nf 3357/3388 3363/3390 3366/3376\nf 3357/3388 3366/3376 3369/3383\nf 3369/3383 3354/3382 3357/3388\nf 3359/3391 3361/3386 3356/3392\nf 3360/3393 3359/3391 3356/3392\nf 3355/3388 3360/3393 3356/3392\ng Mesh335 Inner_BC_Side3 Side_BC_N\nv 25.000000 31.250000 -96.999992\nv 25.000000 50.000000 -96.999992\nv 25.000000 50.000000 -99.999992\nv 25.000000 31.250000 -99.999992\nv 50.000000 25.000002 -99.999992\nv 50.000000 25.000000 -96.999992\nv 31.250000 25.000000 -96.999992\nv 31.250000 25.000002 -99.999992\nv 31.250000 24.999998 -81.250000\nv 31.250000 25.000000 -89.999992\nv 25.000000 25.000000 -89.999992\nv 25.000000 24.999998 -81.250000\nv 31.250000 18.750000 -81.250000\nv 25.000000 18.750000 -81.250000\nv 18.750000 24.999998 -81.250000\nv 25.000000 31.250000 -89.999992\nv 18.750000 31.250000 -81.250000\nv 25.000000 31.250000 -81.250000\nv 25.000000 25.000002 -99.999992\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.220000 0.530000\nvt 0.220000 0.580000\nf 3370/3394 3371/3395 3372/3396 3373/3397\nf 3374/3395 3375/3398 3376/3399 3377/3394\nf 3378/3400 3379/3401 3380/3402 3381/3403\nf 3382/3396 3379/3404 3378/3405\nf 3380/3406 3379/3407 3382/3408 3383/3409\nf 3380/3410 3383/3411 3384/3396\nf 3385/3412 3380/3406 3384/3409 3386/3413\nf 3381/3412 3380/3413 3385/3401 3387/3400\nf 3385/3396 3386/3404 3387/3398\nf 3380/3406 3388/3394 3377/3397\nf 3380/3406 3377/3397 3376/3414\nf 3380/3406 3376/3414 3379/3412\nf 3385/3406 3370/3415 3380/3407\nf 3380/3407 3370/3415 3373/3394\nf 3380/3407 3373/3394 3388/3399\ng Mesh167 Edge_M_S_NE\nv 75.000000 68.750000 -81.250000\nv 81.250000 68.750000 -74.999992\nv 81.250000 31.250000 -74.999992\nv 75.000000 31.250000 -81.250000\nv 81.250000 31.250000 -68.750000\nv 81.250000 68.750000 -68.750000\nv 75.000000 68.750000 -68.750000\nv 75.000000 31.250000 -68.750000\nv 75.000000 31.250000 -74.999992\nv 75.000000 68.750000 -74.999992\nv 68.750000 68.750000 -74.999992\nv 68.750000 31.250000 -74.999992\nv 68.750000 68.750000 -81.250000\nv 68.750000 31.250000 -81.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 3389/3416 3390/3417 3391/3418 3392/3419\nf 3393/3420 3391/3418 3390/3417 3394/3421\nf 3395/3421 3396/3420 3393/3422 3394/3423\nf 3397/3424 3396/3422 3395/3423 3398/3425\nf 3398/3426 3399/3427 3400/3428 3397/3429\nf 3400/3429 3399/3426 3401/3430 3402/3431\nf 3389/3416 3392/3419 3402/3431 3401/3430\ng Mesh56 Side_BC_W\nv 0.000000 24.999996 -68.750000\nv 0.000000 25.000000 -49.999996\nv 3.000000 25.000000 -49.999996\nv 3.000000 24.999996 -68.750000\nv 0.000000 49.999996 -74.999992\nv 0.000000 31.250000 -74.999992\nv 3.000000 31.250000 -74.999992\nv 3.000000 49.999996 -74.999992\nv 0.000000 24.999996 -74.999992\nv 10.000000 24.999996 -74.999992\nv 10.000000 24.999996 -68.750000\nv 10.000000 31.250000 -74.999992\nvt 0.250000 0.530000\nvt 0.580000 0.530000\nvt 0.580000 0.480000\nvt 0.250000 0.480000\nvt 0.250000 0.430000\nvt 0.580000 0.430000\nvt 0.130000 0.480000\nvt 0.130000 0.430000\nvt 0.000000 0.000000\nvt 0.210000 0.480000\nvt 0.130000 0.530000\nf 3403/3432 3404/3433 3405/3434 3406/3435\nf 3407/3434 3408/3435 3409/3436 3410/3437\nf 3411/3435 3403/3436 3412/3438\nf 3412/3438 3403/3436 3413/3439\nf 3413/3440 3403/3440 3406/3440\nf 3409/3441 3408/3435 3411/3432\nf 3414/3438 3409/3441 3411/3432\nf 3412/3442 3414/3438 3411/3432\ng Mesh45 Texture_Connector_Plate8 Texture_Connector_Plate_Mirror4 Texture_Connector_E_N\nv 81.250000 31.250000 -81.250000\nv 81.250000 68.750000 -81.250000\nv 81.250000 68.750000 -68.750000\nv 81.250000 31.250000 -68.750000\nvt 0.000000 1.000000\nf 3415/3443 3416/3443 3417/3443 3418/3443\ng Mesh568 Side_Texture_Plate_Side94 Texture_Side_D3\nv 75.000000 18.750000 -31.250000\nv 81.250000 18.750000 -31.250000\nv 81.250000 18.750000 -68.750000\nv 75.000000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 3419/3444 3420/3444 3421/3444 3422/3444\ng Mesh420 Mount_U_N\nv 56.250000 100.000015 -81.250000\nv 56.250000 100.000015 -75.000015\nv 56.250000 81.250000 -74.999985\nv 56.250000 75.000015 -81.250000\nv 43.750000 100.000015 -81.250000\nv 43.750000 100.000015 -75.000015\nv 43.750000 75.000015 -81.250000\nv 43.750000 81.250000 -74.999985\nv 52.000000 75.000015 -81.250000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.000000 0.000000\nvt 0.880000 0.190000\nvt 0.930000 0.190000\nf 3423/3445 3424/3446 3425/3447 3426/3448\nf 3424/3449 3423/3450 3427/3451 3428/3445\nf 3429/3452 3430/3453 3428/3450 3427/3454\nf 3424/3453 3428/3455 3430/3451 3425/3450\nf 3427/3456 3423/3452 3429/3457\nf 3429/3457 3423/3452 3426/3454\nf 3431/3458 3429/3458 3426/3458\nf 3431/3459 3429/3460 3430/3449\nf 3426/3457 3431/3459 3430/3449\nf 3425/3450 3426/3457 3430/3449\ng Mesh118 Spacer18 Group6\nv 75.000000 31.250000 -31.250000\nv 81.250000 31.250000 -31.250000\nv 81.250000 18.750000 -31.250000\nv 75.000000 18.750000 -31.250000\nv 81.250000 18.750000 -24.999996\nv 81.250000 31.250000 -25.000002\nv 75.000000 18.750000 -18.750000\nv 75.000000 31.250000 -18.750000\nv 68.750000 31.250000 -18.750000\nv 68.750000 18.750000 -18.750000\nv 68.750000 18.750000 -24.999996\nv 68.750000 31.250000 -25.000002\nv 75.000000 18.750000 -24.999996\nv 75.000000 31.250000 -25.000002\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3432/3461 3433/3462 3434/3463 3435/3464\nf 3436/3465 3434/3463 3433/3462 3437/3466\nf 3438/3467 3436/3465 3437/3466 3439/3468\nf 3439/3468 3440/3469 3441/3470 3438/3467\nf 3442/3471 3441/3470 3440/3469 3443/3472\nf 3444/3473 3442/3471 3443/3472 3445/3474\nf 3445/3475 3432/3461 3435/3464 3444/3476\ng Mesh594 Side_Texture_Plate30 Side_Texture_Plate_Mirror15 Texture_Side_E3\nv 81.250000 18.750000 -31.250000\nv 100.000000 18.750000 -31.250000\nv 100.000000 18.750000 -68.750000\nv 81.250000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 3446/3477 3447/3477 3448/3477 3449/3477\ng Mesh109 Edge_M_D_W\nv 18.750000 24.999996 -68.750000\nv 25.000000 18.750000 -68.750000\nv 25.000000 18.750000 -31.250000\nv 18.750000 24.999998 -31.250000\nv 31.250000 18.750000 -31.250000\nv 31.250000 18.750000 -68.750000\nv 31.250000 24.999996 -68.750000\nv 31.250000 24.999998 -31.250000\nv 25.000000 24.999998 -31.250000\nv 25.000000 24.999996 -68.750000\nv 25.000000 31.250000 -68.750000\nv 25.000000 31.250000 -31.250000\nv 18.750000 31.250000 -68.750000\nv 18.750000 31.250000 -31.250000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 3450/3478 3451/3479 3452/3480 3453/3481\nf 3454/3482 3452/3480 3451/3479 3455/3483\nf 3456/3483 3457/3482 3454/3484 3455/3485\nf 3458/3486 3457/3484 3456/3485 3459/3487\nf 3459/3488 3460/3489 3461/3490 3458/3491\nf 3461/3491 3460/3488 3462/3492 3463/3493\nf 3450/3478 3453/3481 3463/3493 3462/3492\ng Mesh196 Side_Texture_Plate_Side86 Texture_Side_D1\nv 31.250000 18.750000 -24.999996\nv 31.250000 18.750000 -18.750000\nv 68.750000 18.750000 -18.750000\nv 68.750000 18.750000 -24.999996\nvt 0.000000 1.000000\nf 3464/3494 3465/3494 3466/3494 3467/3494\ng Mesh405 Texture_Connector_Plate47 Texture_Connector_Plate_Mirror24 Texture_Connector_W_D\nv 18.750000 31.250000 -68.750000\nv 18.750000 31.250000 -31.250000\nv 18.750000 18.750000 -31.250000\nv 18.750000 18.750000 -68.750000\nvt 0.000000 1.000000\nf 3468/3495 3469/3495 3470/3495 3471/3495\ng Mesh438 Side_Texture_Plate_Side37 Texture_Side_S1\nv 31.250000 75.000000 0.000006\nv 31.250000 81.250000 0.000007\nv 68.750000 81.250000 0.000007\nv 68.750000 75.000000 0.000006\nvt 0.000000 1.000000\nf 3472/3496 3473/3496 3474/3496 3475/3496\ng Mesh538 Corner_M_D_SE\nv 75.000000 24.999998 -31.250000\nv 75.000000 24.999996 -25.000004\nv 75.000000 31.250000 -25.000002\nv 75.000000 31.250000 -31.250000\nv 68.750000 24.999998 -31.250000\nv 68.750000 24.999996 -25.000004\nv 68.750000 31.250000 -25.000002\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 3476/3497 3477/3498 3478/3499 3479/3500\nf 3476/3499 3480/3501 3481/3502 3477/3500\nf 3481/3501 3482/3503 3478/3504 3477/3502\ng Mesh239 Corner_I3_D_NW\nv 18.750000 24.999998 -81.250000\nv 25.000000 18.750000 -81.250000\nv 18.750000 18.750000 -75.000000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 3483/3505 3484/3506 3485/3507\ng Mesh502 Texture_Connector_Plate65 Texture_Connector_Plate_Mirror33 Texture_Connector_S_W\nv 18.750000 31.250000 -25.000002\nv 18.750000 68.750000 -25.000004\nv 31.250000 68.750000 -25.000004\nv 31.250000 31.250000 -25.000002\nvt 0.000000 1.000000\nf 3486/3508 3487/3508 3488/3508 3489/3508\ng Mesh513 Mount_D_S\nv 56.250000 -0.000001 -18.750000\nv 56.250000 0.000000 -25.000000\nv 56.250000 18.750000 -24.999996\nv 56.250000 25.000004 -18.750000\nv 43.750000 -0.000001 -18.750000\nv 43.750000 0.000000 -25.000000\nv 43.750000 25.000004 -18.750000\nv 43.750000 18.750000 -24.999996\nv 52.000000 25.000004 -18.750000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.180000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.930000 0.190000\nvt 0.890000 0.190000\nf 3490/3509 3491/3510 3492/3511 3493/3512\nf 3491/3513 3490/3514 3494/3515 3495/3509\nf 3496/3516 3497/3517 3495/3518 3494/3519\nf 3491/3517 3495/3520 3497/3515 3492/3518\nf 3498/3521 3496/3516 3494/3519\nf 3493/3522 3498/3521 3494/3519\nf 3490/3523 3493/3522 3494/3519\nf 3496/3523 3497/3514 3492/3513\nf 3496/3523 3492/3513 3493/3524\nf 3498/3525 3496/3523 3493/3524\ng Mesh110 Texture_Connector_Plate81 Texture_Connector_Plate_Mirror41 Texture_Connector_D_S\nv 31.250000 25.000004 -18.750000\nv 68.750000 25.000004 -18.750000\nv 68.750000 24.999998 -31.250000\nv 31.250000 24.999998 -31.250000\nvt 0.000000 1.000000\nf 3499/3526 3500/3526 3501/3526 3502/3526\ng Mesh306 Edge_M_S_SW\nv 25.000000 68.750000 -18.750000\nv 18.750000 68.750000 -25.000004\nv 18.750000 31.250000 -25.000002\nv 25.000000 31.250000 -18.750000\nv 18.750000 31.250000 -31.250000\nv 18.750000 68.750000 -31.250000\nv 25.000000 68.750000 -31.250000\nv 25.000000 31.250000 -31.250000\nv 25.000000 31.250000 -25.000002\nv 25.000000 68.750000 -25.000004\nv 31.250000 68.750000 -25.000004\nv 31.250000 31.250000 -25.000002\nv 31.250000 68.750000 -18.750000\nv 31.250000 31.250000 -18.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 3503/3527 3504/3528 3505/3529 3506/3530\nf 3507/3531 3505/3529 3504/3528 3508/3532\nf 3509/3532 3510/3531 3507/3533 3508/3534\nf 3511/3535 3510/3533 3509/3534 3512/3536\nf 3512/3537 3513/3538 3514/3539 3511/3540\nf 3514/3540 3513/3537 3515/3541 3516/3542\nf 3503/3527 3506/3530 3516/3542 3515/3541\ng Mesh301 Side_Texture_Plate_Side2 Texture_Side_N\nv 68.750000 75.000015 -81.250000\nv 68.750000 81.250000 -81.250000\nv 31.250000 81.250000 -81.250000\nv 31.250000 75.000015 -81.250000\nvt 0.000000 1.000000\nf 3517/3543 3518/3543 3519/3543 3520/3543\ng Mesh309 Texture_Connector_Plate22 Texture_Connector_Plate_Mirror11 Texture_Connector_N_D\nv 31.250000 31.250000 -74.999992\nv 68.750000 31.250000 -74.999992\nv 68.750000 18.750000 -75.000000\nv 31.250000 18.750000 -75.000000\nvt 0.000000 1.000000\nf 3521/3544 3522/3544 3523/3544 3524/3544\ng Mesh198 Side_Texture_Plate37 Side_Texture_Plate_Mirror19 Texture_Side_S1\nv 31.250000 81.250000 -18.750000\nv 31.250000 81.250000 0.000007\nv 68.750000 81.250000 0.000007\nv 68.750000 81.250000 -18.750000\nvt 0.000000 1.000000\nf 3525/3545 3526/3545 3527/3545 3528/3545\ng Mesh177 Texture_Plate_S\nv 68.750000 68.750000 -18.750000\nv 31.250000 68.750000 -18.750000\nv 31.250000 31.250000 -18.750000\nv 68.750000 31.250000 -18.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 3529/3546 3530/3547 3531/3548 3532/3549\ng Mesh197 Side_Texture_Plate_Side43 Texture_Side_S2\nv 75.000000 31.250000 -18.750000\nv 81.250000 31.250000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 75.000000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 3533/3550 3534/3550 3535/3550 3536/3550\ng Mesh446 Inner_BC_Side22 Side_BC_D\nv 25.000000 3.000000 -31.250000\nv 25.000000 3.000000 -50.000000\nv 25.000000 0.000000 -50.000000\nv 25.000000 0.000001 -31.250000\nv 50.000000 0.000000 -25.000000\nv 50.000000 3.000000 -25.000000\nv 31.250000 3.000000 -25.000000\nv 31.250000 0.000000 -25.000000\nv 31.250000 18.750000 -24.999996\nv 31.250000 10.000000 -24.999998\nv 25.000000 10.000000 -24.999998\nv 25.000000 18.750000 -24.999996\nv 31.250000 18.750000 -18.750000\nv 25.000000 18.750000 -18.750000\nv 18.750000 18.750000 -24.999996\nv 25.000000 10.000001 -31.250000\nv 18.750000 18.750000 -31.250000\nv 25.000000 18.750000 -31.250000\nv 25.000000 0.000000 -25.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 3537/3551 3538/3552 3539/3553 3540/3554\nf 3541/3552 3542/3555 3543/3556 3544/3551\nf 3545/3557 3546/3558 3547/3559 3548/3560\nf 3549/3553 3546/3561 3545/3562\nf 3547/3563 3546/3564 3549/3565 3550/3566\nf 3547/3567 3550/3568 3551/3553\nf 3552/3569 3547/3563 3551/3566 3553/3570\nf 3548/3569 3547/3570 3552/3558 3554/3557\nf 3552/3553 3553/3561 3554/3555\nf 3546/3563 3547/3564 3555/3556\nf 3543/3571 3546/3563 3555/3556\nf 3544/3551 3543/3571 3555/3556\nf 3555/3551 3547/3563 3552/3569\nf 3552/3569 3537/3572 3555/3551\nf 3555/3551 3537/3572 3540/3554\ng Mesh404 Texture_Connector_Plate66 Texture_Connector_Plate_Mirror33 Texture_Connector_S_W\nv 18.750000 68.750000 -25.000004\nv 18.750000 31.250000 -25.000002\nv 31.250000 31.250000 -25.000002\nv 31.250000 68.750000 -25.000004\nvt 0.000000 1.000000\nf 3556/3573 3557/3573 3558/3573 3559/3573\ng Mesh324 Side_Texture_Plate18 Side_Texture_Plate_Mirror9 Texture_Side_E\nv 81.250000 68.750000 -18.750000\nv 100.000000 68.750000 -18.750000\nv 100.000000 31.250000 -18.750000\nv 81.250000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 3560/3574 3561/3574 3562/3574 3563/3574\ng Mesh567 Side_Texture_Plate_Side56 Texture_Side_W1\nv 0.000000 25.000004 -68.750000\nv 0.000000 18.750000 -68.750000\nv 0.000000 18.750000 -31.250000\nv 0.000000 25.000002 -31.250000\nvt 0.000000 1.000000\nf 3564/3575 3565/3575 3566/3575 3567/3575\ng Mesh463 Side_Texture_Plate28 Side_Texture_Plate_Mirror14 Texture_Side_E2\nv 81.250000 31.250000 -74.999992\nv 100.000000 31.250000 -74.999992\nv 100.000000 68.750000 -74.999992\nv 81.250000 68.750000 -74.999992\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3568/3576 3569/3577 3570/3578 3571/3579\ng Mesh308 Texture_Connector_Plate39 Texture_Connector_Plate_Mirror20 Texture_Connector_W_N\nv 18.750000 31.250000 -81.250000\nv 18.750000 68.750000 -81.250000\nv 18.750000 68.750000 -68.750000\nv 18.750000 31.250000 -68.750000\nvt 0.000000 1.000000\nf 3572/3580 3573/3580 3574/3580 3575/3580\ng Mesh149 Spacer23 Group7\nv 31.250000 68.750000 -74.999992\nv 31.250000 68.750000 -81.250000\nv 31.250000 81.250000 -81.250000\nv 31.250000 81.250000 -74.999985\nv 25.000000 81.250000 -81.250000\nv 25.000000 68.750000 -81.250000\nv 18.750000 81.250000 -74.999985\nv 18.750000 68.750000 -74.999992\nv 18.750000 68.750000 -68.750000\nv 18.750000 81.250000 -68.750000\nv 25.000000 81.250000 -68.750000\nv 25.000000 68.750000 -68.750000\nv 25.000000 81.250000 -74.999985\nv 25.000000 68.750000 -74.999992\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3576/3581 3577/3582 3578/3583 3579/3584\nf 3580/3585 3578/3583 3577/3582 3581/3586\nf 3582/3587 3580/3585 3581/3586 3583/3588\nf 3583/3588 3584/3589 3585/3590 3582/3587\nf 3586/3591 3585/3590 3584/3589 3587/3592\nf 3588/3593 3586/3591 3587/3592 3589/3594\nf 3589/3595 3576/3581 3579/3584 3588/3596\ng Mesh193 Side_Texture_Plate_Side75 Texture_Side_U2\nv 68.750000 81.250000 -74.999985\nv 68.750000 81.250000 -81.250000\nv 31.250000 81.250000 -81.250000\nv 31.250000 81.250000 -74.999985\nvt 0.000000 1.000000\nf 3590/3597 3591/3597 3592/3597 3593/3597\ng Mesh571 Edge_M_D_S\nv 31.250000 25.000004 -18.750000\nv 31.250000 18.750000 -24.999996\nv 68.750000 18.750000 -24.999996\nv 68.750000 25.000004 -18.750000\nv 68.750000 18.750000 -31.250000\nv 31.250000 18.750000 -31.250000\nv 31.250000 24.999998 -31.250000\nv 68.750000 24.999998 -31.250000\nv 68.750000 24.999996 -25.000004\nv 31.250000 24.999996 -25.000004\nv 31.250000 31.250000 -25.000002\nv 68.750000 31.250000 -25.000002\nv 31.250000 31.250000 -18.750000\nv 68.750000 31.250000 -18.750000\nvt 0.400000 0.780000\nvt 0.400000 0.850000\nvt 0.000000 0.850000\nvt 0.000000 0.780000\nvt 0.000000 0.900000\nvt 0.400000 0.900000\nvt 0.000000 0.950000\nvt 0.400000 0.950000\nvt 0.000000 1.000000\nvt 0.400000 1.000000\nvt 0.400000 0.680000\nvt 0.400000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.680000\nvt 0.400000 0.730000\nvt 0.000000 0.730000\nf 3594/3598 3595/3599 3596/3600 3597/3601\nf 3598/3602 3596/3600 3595/3599 3599/3603\nf 3600/3603 3601/3602 3598/3604 3599/3605\nf 3602/3606 3601/3604 3600/3605 3603/3607\nf 3603/3608 3604/3609 3605/3610 3602/3611\nf 3605/3611 3604/3608 3606/3612 3607/3613\nf 3594/3598 3597/3601 3607/3613 3606/3612\ng Mesh566 Side_Texture_Plate77 Side_Texture_Plate_Mirror39 Texture_Side_U3\nv 81.250000 81.250000 -68.750000\nv 81.250000 100.000008 -68.750000\nv 81.250000 100.000008 -31.250000\nv 81.250000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 3608/3614 3609/3614 3610/3614 3611/3614\ng Mesh135 Texture_Connector_Plate73 Texture_Connector_Plate_Mirror37 Texture_Connector_U_E\nv 68.750000 75.000008 -31.250000\nv 68.750000 75.000008 -68.750000\nv 81.250000 75.000008 -68.750000\nv 81.250000 75.000008 -31.250000\nvt 0.000000 1.000000\nf 3612/3615 3613/3615 3614/3615 3615/3615\ng Mesh427 Side_Texture_Plate_Side5 Texture_Side_N1\nv 25.000000 68.750000 -99.999992\nv 18.750000 68.750000 -99.999992\nv 18.750000 31.250000 -99.999992\nv 25.000000 31.250000 -99.999992\nvt 0.000000 1.000000\nf 3616/3616 3617/3616 3618/3616 3619/3616\ng Mesh300 Side_Texture_Plate25 Side_Texture_Plate_Mirror13 Texture_Side_E2\nv 81.250000 68.750000 -81.250000\nv 100.000000 68.750000 -81.250000\nv 100.000000 31.250000 -81.250000\nv 81.250000 31.250000 -81.250000\nvt 0.000000 1.000000\nf 3620/3617 3621/3617 3622/3617 3623/3617\ng Mesh291 Texture_Connector_Plate84 Texture_Connector_Plate_Mirror42 Texture_Connector_D_S\nv 68.750000 18.750000 -18.750000\nv 31.250000 18.750000 -18.750000\nv 31.250000 18.750000 -31.250000\nv 68.750000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 3624/3618 3625/3618 3626/3618 3627/3618\ng Mesh520 Texture_Connector_Plate72 Texture_Connector_Plate_Mirror36 Texture_Connector_U_W\nv 18.750000 81.250000 -68.750000\nv 18.750000 81.250000 -31.250000\nv 31.250000 81.250000 -31.250000\nv 31.250000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 3628/3619 3629/3619 3630/3619 3631/3619\ng Mesh595 Side_Texture_Plate7 Side_Texture_Plate_Mirror4 Texture_Side_N1\nv 25.000000 68.750000 -81.250000\nv 25.000000 68.750000 -99.999992\nv 25.000000 31.250000 -99.999992\nv 25.000000 31.250000 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3632/3620 3633/3621 3634/3622 3635/3623\ng Mesh73 Texture_Connector_Plate93 Texture_Connector_Plate_Mirror47 Texture_Connector_D_W\nv 18.750000 24.999996 -68.750000\nv 18.750000 24.999998 -31.250000\nv 31.250000 24.999998 -31.250000\nv 31.250000 24.999996 -68.750000\nvt 0.000000 1.000000\nf 3636/3624 3637/3624 3638/3624 3639/3624\ng Mesh32 Side_Texture_Plate15 Side_Texture_Plate_Mirror8 Texture_Side_N3\nv 75.000000 31.250000 -81.250000\nv 75.000000 31.250000 -99.999992\nv 75.000000 68.750000 -99.999992\nv 75.000000 68.750000 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3640/3625 3641/3626 3642/3627 3643/3628\ng Mesh133 Side_Texture_Plate54 Side_Texture_Plate_Mirror27 Texture_Side_W1\nv 18.750000 18.750000 -68.750000\nv 0.000000 18.750000 -68.750000\nv 0.000000 18.750000 -31.250000\nv 18.750000 18.750000 -31.250000\nvt 0.000000 1.000000\nf 3644/3629 3645/3629 3646/3629 3647/3629\ng Mesh115 Corner_I_D_NE2\nv 81.250000 31.250000 -74.999992\nv 81.250000 31.250000 -81.250000\nv 68.750000 31.250000 -81.250000\nv 68.750000 31.250000 -74.999992\nv 81.250000 18.750000 -75.000000\nv 75.000000 18.750000 -81.250000\nv 81.250000 24.999998 -81.250000\nv 68.750000 18.750000 -81.250000\nv 68.750000 18.750000 -75.000000\nv 75.000000 18.750000 -75.000000\nv 75.000000 18.750000 -68.750000\nv 75.000000 24.999996 -68.750000\nv 75.000000 24.999996 -74.999992\nv 81.250000 24.999996 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 24.999996 -74.999992\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.330000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.650000 0.430000\nvt 0.690000 0.330000\nvt 0.750000 0.390000\nf 3648/3630 3649/3631 3650/3632 3651/3633\nf 3652/3634 3653/3635 3654/3636\nf 3655/3631 3656/3630 3651/3637 3650/3638\nf 3657/3639 3658/3640 3659/3636 3660/3641\nf 3661/3642 3659/3643 3658/3644 3662/3645\nf 3661/3639 3663/3641 3660/3642 3659/3645\nf 3660/3634 3651/3646 3656/3647\nf 3648/3639 3651/3646 3660/3634\nf 3663/3640 3648/3639 3660/3634\nf 3657/3648 3660/3634 3656/3647\nf 3655/3644 3650/3649 3649/3646\nf 3655/3644 3649/3646 3654/3650\nf 3655/3644 3654/3650 3653/3651\ng Mesh254 Side_Texture_Plate42 Side_Texture_Plate_Mirror21 Texture_Side_S2\nv 81.250000 31.250000 -18.750000\nv 81.250000 31.250000 0.000003\nv 81.250000 68.750000 0.000005\nv 81.250000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 3664/3652 3665/3652 3666/3652 3667/3652\ng Mesh35 Side_Texture_Plate_Side66 Texture_Side_U\nv 25.000000 81.250000 -31.250000\nv 18.750000 81.250000 -31.250000\nv 18.750000 81.250000 -68.750000\nv 25.000000 81.250000 -68.750000\nvt 0.000000 1.000000\nf 3668/3653 3669/3653 3670/3653 3671/3653\ng Mesh14 Spacer10 Group4\nv 68.750000 75.000008 -31.250000\nv 68.750000 81.250000 -31.250000\nv 81.250000 81.250000 -31.250000\nv 81.250000 75.000008 -31.250000\nv 81.250000 81.250000 -25.000002\nv 68.750000 81.250000 -25.000002\nv 81.250000 75.000000 -18.750000\nv 68.750000 75.000000 -18.750000\nv 68.750000 68.750000 -18.750000\nv 81.250000 68.750000 -18.750000\nv 81.250000 68.750000 -25.000004\nv 68.750000 68.750000 -25.000004\nv 81.250000 75.000008 -25.000004\nv 68.750000 75.000008 -25.000004\nvt 0.750000 0.950000\nvt 0.750000 0.900000\nvt 0.870000 0.900000\nvt 0.870000 0.950000\nvt 0.870000 0.850000\nvt 0.750000 0.850000\nvt 0.870000 0.780000\nvt 0.750000 0.780000\nvt 0.750000 0.730000\nvt 0.870000 0.730000\nvt 0.870000 0.680000\nvt 0.750000 0.680000\nvt 0.870000 0.630000\nvt 0.750000 0.630000\nvt 0.750000 1.000000\nvt 0.870000 1.000000\nf 3672/3654 3673/3655 3674/3656 3675/3657\nf 3676/3658 3674/3656 3673/3655 3677/3659\nf 3678/3660 3676/3658 3677/3659 3679/3661\nf 3679/3661 3680/3662 3681/3663 3678/3660\nf 3682/3664 3681/3663 3680/3662 3683/3665\nf 3684/3666 3682/3664 3683/3665 3685/3667\nf 3685/3668 3672/3654 3675/3657 3684/3669\ng Mesh179 Side_Texture_Plate_Side84 Texture_Side_D\nv 25.000000 0.000003 -31.250000\nv 18.750000 0.000003 -31.250000\nv 18.750000 0.000005 -68.750000\nv 25.000000 0.000005 -68.750000\nvt 0.000000 1.000000\nf 3686/3670 3687/3670 3688/3670 3689/3670\ng Mesh597 Inner_BC_Side24 Side_BC_D\nv 75.000000 3.000000 -68.750000\nv 75.000000 3.000000 -50.000000\nv 75.000000 0.000000 -50.000000\nv 75.000000 -0.000001 -68.750000\nv 50.000000 0.000000 -75.000000\nv 50.000000 3.000000 -75.000000\nv 68.750000 3.000000 -75.000000\nv 68.750000 0.000000 -75.000000\nv 68.750000 18.750000 -75.000000\nv 68.750000 10.000001 -75.000000\nv 75.000000 10.000001 -75.000000\nv 75.000000 18.750000 -75.000000\nv 68.750000 18.750000 -81.250000\nv 75.000000 18.750000 -81.250000\nv 81.250000 18.750000 -75.000000\nv 75.000000 10.000000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 75.000000 18.750000 -68.750000\nv 75.000000 0.000000 -75.000000\nvt 0.250000 0.580000\nvt 0.580000 0.580000\nvt 0.580000 0.530000\nvt 0.250000 0.530000\nvt 0.580000 0.630000\nvt 0.250000 0.630000\nvt 0.130000 0.480000\nvt 0.000000 0.480000\nvt 0.000000 0.430000\nvt 0.130000 0.430000\nvt 0.650000 0.630000\nvt 0.650000 0.530000\nvt 0.130000 0.580000\nvt 0.130000 0.630000\nvt 0.000000 0.630000\nvt 0.000000 0.580000\nvt 0.610000 0.400000\nvt 0.640000 0.530000\nvt 0.130000 0.530000\nvt 0.000000 0.530000\nvt 0.210000 0.580000\nvt 0.210000 0.530000\nf 3690/3671 3691/3672 3692/3673 3693/3674\nf 3694/3672 3695/3675 3696/3676 3697/3671\nf 3698/3677 3699/3678 3700/3679 3701/3680\nf 3702/3673 3699/3681 3698/3682\nf 3700/3683 3699/3684 3702/3685 3703/3686\nf 3700/3687 3703/3688 3704/3673\nf 3705/3689 3700/3683 3704/3686 3706/3690\nf 3701/3689 3700/3690 3705/3678 3707/3677\nf 3705/3673 3706/3681 3707/3675\nf 3696/3691 3699/3683 3700/3684\nf 3696/3691 3700/3684 3708/3676\nf 3697/3671 3696/3691 3708/3676\nf 3705/3689 3690/3692 3700/3683\nf 3700/3683 3690/3692 3708/3671\nf 3708/3671 3690/3692 3693/3674\ng Mesh96 Side_Texture_Plate43 Side_Texture_Plate_Mirror22 Texture_Side_S2\nv 75.000000 68.750000 -18.750000\nv 75.000000 68.750000 0.000005\nv 75.000000 31.250000 0.000003\nv 75.000000 31.250000 -18.750000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3709/3693 3710/3694 3711/3695 3712/3696\ng Mesh348 Side_Texture_Plate11 Side_Texture_Plate_Mirror6 Texture_Side_N2\nv 31.250000 25.000006 -81.250000\nv 31.250000 25.000010 -99.999992\nv 68.750000 25.000010 -99.999992\nv 68.750000 25.000006 -81.250000\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3713/3697 3714/3698 3715/3699 3716/3700\ng Mesh378 Side_Texture_Plate_Side33 Texture_Side_S\nv 25.000000 31.250000 0.000003\nv 18.750000 31.250000 0.000003\nv 18.750000 68.750000 0.000005\nv 25.000000 68.750000 0.000005\nvt 0.000000 1.000000\nf 3717/3701 3718/3701 3719/3701 3720/3701\ng Mesh228 Texture_Connector_Plate38 Texture_Connector_Plate_Mirror19 Texture_Connector_W_N\nv 25.000000 68.750000 -81.250000\nv 25.000000 31.250000 -81.250000\nv 25.000000 31.250000 -68.750000\nv 25.000000 68.750000 -68.750000\nvt 0.000000 1.000000\nf 3721/3702 3722/3702 3723/3702 3724/3702\ng Mesh462 Side_Texture_Plate_Side20 Texture_Side_E\nv 100.000000 68.750000 -24.999996\nv 100.000000 68.750000 -18.750000\nv 100.000000 31.250000 -18.750000\nv 100.000000 31.250000 -24.999998\nvt 0.000000 1.000000\nf 3725/3703 3726/3703 3727/3703 3728/3703\ng Mesh106 Side_Texture_Plate_Side10 Texture_Side_N2\nv 31.250000 25.000006 -81.250000\nv 31.250000 18.750000 -81.250000\nv 68.750000 18.750000 -81.250000\nv 68.750000 25.000006 -81.250000\nvt 0.000000 1.000000\nf 3729/3704 3730/3704 3731/3704 3732/3704\ng Mesh92 Corner_I3_U_NE\nv 75.000000 81.250000 -81.250000\nv 81.250000 81.250000 -74.999985\nv 81.250000 75.000015 -81.250000\nvt 0.650000 0.900000\nvt 0.700000 0.820000\nvt 0.750000 0.900000\nf 3733/3705 3734/3706 3735/3707\ng Mesh581 Side_Texture_Plate52 Side_Texture_Plate_Mirror26 Texture_Side_W\nv 18.750000 31.250000 -24.999998\nv 0.000000 31.250000 -24.999998\nv 0.000000 68.750000 -24.999996\nv 18.750000 68.750000 -24.999996\nvt 0.000000 0.400000\nvt 0.000000 0.060000\nvt 0.640000 0.060000\nvt 0.640000 0.400000\nf 3736/3708 3737/3709 3738/3710 3739/3711\ng Mesh172 Corner_M_U_SE\nv 75.000000 68.750000 -25.000004\nv 75.000000 75.000008 -25.000004\nv 75.000000 75.000008 -31.250000\nv 75.000000 68.750000 -31.250000\nv 68.750000 68.750000 -25.000004\nv 68.750000 75.000008 -25.000004\nv 68.750000 75.000008 -31.250000\nvt 0.800000 0.480000\nvt 0.800000 0.530000\nvt 0.750000 0.530000\nvt 0.750000 0.480000\nvt 0.700000 0.530000\nvt 0.700000 0.480000\nvt 0.650000 0.530000\nvt 0.650000 0.480000\nf 3740/3712 3741/3713 3742/3714 3743/3715\nf 3740/3714 3744/3716 3745/3717 3741/3715\nf 3745/3716 3746/3718 3742/3719 3741/3717\ng Mesh365 Side_Texture_Plate_Side92 Texture_Side_D2\nv 31.250000 0.000006 -75.000000\nv 31.250000 0.000007 -81.250000\nv 68.750000 0.000007 -81.250000\nv 68.750000 0.000006 -75.000000\nvt 0.000000 1.000000\nf 3747/3720 3748/3720 3749/3720 3750/3720\ng Mesh507 Mount_S_D\nv 43.750000 18.750000 -0.000001\nv 43.750000 25.000000 0.000000\nv 43.750000 25.000004 -18.750000\nv 43.750000 18.750000 -24.999996\nv 56.250000 18.750000 -0.000001\nv 56.250000 25.000000 0.000000\nv 56.250000 18.750000 -24.999996\nv 56.250000 25.000004 -18.750000\nv 48.000000 18.750000 -24.999996\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.930000 0.100000\nvt 0.860000 0.100000\nvt 0.860000 0.000000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.860000 0.130000\nvt 0.860000 0.190000\nvt 0.650000 0.190000\nvt 0.930000 0.190000\nvt 0.860000 0.170000\nf 3751/3721 3752/3722 3753/3723 3754/3724\nf 3752/3725 3751/3726 3755/3727 3756/3721\nf 3757/3728 3758/3729 3756/3730 3755/3731\nf 3752/3729 3756/3732 3758/3727 3753/3730\nf 3751/3728 3754/3731 3759/3733\nf 3751/3728 3759/3733 3757/3734\nf 3751/3728 3757/3734 3755/3735\nf 3753/3736 3754/3734 3759/3737\nf 3753/3736 3759/3737 3757/3726\nf 3753/3736 3757/3726 3758/3725\ng Mesh508 Support_S_S\nv 31.250000 56.250000 -18.750000\nv 68.750000 56.250000 -18.750000\nv 68.750000 56.250000 -22.999998\nv 31.250000 56.250000 -22.999998\nv 31.250000 43.750000 -18.750000\nv 68.750000 43.750000 -18.750000\nv 31.250000 43.750000 -23.000000\nv 68.750000 43.750000 -23.000000\nvt 0.900000 0.700000\nvt 0.900000 0.400000\nvt 0.930000 0.400000\nvt 0.930000 0.700000\nvt 0.970000 0.700000\nvt 0.970000 1.000000\nvt 0.920000 1.000000\nvt 0.920000 0.700000\nvt 0.960000 0.400000\nvt 0.960000 0.700000\nvt 0.870000 1.000000\nvt 0.870000 0.700000\nf 3760/3738 3761/3739 3762/3740 3763/3741\nf 3761/3742 3760/3743 3764/3744 3765/3745\nf 3765/3746 3764/3747 3766/3741 3767/3740\nf 3767/3745 3766/3744 3763/3748 3762/3749\ng Mesh80 Corner_I_D_NE1\nv 75.000000 18.750000 -68.750000\nv 81.250000 18.750000 -68.750000\nv 81.250000 31.250000 -68.750000\nv 75.000000 31.250000 -68.750000\nv 75.000000 18.750000 -81.250000\nv 81.250000 24.999998 -81.250000\nv 81.250000 18.750000 -75.000000\nv 81.250000 31.250000 -81.250000\nv 75.000000 31.250000 -81.250000\nv 75.000000 24.999998 -81.250000\nv 68.750000 24.999998 -81.250000\nv 68.750000 24.999996 -74.999992\nv 75.000000 24.999996 -74.999992\nv 68.750000 18.750000 -75.000000\nv 68.750000 18.750000 -81.250000\nv 75.000000 18.750000 -75.000000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.800000 0.350000\nvt 0.850000 0.350000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.800000 0.280000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.750000 0.280000\nvt 0.800000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.750000 0.380000\nvt 0.650000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nvt 0.650000 0.430000\nvt 0.750000 0.390000\nvt 0.690000 0.330000\nf 3768/3750 3769/3751 3770/3752 3771/3753\nf 3772/3754 3773/3755 3774/3756\nf 3775/3753 3776/3752 3771/3757 3770/3758\nf 3777/3759 3778/3760 3779/3761 3780/3756\nf 3781/3762 3779/3763 3778/3764 3782/3765\nf 3781/3760 3783/3759 3780/3762 3779/3765\nf 3768/3760 3771/3766 3780/3754\nf 3780/3754 3771/3766 3776/3767\nf 3780/3754 3776/3767 3777/3768\nf 3768/3760 3780/3754 3783/3761\nf 3775/3764 3770/3769 3769/3766\nf 3773/3770 3775/3764 3769/3766\nf 3774/3771 3773/3770 3769/3766\ng Mesh165 Side_Texture_Plate61 Side_Texture_Plate_Mirror31 Texture_Side_W3\nv 18.750000 81.250000 -68.750000\nv 0.000000 81.250000 -68.750000\nv 0.000000 81.250000 -31.250000\nv 18.750000 81.250000 -31.250000\nvt 0.000000 1.000000\nf 3784/3772 3785/3772 3786/3772 3787/3772\ng Mesh298 Side_Texture_Plate_Side35 Texture_Side_S\nv 25.000000 68.750000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 25.000000 31.250000 -18.750000\nvt 0.000000 1.000000\nf 3788/3773 3789/3773 3790/3773 3791/3773\ng Mesh585 Corner_I_D_SW1\nv 25.000000 31.250000 -31.250000\nv 18.750000 31.250000 -31.250000\nv 18.750000 31.250000 -18.750000\nv 25.000000 31.250000 -18.750000\nv 25.000000 18.750000 -31.250000\nv 18.750000 18.750000 -31.250000\nv 31.250000 24.999996 -25.000004\nv 25.000000 24.999996 -25.000004\nv 25.000000 25.000004 -18.750000\nv 31.250000 25.000004 -18.750000\nv 31.250000 18.750000 -24.999996\nv 25.000000 18.750000 -24.999996\nv 31.250000 18.750000 -18.750000\nv 18.750000 25.000004 -18.750000\nv 18.750000 18.750000 -24.999996\nv 25.000000 18.750000 -18.750000\nvt 0.850000 0.350000\nvt 0.800000 0.350000\nvt 0.800000 0.250000\nvt 0.850000 0.250000\nvt 0.850000 0.450000\nvt 0.800000 0.450000\nvt 0.750000 0.280000\nvt 0.800000 0.280000\nvt 0.800000 0.330000\nvt 0.750000 0.330000\nvt 0.800000 0.380000\nvt 0.750000 0.380000\nvt 0.800000 0.430000\nvt 0.750000 0.430000\nvt 0.700000 0.280000\nvt 0.750000 0.190000\nvt 0.750000 0.390000\nvt 0.650000 0.430000\nvt 0.650000 0.330000\nvt 0.690000 0.330000\nvt 0.650000 0.230000\nvt 0.700000 0.230000\nf 3792/3774 3793/3775 3794/3776 3795/3777\nf 3793/3775 3792/3774 3796/3778 3797/3779\nf 3798/3780 3799/3781 3800/3782 3801/3783\nf 3799/3783 3798/3782 3802/3784 3803/3785\nf 3804/3785 3802/3784 3798/3786 3801/3787\nf 3805/3781 3806/3788 3807/3789\nf 3805/3790 3794/3787 3793/3791\nf 3805/3790 3793/3791 3797/3792\nf 3806/3793 3805/3790 3797/3792\nf 3792/3792 3795/3794 3800/3795\nf 3799/3788 3792/3792 3800/3795\nf 3796/3783 3792/3792 3799/3788\nf 3796/3783 3799/3788 3803/3780\ng Mesh259 Side_Texture_Plate_Side34 Texture_Side_S\nv 25.000000 31.250000 -18.750000\nv 18.750000 31.250000 -18.750000\nv 18.750000 68.750000 -18.750000\nv 25.000000 68.750000 -18.750000\nvt 0.000000 1.000000\nf 3808/3796 3809/3796 3810/3796 3811/3796\ng Mesh23 Texture_Plate_D1\nv 31.250000 18.750000 -31.250000\nv 68.750000 18.750000 -31.250000\nv 68.750000 18.750000 -68.750000\nv 31.250000 18.750000 -68.750000\nvt 0.000000 1.000000\nvt 0.000000 0.000000\nvt 1.000000 0.000000\nvt 1.000000 1.000000\nf 3812/3797 3813/3798 3814/3799 3815/3800\ng Mesh157 Side_Texture_Plate_Side65 Texture_Side_U\nv 25.000000 100.000008 -31.250000\nv 18.750000 100.000008 -31.250000\nv 18.750000 100.000008 -68.750000\nv 25.000000 100.000008 -68.750000\nvt 0.000000 1.000000\nf 3816/3801 3817/3801 3818/3801 3819/3801\ng Mesh480 Mount_N_D\nv 56.250000 18.750000 -100.000000\nv 56.250000 25.000002 -99.999992\nv 56.250000 24.999998 -81.250000\nv 56.250000 18.750000 -75.000000\nv 43.750000 18.750000 -100.000000\nv 43.750000 25.000002 -99.999992\nv 43.750000 18.750000 -75.000000\nv 43.750000 24.999998 -81.250000\nv 52.000000 18.750000 -75.000000\nvt 0.930000 0.000000\nvt 0.980000 0.000000\nvt 0.980000 0.160000\nvt 0.930000 0.210000\nvt 0.860000 0.000000\nvt 0.930000 0.090000\nvt 0.860000 0.090000\nvt 0.650000 0.120000\nvt 0.700000 0.070000\nvt 0.860000 0.070000\nvt 0.860000 0.120000\nvt 0.700000 0.000000\nvt 0.650000 0.190000\nvt 0.860000 0.190000\nvt 0.000000 0.000000\nvt 0.930000 0.190000\nf 3820/3802 3821/3803 3822/3804 3823/3805\nf 3821/3806 3820/3802 3824/3807 3825/3808\nf 3826/3809 3827/3810 3825/3811 3824/3812\nf 3821/3806 3825/3811 3827/3810 3822/3813\nf 3824/3814 3820/3809 3826/3815\nf 3826/3815 3820/3809 3823/3812\nf 3828/3816 3826/3816 3823/3816\nf 3826/3817 3827/3815 3822/3808\nf 3826/3817 3822/3808 3823/3807\ng Mesh369 Texture_Connector_Plate23 Texture_Connector_Plate_Mirror12 Texture_Connector_N_D\nv 68.750000 31.250000 -81.250000\nv 31.250000 31.250000 -81.250000\nv 31.250000 18.750000 -81.250000\nv 68.750000 18.750000 -81.250000\nvt 0.000000 1.000000\nf 3829/3818 3830/3818 3831/3818 3832/3818\n"
  },
  {
    "path": "resources/pack.mcmeta",
    "content": "{\n    \"pack\": {\n        \"description\": \"LogisticsPipes resources\",\n        \"pack_format\": 3\n    }\n}\n"
  },
  {
    "path": "resources_raw/mcmod.info",
    "content": "[{\n    \"modid\": \"logisticspipes\",\n    \"name\": \"Logistics Pipes\",\n    \"description\": \"Logistics Pipes is an extensive overhaul of the Buildcraft pipe system. It allows for better distribution of items via pipes, more organised stockkeeping and easier automated crafting.\",\n    \"version\": \"${version}\",\n    \"mcversion\": \"${mcversion}\",\n    \"url\": \"https://github.com/RS485/LogisticsPipes\",\n    \"updateUrl\": \"\",\n    \"authorList\": [ \"RS485\", \"LP Team\" ],\n    \"credits\": \"Contributors: https://github.com/RS485/LogisticsPipes/contributors. Original code and idea made by Krapht. Thanks!\",\n    \"logoFile\": \"\",\n    \"screenshots\": [],\n    \"requiredMods\": [\n        \"forge@[10.12.1.1079,)\",\n        \"codechickenlib@[3.1.7.340,)\"\n    ],\n    \"dependencies\": [\n        \"forge@[10.12.1.1079,)\",\n        \"codechickenlib@[3.1.7.340,)\",\n        \"buildcraftcore\",\n        \"buildcrafttransport\",\n        \"buildcraftsilicon\",\n        \"buildcraftrobotics\",\n        \"ic2\",\n        \"computercraft\",\n        \"factorization\",\n        \"gregtech_addon\",\n        \"appliedenergistics\",\n        \"thermalexpansion\",\n        \"betterstorage\",\n        \"mcmultipart\"\n    ],\n    \"dependants\": [],\n    \"useDependencyInformation\": true\n}]\n"
  },
  {
    "path": "run/.gitkeep",
    "content": ""
  },
  {
    "path": "run-server/.gitkeep",
    "content": ""
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'LogisticsPipes'\n"
  },
  {
    "path": "src/api/java/network/rs485/debug/api/IDataConnection.java",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.debug.api;\n\npublic interface IDataConnection {\n\n\tvoid passData(byte[] packet);\n\n\tvoid closeCon();\n}\n"
  },
  {
    "path": "src/api/java/network/rs485/debug/api/IDebugGuiEntry.java",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.debug.api;\n\nimport java.util.concurrent.Future;\n\npublic abstract class IDebugGuiEntry {\n\n\tpublic static IDebugGuiEntry create()\n\t\t\tthrows ClassNotFoundException, IllegalAccessException, InstantiationException {\n\t\ttry {\n\t\t\treturn (IDebugGuiEntry) Class.forName(\"network.rs485.debug.gui.DebugGuiEntry\").newInstance();\n\t\t} catch (ReflectiveOperationException ignored) {}\n\t\treturn (IDebugGuiEntry) Class.forName(\"network.rs485.debuggui.DebugGuiEntry\").newInstance();\n\t}\n\n\tpublic abstract IDataConnection startServerDebugging(Object object, IDataConnection outgoingData,\n\t\t\tIObjectIdentification objectIdent);\n\n\tpublic abstract Future<IDataConnection> startClientDebugging(String name, IDataConnection outgoingData);\n\n\tpublic abstract void exec();\n\n}\n"
  },
  {
    "path": "src/api/java/network/rs485/debug/api/IObjectIdentification.java",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.debug.api;\n\npublic interface IObjectIdentification {\n\n\tboolean toStringObject(Object o);\n\n\t/**\n\t * @param o\n\t * @return null, if object isn't handled, otherwise the String value\n\t */\n\tString handleObject(Object o);\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/IStore.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes\n\nimport net.minecraft.nbt.NBTTagCompound\n\ninterface IStore {\n    fun readFromNBT(tag: NBTTagCompound)\n    fun writeToNBT(tag: NBTTagCompound)\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/connection/Adjacent.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.math.BlockPos\nimport java.util.*\n\ninterface Adjacent {\n    fun connectedPos(): Map<BlockPos, ConnectionType>\n\n    operator fun get(direction: EnumFacing): ConnectionType?\n\n    fun optionalGet(direction: EnumFacing): Optional<ConnectionType>\n\n    fun neighbors(): Map<NeighborTileEntity<TileEntity>, ConnectionType>\n\n    fun inventories(): List<NeighborTileEntity<TileEntity>>\n\n    fun fluidTanks(): List<NeighborTileEntity<TileEntity>>\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/connection/ConnectionType.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nenum class ConnectionType {\n    ITEM, FLUID, MULTIBLOCK, UNDEFINED;\n\n    fun isItem(): Boolean = this == ITEM || this == UNDEFINED\n    fun isFluid(): Boolean = this == FLUID || this == UNDEFINED\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/connection/NeighborTileEntity.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraftforge.common.capabilities.Capability\n\nabstract class NeighborTileEntity<T : TileEntity>(val tileEntity: T, val direction: EnumFacing) {\n    open fun getOurDirection(): EnumFacing = direction.opposite\n\n    fun hasCapability(capability: Capability<*>): Boolean = tileEntity.hasCapability(capability, getOurDirection())\n\n    abstract fun isLogisticsPipe(): Boolean\n\n    abstract fun canHandleItems(): Boolean\n\n    abstract fun canHandleFluids(): Boolean\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/gui/Constraints.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\ndata class Margin(val top: Int = 0, val left: Int = 0, val bottom: Int = 0, val right: Int = 0) {\n    companion object {\n        val NONE = Margin()\n        val DEFAULT = Margin(6)\n    }\n\n    constructor(margin: Int) : this(\n        top = margin,\n        bottom = margin,\n        left = margin,\n        right = margin\n    )\n\n    val horizontal = left + right\n    val vertical = top + bottom\n}\n\nenum class HorizontalAlignment {\n    LEFT,\n    CENTER,\n    RIGHT;\n}\n\nenum class VerticalAlignment {\n    TOP,\n    CENTER,\n    BOTTOM;\n}\n\nenum class Size {\n    FIXED,\n    GROW,\n    MIN\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/gui/Dsl.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport network.rs485.logisticspipes.property.Property\nimport network.rs485.logisticspipes.property.layer.PropertyLayer\n\n@DslMarker\nannotation class GuiComponentMarker\n\n@GuiComponentMarker\nabstract class GuiComponent {\n    var width: Int = -1\n    var height: Int = -1\n    val children = arrayListOf<GuiComponent>()\n    var margin: Margin = Margin.NONE\n    var horizontalAlignment: HorizontalAlignment = HorizontalAlignment.LEFT\n    var verticalAlignment: VerticalAlignment = VerticalAlignment.TOP\n    var horizontalSize: Size = Size.GROW\n    var verticalSize: Size = Size.GROW\n    var enabled: Boolean = true\n\n    open fun <T : GuiComponent> initComponent(component: T, init: T.() -> Unit): T {\n        component.apply(init)\n        children.add(component)\n        return component\n    }\n}\n\n\nabstract class ComponentContainer : GuiComponent() {\n\n    var gap: Int = 1\n\n    /**\n     * Arranges contained widgets left-to-right horizontally\n     */\n    fun horizontal(init: HContainer.() -> Unit) = initComponent(HContainer(), init)\n\n    /**\n     * Arranges contained widgets top-to-bottom vertically\n     */\n    fun vertical(init: VContainer.() -> Unit) = initComponent(VContainer(), init)\n\n    fun optionalComponent(init: OptionalComponent.() -> Unit) = initComponent(OptionalComponent(), init)\n\n    /**\n     * Represents a label with the text value based on a property.\n     */\n    fun <V : Any, P : Property<V>> label(init: PropertyLabel<V, P>.() -> Unit) = initComponent(PropertyLabel(), init)\n\n    /**\n     * Represents a button with the text value based on a property.\n     */\n    fun <V : Any, P : Property<V>> propertyButton(init: PropertyButton<V, P>.() -> Unit) =\n        initComponent(PropertyButton(), init)\n\n    /**\n     * Represents a static button.\n     */\n    fun button(init: Button.() -> Unit) = initComponent(Button(), init)\n\n    /**\n     * Represents a static piece of text.\n     */\n    fun staticLabel(init: Label.() -> Unit) = initComponent(Label(), init)\n}\n\n/**\n * Used to construct a base container component.\n */\nfun widgetContainer(init: VContainer.() -> Unit): VContainer =\n    VContainer().apply(init)\n\nclass HContainer : ComponentContainer() {\n    var alignment: HorizontalAlignment = HorizontalAlignment.LEFT\n}\n\nclass VContainer : ComponentContainer() {\n    var alignment: VerticalAlignment = VerticalAlignment.TOP\n}\n\n/**\n * Adds component to hierarchy if the predicate returns true.\n */\nclass OptionalComponent : ComponentContainer() {\n    var predicate: () -> Boolean = { false }\n    var vertical: Boolean = true\n    private var addComponents: Boolean = false\n\n    override fun <T : GuiComponent> initComponent(component: T, init: T.() -> Unit): T {\n        if (addComponents) {\n            component.apply(init)\n            children.add(component)\n        }\n        return component\n    }\n\n    fun activeComponents(init: OptionalComponent.() -> Unit): OptionalComponent {\n        if (predicate.invoke()) {\n            addComponents = true\n        }\n        init(this)\n        addComponents = false\n        return this\n    }\n\n    fun inactiveComponents(init: OptionalComponent.() -> Unit): OptionalComponent {\n        if (!predicate.invoke()) {\n            addComponents = true\n        }\n        init(this)\n        addComponents = false\n        return this\n    }\n}\n\nopen class Label : GuiComponent() {\n    var text: String = \"\"\n    var textAlignment: HorizontalAlignment = HorizontalAlignment.LEFT\n    var textColor: Int = 0\n    var extendable: Boolean = false\n    var backgroundColor: Int = 0\n}\n\ninterface PropertyAware {\n    fun onPropertyUpdate(callback: (String) -> Unit)\n}\n\nclass PropertyLabel<V : Any, P : Property<V>> : Label(), PropertyAware {\n    lateinit var propertyLayer: PropertyLayer\n    lateinit var property: P\n    var propertyToText: (V) -> String = Any::toString\n\n    override fun onPropertyUpdate(callback: (String) -> Unit) {\n        propertyLayer.addObserver(property) {\n            callback.invoke(propertyToText.invoke(it.copyValue()))\n        }\n    }\n}\n\nopen class Button : GuiComponent() {\n    var text: String = \"\"\n    var action: () -> Unit = {}\n}\n\nclass PropertyButton<V : Any, P : Property<V>> : Button(), PropertyAware {\n    lateinit var propertyLayer: PropertyLayer\n    lateinit var property: P\n    var propertyToText: (V) -> String = Any::toString\n\n    override fun onPropertyUpdate(callback: (String) -> Unit) {\n        propertyLayer.addObserver(property) {\n            callback.invoke(propertyToText.invoke(it.copyValue()))\n        }\n    }\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/gui/SwingStuff.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport java.awt.Container\nimport javax.swing.JButton\nimport javax.swing.JLabel\nimport javax.swing.JPanel\n\ninterface WidgetRenderer<T : Any> {\n    fun render(componentContainer: ComponentContainer): T\n}\n\nobject SwingRenderer : WidgetRenderer<JPanel> {\n    fun Container.addContainer(container: ComponentContainer) {\n        container.children.forEach { child ->\n            when (child) {\n                is PropertyLabel<*, *> -> JLabel().apply {\n                    text = child.text\n                    child.onPropertyUpdate { newText ->\n                        text = newText\n                    }\n                }\n\n                is PropertyButton<*, *> -> JButton().apply {\n                    text = child.text\n                    addActionListener { child.action.invoke() }\n                    child.onPropertyUpdate { newText ->\n                        text = newText\n                    }\n                }\n\n                is Label -> JLabel().apply {\n                    text = child.text\n                }\n\n                is Button -> JButton().apply {\n                    text = child.text\n                    addActionListener { child.action.invoke() }\n                }\n\n                is ComponentContainer -> JPanel().apply {\n                    addContainer(child)\n                }\n\n                else -> null\n            }?.also(::add)\n        }\n    }\n\n    override fun render(componentContainer: ComponentContainer): JPanel {\n        return JPanel().apply {\n            addContainer(componentContainer)\n        }\n    }\n}\n\n//fun main() {\n//    SwingUtilities.invokeAndWait {\n//        val frame = JFrame()\n//        val gui = ProviderGui()\n//        frame.add(SwingRenderer.render(gui.widgets))\n//        frame.pack()\n//        frame.isVisible = true\n//    }\n//}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/pipes/IChassisPipe.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.pipes\n\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.util.EnumFacing\n\ninterface IChassisPipe {\n    fun nextOrientation()\n    fun setPointedOrientation(dir: EnumFacing?)\n    fun getPointedOrientation(): EnumFacing?\n    fun getModuleInventory(): IInventory\n    fun getChassisSize(): Int\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/BitSetProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\nimport java.util.*\nimport java.util.concurrent.CopyOnWriteArraySet\n\ninterface IBitSet {\n    operator fun get(bit: Int): Boolean\n    operator fun set(bit: Int, value: Boolean)\n    fun flip(bit: Int)\n    fun nextSetBit(idx: Int): Int\n    fun replaceWith(other: BitSet)\n    fun replaceWith(other: IBitSet)\n    fun copyValue(): BitSet\n    fun clear()\n\n    fun sequence(): Sequence<Int> {\n        var idx = nextSetBit(0)\n        return generateSequence {\n            idx.takeUnless { it == -1 }?.also { idx = nextSetBit(it + 1) }\n        }\n    }\n}\n\nclass BitSetProperty(private val bitset: BitSet, override val tagKey: String) : IBitSet, Property<BitSet> {\n\n    override val propertyObservers: CopyOnWriteArraySet<ObserverCallback<BitSet>> = CopyOnWriteArraySet()\n\n    override fun copyValue(): BitSet = bitset.clone() as BitSet\n\n    override fun clear() = bitset.clear().alsoIChanged()\n\n    fun copyValue(startIdx: Int, endIdx: Int): BitSet = bitset.get(startIdx, endIdx + 1)\n\n    override fun copyProperty(): BitSetProperty = BitSetProperty(copyValue(), tagKey)\n\n    override fun replaceWith(other: BitSet) {\n        other.takeUnless { it == bitset }\n            ?.let { bitset.clear(); bitset.or(it) }\n            ?.alsoIChanged()\n    }\n\n    override fun replaceWith(other: IBitSet) {\n        other.takeUnless { it == bitset }\n            ?.let { bitset.clear(); bitset.or(it.copyValue()) }\n            ?.alsoIChanged()\n    }\n\n    fun replaceWith(other: BitSetProperty) {\n        other.takeUnless { it === this }\n            ?.let { bitset.clear(); bitset.or(other.bitset) }\n            ?.alsoIChanged()\n    }\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) replaceWith(BitSet.valueOf(tag.getByteArray(tagKey)))\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = tag.setByteArray(tagKey, bitset.toByteArray())\n\n    override fun get(bit: Int): Boolean = bitset.get(bit)\n    override fun set(bit: Int, value: Boolean) = bitset.set(bit, value).alsoIChanged()\n    override fun flip(bit: Int) = bitset.flip(bit).alsoIChanged()\n    override fun nextSetBit(idx: Int): Int = bitset.nextSetBit(idx)\n\n    fun get(startIdx: Int, endIdx: Int): IBitSet {\n        if (startIdx < 0 || startIdx >= bitset.size()) {\n            throw IndexOutOfBoundsException(\"startIdx[$startIdx] is out of bounds\")\n        }\n        if (endIdx < 0 || endIdx >= bitset.size()) {\n            throw IndexOutOfBoundsException(\"endIdx[$endIdx] is out of bounds\")\n        }\n        return PartialBitSet(startIdx..endIdx)\n    }\n\n    override fun equals(other: Any?): Boolean = (other as? BitSetProperty)?.let {\n        tagKey == other.tagKey && bitset == other.bitset\n    } ?: false\n\n    override fun hashCode(): Int = Objects.hash(tagKey, bitset)\n\n    override fun toString(): String = \"BitSetProperty(tagKey=$tagKey, bitset=$bitset)\"\n\n    inner class PartialBitSet(private val indices: IntRange) : IBitSet {\n\n        val size: Int\n            get() = (indices.last - indices.first) + 1\n\n        init {\n            if (indices.last < indices.first) {\n                throw IllegalArgumentException(\"start[${indices.first}] must be <= end[${indices.last}]\")\n            }\n        }\n\n        private fun rangeCheck(idx: Int): Int {\n            if (idx < 0 || idx >= size) {\n                throw IndexOutOfBoundsException(\"idx[$idx] out of bounds of $this\")\n            }\n            return idx\n        }\n\n        override fun get(bit: Int): Boolean = this@BitSetProperty[indices.first + rangeCheck(bit)]\n        override fun set(bit: Int, value: Boolean) = this@BitSetProperty.set(indices.first + rangeCheck(bit), value)\n        override fun flip(bit: Int) = this@BitSetProperty.flip(indices.first + rangeCheck(bit))\n        override fun clear() = this@BitSetProperty.bitset.clear(indices.first, indices.last + 1).alsoIChanged()\n        override fun copyValue(): BitSet = this@BitSetProperty.copyValue(indices.first, indices.last)\n\n        override fun nextSetBit(idx: Int): Int {\n            if (idx >= size) return -1\n            return this@BitSetProperty.nextSetBit(indices.first + rangeCheck(idx))\n                .takeUnless { it == -1 || it > indices.last }\n                ?.let { it - indices.first }\n                ?: -1\n        }\n\n        override fun replaceWith(other: BitSet) {\n            bitset.clear(indices.first, indices.last + 1)\n            other.stream().forEach { bit -> (indices.first + bit).takeIf { it <= indices.last }?.also { bitset.set(it) } }\n            iChanged()\n        }\n\n        override fun replaceWith(other: IBitSet) {\n            bitset.clear(indices.first, indices.last + 1)\n            other.sequence().map { bit -> indices.first + bit }\n                .takeWhile { bit -> bit <= indices.last }\n                .forEach { bit -> bitset.set(bit) }\n            iChanged()\n        }\n\n        override fun equals(other: Any?): Boolean = (other as? IBitSet)?.copyValue()?.equals(copyValue()) ?: false\n        override fun hashCode(): Int = copyValue().hashCode()\n\n        override fun toString(): String =\n            \"PartialBitSet(indices=$indices, bitset=${copyValue()})\"\n    }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/BooleanProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\n\nclass BooleanProperty(initialValue: Boolean, override val tagKey: String) : ValueProperty<Boolean>(initialValue) {\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) value = tag.getBoolean(tagKey)\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = tag.setBoolean(tagKey, value)\n\n    override fun copyValue(): Boolean = value\n\n    override fun copyProperty(): BooleanProperty = BooleanProperty(copyValue(), tagKey)\n\n    fun toggle(): Boolean = (!value).also { value = it }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/EnumProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\n\nclass EnumProperty<E : Enum<E>>(\n    private val defaultValue: E,\n    override val tagKey: String,\n    private val enumValues: Array<E>,\n) : ValueProperty<E>(defaultValue) {\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) value = (enumValues.getOrNull(tag.getInteger(tagKey)) ?: defaultValue)\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = tag.setInteger(tagKey, value.ordinal)\n\n    override fun copyValue(): E = value\n\n    override fun copyProperty(): EnumProperty<out E> =\n        EnumProperty(defaultValue, tagKey, enumValues).also { it.value = copyValue() }\n\n    fun next() = (enumValues.getOrNull(value.ordinal + 1) ?: enumValues[0]).also { value = it }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/IntegerProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\n\nclass IntegerProperty(initialValue: Int, override val tagKey: String) : ValueProperty<Int>(initialValue) {\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) value = tag.getInteger(tagKey)\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = tag.setInteger(tagKey, value)\n\n    override fun copyValue(): Int = value\n\n    override fun copyProperty(): IntegerProperty = IntegerProperty(copyValue(), tagKey)\n\n    fun increase(by: Int) = value.plus(by).also { value = it }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/InventoryProperty.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.inventory.IInventory\n\ninterface InventoryProperty<T : IInventory> : Property<T>, IInventory {\n    override fun copyProperty(): InventoryProperty<out T>\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/ListProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\nimport java.util.concurrent.CopyOnWriteArraySet\nimport java.util.function.UnaryOperator\n\ninterface IListProperty<T> : MutableList<T>, Property<MutableList<T>> {\n    fun ensureSize(size: Int, fillWith: (Int) -> T): Unit?\n    fun ensureSize(size: Int): Unit?\n    fun replaceContent(col: Collection<T>): Boolean?\n    fun replaceContent(arr: Array<T>): Boolean?\n    fun readSingleFromNBT(tag: NBTTagCompound, key: String): T\n    fun writeSingleToNBT(tag: NBTTagCompound, key: String, value: T)\n    fun copyValue(obj: T): T\n}\n\nabstract class ListProperty<T>(\n    protected val list: MutableList<T>,\n) : MutableList<T> by list, IListProperty<T> {\n\n    companion object {\n        private const val SIZE_NAME = \"listSize\"\n        private const val ITEM_NAME = \"listItem\"\n\n        fun sizeTagKey(tagKey: String) = if (tagKey.isEmpty()) SIZE_NAME else \"$tagKey.$SIZE_NAME\"\n        fun itemTagKey(tagKey: String, idx: Int) =\n            if (tagKey.isEmpty()) \"$ITEM_NAME.$idx\" else \"$tagKey.$ITEM_NAME.$idx\"\n    }\n\n    override val propertyObservers: CopyOnWriteArraySet<ObserverCallback<MutableList<T>>> = CopyOnWriteArraySet()\n\n    override fun ensureSize(size: Int, fillWith: (Int) -> T) =\n        (size - list.size).takeIf { it > 0 }?.let { repeat(it) { list.add(fillWith(list.size)) } }?.alsoIChanged()\n\n    override fun ensureSize(size: Int) = ensureSize(size) { defaultValue(it) }\n\n    override fun replaceContent(col: Collection<T>) =\n        list.takeUnless { it == col.toMutableList() }\n            ?.run { clear(); addAll(col) }\n            ?.alsoIChanged()\n\n    override fun replaceContent(arr: Array<T>) = replaceContent(arr.asList())\n\n    abstract fun defaultValue(idx: Int): T\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(sizeTagKey(tagKey))) {\n            replaceContent(\n                MutableList(tag.getInteger(sizeTagKey(tagKey))) { idx ->\n                    if (tag.hasKey(itemTagKey(tagKey, idx))) {\n                        readSingleFromNBT(tag, itemTagKey(tagKey, idx))\n                    } else defaultValue(idx)\n                }\n            )\n        }\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) {\n        tag.setInteger(sizeTagKey(tagKey), list.size)\n        list.withIndex().forEach { writeSingleToNBT(tag, itemTagKey(tagKey, it.index), it.value) }\n    }\n\n    override fun copyValue(): MutableList<T> = MutableList(list.size) { idx -> copyValue(list[idx]) }\n\n    override fun add(element: T): Boolean = list.add(element).alsoIChanged()\n\n    override fun add(index: Int, element: T) = list.add(index, element).alsoIChanged()\n\n    override fun addAll(index: Int, elements: Collection<T>): Boolean = list.addAll(index, elements).alsoIChanged()\n\n    override fun addAll(elements: Collection<T>): Boolean = list.addAll(elements).alsoIChanged()\n\n    override fun clear() = list.clear().alsoIChanged()\n\n    override fun remove(element: T): Boolean = list.remove(element).alsoIChanged()\n\n    override fun removeAll(elements: Collection<T>): Boolean = list.removeAll(elements).alsoIChanged()\n\n    override fun removeAt(index: Int): T = list.removeAt(index).alsoIChanged()\n\n    override fun replaceAll(operator: UnaryOperator<T>) = list.replaceAll(operator).alsoIChanged()\n\n    override fun retainAll(elements: Collection<T>): Boolean = list.retainAll(elements).alsoIChanged()\n\n    override fun set(index: Int, element: T): T = list.set(index, element).alsoIChanged()\n\n    override fun sort(c: Comparator<in T>) = list.sortWith(c).alsoIChanged()\n\n    override fun listIterator(): MutableListIterator<T> =\n        TODO(\"Returned MutableListIterator needs to inform of changes\")\n\n    override fun listIterator(index: Int): MutableListIterator<T> =\n        TODO(\"Returned MutableListIterator needs to inform of changes\")\n\n    override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> =\n        TODO(\"Returned sub list needs to inform of changes\")\n\n}\n\nclass IntListProperty : ListProperty<Int> {\n\n    override val tagKey: String\n\n    constructor(tagKey: String) : super(mutableListOf()) {\n        this.tagKey = tagKey\n    }\n\n    private constructor(tagKey: String, list: MutableList<Int>) : super(list) {\n        this.tagKey = tagKey\n    }\n\n    fun replaceContent(arr: IntArray) = replaceContent(arr.asList())\n\n    fun getArray(): IntArray = list.toIntArray()\n\n    fun increase(index: Int, by: Int) = set(index, get(index) + by)\n\n    override fun defaultValue(idx: Int): Int = 0\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) replaceContent(tag.getIntArray(tagKey))\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = tag.setIntArray(tagKey, list.toIntArray())\n\n    override fun copyValue(obj: Int): Int = obj\n\n    override fun copyProperty(): IntListProperty = IntListProperty(tagKey = tagKey, list = copyValue())\n\n    override fun readSingleFromNBT(tag: NBTTagCompound, key: String): Int = tag.getInteger(key)\n\n    override fun writeSingleToNBT(tag: NBTTagCompound, key: String, value: Int) = tag.setInteger(key, value)\n\n}\n\nclass StringListProperty : ListProperty<String> {\n\n    override val tagKey: String\n\n    constructor(tagKey: String) : super(mutableListOf()) {\n        this.tagKey = tagKey\n    }\n\n    private constructor(tagKey: String, list: MutableList<String>) : super(list) {\n        this.tagKey = tagKey\n    }\n\n    override fun defaultValue(idx: Int): String = \"\"\n\n    override fun readSingleFromNBT(tag: NBTTagCompound, key: String): String = tag.getString(key)\n\n    override fun writeSingleToNBT(tag: NBTTagCompound, key: String, value: String) = tag.setString(key, value)\n\n    override fun copyValue(obj: String): String = obj\n\n    override fun copyProperty(): StringListProperty = StringListProperty(tagKey = tagKey, list = copyValue())\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/NullableEnumProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\n\nclass NullableEnumProperty<E : Enum<E>>(\n    private val defaultValue: E?,\n    override val tagKey: String,\n    private val enumValues: Array<E>,\n) : ValueProperty<E?>(defaultValue) {\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) {\n            val ordinalValue = tag.getInteger(tagKey)\n            value = if (ordinalValue == -1) {\n                null\n            } else {\n                enumValues.getOrNull(ordinalValue) ?: defaultValue\n            }\n        }\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) =\n        value?.let { tag.setInteger(tagKey, it.ordinal) } ?: tag.setInteger(tagKey, -1)\n\n    override fun copyValue(): E? = value\n\n    override fun copyProperty(): NullableEnumProperty<out E> =\n        NullableEnumProperty(defaultValue, tagKey, enumValues).also { it.value = copyValue() }\n\n    /**\n     * This will throw a NPE when the current value is null.\n     */\n    fun next() = (enumValues.getOrNull(value!!.ordinal + 1) ?: enumValues[0]).also { value = it }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/Property.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport network.rs485.logisticspipes.IStore\nimport java.util.concurrent.CopyOnWriteArraySet\n\n/**\n * Properties follow a standard observer pattern by notifying on every write access.\n */\ninterface Property<V> : IStore {\n    val tagKey: String\n    val propertyObservers: CopyOnWriteArraySet<ObserverCallback<V>>\n\n    fun iChanged() = propertyObservers.forEach { observer -> observer.invoke(this) }\n    fun <T> T.alsoIChanged(): T = this.also { iChanged() }\n    fun addObserver(callback: ObserverCallback<V>) = propertyObservers.add(callback)\n    fun copyValue(): V\n\n    /**\n     * Copies the property and its current value. Must always return property of same class as the callee.\n     */\n    fun copyProperty(): Property<out V>\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/PropertyHolder.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport network.rs485.logisticspipes.IStore\nimport net.minecraft.nbt.NBTTagCompound\n\n/**\n * Holds a [properties] list and can read and write [NBT][NBTTagCompound] via [IStore].\n */\ninterface PropertyHolder {\n    val properties: List<Property<*>>\n\n    companion object {\n        @JvmStatic\n        fun readFromNBT(tag: NBTTagCompound, holder: PropertyHolder) = holder.properties.readFromNBT(tag)\n\n        @JvmStatic\n        fun writeToNBT(tag: NBTTagCompound, holder: PropertyHolder) = holder.properties.writeToNBT(tag)\n    }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/UUIDProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\nimport java.util.*\n\nprivate val zero = UUID(0L, 0L)\n\nfun isZero(uuid: UUID) = uuid == zero\n\nclass UUIDProperty(initialValue: UUID?, override val tagKey: String) : ValueProperty<UUID>(initialValue ?: zero) {\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        // FIXME after 1.12: remove support for empty string\n        if (tag.hasKey(tagKey)) tag.getString(tagKey).takeUnless(String::isEmpty)?.also { value = UUID.fromString(it) }\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = tag.setString(tagKey, value.toString())\n\n    override fun copyValue(): UUID = value\n\n    override fun copyProperty(): UUIDProperty = UUIDProperty(copyValue(), tagKey)\n\n    fun isZero() = isZero(value)\n\n    fun zero() {\n        value = zero\n    }\n\n}\n\nclass UUIDListProperty : ListProperty<UUID> {\n\n    override val tagKey: String\n\n    constructor(tagKey: String) : super(mutableListOf()) {\n        this.tagKey = tagKey\n    }\n\n    private constructor(tagKey: String, list: MutableList<UUID>) : super(list) {\n        this.tagKey = tagKey\n    }\n\n    override fun defaultValue(idx: Int): UUID = zero\n\n    override fun readSingleFromNBT(tag: NBTTagCompound, key: String): UUID = UUID.fromString(tag.getString(key))\n\n    override fun writeSingleToNBT(tag: NBTTagCompound, key: String, value: UUID) = tag.setString(key, value.toString())\n\n    // UUID objects are immutable\n    override fun copyValue(obj: UUID): UUID = obj\n\n    override fun copyProperty(): UUIDListProperty = UUIDListProperty(tagKey, list)\n\n    fun isZero(idx: Int) = isZero(get(idx))\n\n    fun zero(idx: Int) = set(idx, zero)\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/Util.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport net.minecraft.nbt.NBTTagCompound\n\ntypealias ObserverCallback<V> = (Property<V>) -> Unit\n\nfun Collection<Property<*>>.addObserver(callback: ObserverCallback<*>) =\n    forEach { prop -> prop.addObserver(callback) }\n\nfun Collection<Property<*>>.removeObserver(callback: ObserverCallback<*>) =\n    forEach { prop -> prop.propertyObservers.remove(callback) }\n\nfun Collection<Property<*>>.readFromNBT(tag: NBTTagCompound) = forEach { prop -> prop.readFromNBT(tag) }\n\nfun Collection<Property<*>>.writeToNBT(tag: NBTTagCompound) = forEach { prop -> prop.writeToNBT(tag) }\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/ValueProperty.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport java.util.*\nimport java.util.concurrent.CopyOnWriteArraySet\nimport kotlin.properties.Delegates\nimport kotlin.reflect.KProperty\n\nabstract class ValueProperty<V>(initialValue: V) : Property<V> {\n    override val propertyObservers: CopyOnWriteArraySet<ObserverCallback<V>> = CopyOnWriteArraySet()\n\n    var value: V by Delegates.observable(initialValue) { _: KProperty<*>, oldValue: V, newValue: V ->\n        if (oldValue != newValue) iChanged()\n    }\n\n    override fun equals(other: Any?): Boolean =\n        other is ValueProperty<*> && tagKey == other.tagKey && value == other.value\n\n    override fun hashCode(): Int = Objects.hash(value, tagKey)\n\n    override fun toString(): String = \"Property($value)\"\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/layer/PropertyLayer.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property.layer\n\nimport network.rs485.logisticspipes.property.ObserverCallback\nimport network.rs485.logisticspipes.property.Property\nimport network.rs485.logisticspipes.property.PropertyHolder\nimport network.rs485.logisticspipes.property.ValueProperty\nimport java.util.*\nimport kotlin.streams.toList\n\n/**\n * The property is created with a list of properties that are not being written to.\n * A layer of a property can be retrieved by calling [overlay] with the original property.\n * Whenever a layer receives a write access, the underlying property will be copied to a new property on the [upperLayer].\n * A list of changed properties can be retrieved with [properties],\n * which e.g. can be used with [logisticspipes.network.packets.pipe.PipePropertiesUpdate].\n */\nopen class PropertyLayer(propertiesIn: Collection<Property<*>>) : PropertyHolder {\n    private val lowerLayer: List<Property<*>> = propertiesIn.toList()\n    private val upperLayer: MutableList<Property<*>?> = MutableList(propertiesIn.size) { null }\n    private val changedIndices: BitSet = BitSet(propertiesIn.size)\n    private val observersToRemove: MutableMap<Int, ObserverCallback<*>> = mutableMapOf()\n\n    /**\n     * A list consisting only of changed [properties][Property] on this [PropertyLayer].\n     */\n    override val properties: List<Property<*>>\n        get() = changedIndices.stream().mapToObj { upperLayer[it]!! }.toList()\n\n    private fun prepareWrite(idx: Int) {\n        upperLayer[idx] = lowerLayer[idx].copyProperty().also { upperLayerProperty ->\n            upperLayerProperty.addObserver {\n                // set to changed once the copied property is actually changed\n                changedIndices.set(idx)\n                observersToRemove.remove(idx)?.also { obs ->\n                    lowerLayer[idx].propertyObservers.remove(obs)\n                    upperLayerProperty.addObserver(obs)\n                    obs(upperLayerProperty)\n                }\n            }\n        }\n    }\n\n    private fun lookupIndex(prop: Property<*>, propList: List<Property<*>>): Int =\n        propList.indexOfFirst { other -> prop === other }.takeUnless { it == -1 }\n            ?: throw IllegalArgumentException(\"Property <$prop> not in this layer\")\n\n    fun <T, P : ValueProperty<T>> overlay(valueProp: P): ValuePropertyOverlay<T, P> =\n        ValuePropertyOverlayImpl(lookupIndex(valueProp, lowerLayer))\n\n    fun <T, P : Property<T>> overlay(prop: P): PropertyOverlay<T, P> =\n        PropertyOverlayImpl(lookupIndex(prop, lowerLayer))\n\n    @Suppress(\"UNCHECKED_CAST\")\n    fun <T, P : Property<T>> writeProp(prop: P): P {\n        val idx = lookupIndex(prop, lowerLayer)\n        if (!changedIndices.get(idx)) {\n            prepareWrite(idx)\n        }\n        return upperLayer[idx]!! as P\n    }\n\n    @Suppress(\"UNCHECKED_CAST\")\n    fun <T, P : Property<T>> addObserver(prop: P, observer: ObserverCallback<T>) {\n        val idx = lookupIndex(prop, lowerLayer)\n        if (changedIndices.get(idx)) {\n            (upperLayer[idx]!! as P).addObserver(observer)\n        } else {\n            observersToRemove[idx] = observer as ObserverCallback<*>\n            (lowerLayer[idx] as P).addObserver(observer)\n        }\n    }\n\n    fun unregister() = observersToRemove.forEach { lowerLayer[it.key].propertyObservers.remove(it.value) }\n\n    open inner class PropertyOverlayImpl<T, P : Property<T>>(private val idx: Int) : PropertyOverlay<T, P> {\n\n        @Suppress(\"UNCHECKED_CAST\")\n        protected fun lookupRead(): P = if (changedIndices.get(idx)) {\n            upperLayer[idx]!! as P\n        } else lowerLayer[idx] as P\n\n        @Suppress(\"UNCHECKED_CAST\")\n        protected fun lookupWrite(): P {\n            if (!changedIndices.get(idx)) {\n                prepareWrite(idx)\n            }\n            return upperLayer[idx]!! as P\n        }\n\n        override fun <V> read(func: (P) -> V): V = func(lookupRead())\n\n        override fun <V> write(func: (P) -> V): V = func(lookupWrite())\n\n        override fun isWriteMode(): Boolean = changedIndices.get(idx)\n\n    }\n\n    inner class ValuePropertyOverlayImpl<T, P : ValueProperty<T>>(idx: Int) :\n        PropertyOverlayImpl<T, P>(idx), ValuePropertyOverlay<T, P> {\n\n        override fun get(): T = lookupRead().value\n\n        override fun set(value: T) {\n            lookupWrite().value = value\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/layer/PropertyLayerInventoryAdapter.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property.layer\n\nimport network.rs485.logisticspipes.property.InventoryProperty\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\nimport net.minecraft.util.text.ITextComponent\n\nclass PropertyOverlayInventoryAdapter<T : IInventory, out P : InventoryProperty<T>>(\n    private val propertyOverlay: PropertyOverlay<T, P>,\n) : IInventory {\n    override fun getName(): String = propertyOverlay.read { it.name }\n\n    override fun hasCustomName(): Boolean = propertyOverlay.read { it.hasCustomName() }\n\n    override fun getDisplayName(): ITextComponent? = propertyOverlay.read { it.displayName }\n\n    override fun getSizeInventory(): Int = propertyOverlay.read { it.sizeInventory }\n\n    override fun isEmpty(): Boolean = propertyOverlay.read { it.isEmpty }\n\n    @Deprecated(\"do not modify returned ItemStack, handle as immutable\")\n    override fun getStackInSlot(index: Int): ItemStack = propertyOverlay.read { it.getStackInSlot(index) }\n\n    override fun decrStackSize(index: Int, count: Int): ItemStack =\n        propertyOverlay.write { it.decrStackSize(index, count) }\n\n    override fun removeStackFromSlot(index: Int): ItemStack = propertyOverlay.write { it.removeStackFromSlot(index) }\n\n    override fun setInventorySlotContents(index: Int, stack: ItemStack) =\n        propertyOverlay.write { it.setInventorySlotContents(index, stack) }\n\n    override fun getInventoryStackLimit(): Int = propertyOverlay.read { it.inventoryStackLimit }\n\n    override fun markDirty() = propertyOverlay.write { it.markDirty() }\n\n    override fun isUsableByPlayer(player: EntityPlayer): Boolean = propertyOverlay.read { it.isUsableByPlayer(player) }\n\n    @Deprecated(\"no-op on adapter\")\n    override fun openInventory(player: EntityPlayer) {\n    }\n\n    @Deprecated(\"no-op on adapter\")\n    override fun closeInventory(player: EntityPlayer) {\n    }\n\n    override fun isItemValidForSlot(index: Int, stack: ItemStack): Boolean =\n        propertyOverlay.read { it.isItemValidForSlot(index, stack) }\n\n    override fun getField(id: Int): Int = propertyOverlay.read { it.getField(id) }\n\n    override fun setField(id: Int, value: Int) = propertyOverlay.write { it.setField(id, value) }\n\n    override fun getFieldCount(): Int = propertyOverlay.read { it.fieldCount }\n\n    override fun clear() = propertyOverlay.write { it.clear() }\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/layer/PropertyOverlay.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property.layer\n\nimport network.rs485.logisticspipes.property.Property\n\ninterface PropertyOverlay<T, P : Property<T>> {\n    fun <V> read(func: (P) -> V): V\n    fun <V> write(func: (P) -> V): V\n    fun isWriteMode(): Boolean\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/layer/SimplePropertyOverlay.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property.layer\n\nimport network.rs485.logisticspipes.property.Property\n\nclass SimplePropertyOverlay<T : Any, P : Property<T>>(private val sourceProperty: P) :\n    PropertyOverlay<T, P> {\n    private var isPropertyCopied: Boolean = false\n    private lateinit var copiedProperty: P\n\n    override fun <V> read(func: (P) -> V): V =\n        if (isPropertyCopied) func(copiedProperty) else func(sourceProperty)\n\n    override fun <V> write(func: (P) -> V): V {\n        if (!isPropertyCopied) {\n            @Suppress(\"UNCHECKED_CAST\") // as specified by copyProperty\n            copiedProperty = sourceProperty.copyProperty() as P\n            isPropertyCopied = true\n        }\n        return func(copiedProperty)\n    }\n\n    override fun isWriteMode(): Boolean = isPropertyCopied\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/property/layer/ValuePropertyOverlay.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property.layer\n\nimport network.rs485.logisticspipes.property.ValueProperty\n\ninterface ValuePropertyOverlay<T, P : ValueProperty<T>> : PropertyOverlay<T, P> {\n    fun get(): T\n    fun set(value: T)\n}\n"
  },
  {
    "path": "src/api/kotlin/network/rs485/logisticspipes/util/Rectangle.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\nimport kotlin.math.max\nimport kotlin.math.min\nimport kotlin.math.roundToInt\n\ninterface IRectangle {\n    // Size getters\n    val width: Float\n    val height: Float\n\n    // Position getters\n    val x0: Float\n    val y0: Float\n    val x1: Float\n        get() = x0 + width\n    val y1: Float\n        get() = y0 + height\n\n    // Named getters\n    val left: Float\n        get() = x0\n    val right: Float\n        get() = x1\n    val top: Float\n        get() = y0\n    val bottom: Float\n        get() = y1\n\n    // Corners\n    val topRight: Pair<Float, Float>\n        get() = right to top\n    val topLeft: Pair<Float, Float>\n        get() = left to top\n    val bottomLeft: Pair<Float, Float>\n        get() = left to bottom\n    val bottomRight: Pair<Float, Float>\n        get() = right to bottom\n\n    // Integer getters, only to be used when precision is not important\n    val roundedX: Int\n        get() = x0.roundToInt()\n    val roundedY: Int\n        get() = y0.roundToInt()\n    val roundedWidth: Int\n        get() = width.roundToInt()\n    val roundedHeight: Int\n        get() = height.roundToInt()\n    val roundedLeft: Int\n        get() = roundedX\n    val roundedRight: Int\n        get() = right.roundToInt()\n    val roundedTop: Int\n        get() = roundedY\n    val roundedBottom: Int\n        get() = bottom.roundToInt()\n\n    // Non-destructive\n    fun translated(translateX: Float, translateY: Float): IRectangle\n    fun translated(translateX: Int, translateY: Int): IRectangle\n    fun translated(rect: IRectangle): IRectangle = translated(rect.x0, rect.y0)\n\n    // Non-destructive\n    fun scaled(multiplier: Float): IRectangle\n\n    // Logic checks\n    fun contains(x: Float, y: Float): Boolean = x in this.x0..x1 && y in this.y0..y1\n    fun contains(x: Int, y: Int): Boolean = contains(x.toFloat(), y.toFloat())\n    fun contains(rect: IRectangle): Boolean = contains(rect.x0, rect.y0) && contains(rect.x1, rect.y1)\n    fun intersects(rect: IRectangle): Boolean =\n        !(right < rect.left || rect.right < left || bottom < rect.top || rect.bottom < top)\n\n    // Operations\n    fun overlap(rect: IRectangle): IRectangle\n\n}\n\ndata class Rectangle(\n    override val x0: Float = 0.0f,\n    override val y0: Float = 0.0f,\n    override val width: Float,\n    override val height: Float,\n) : IRectangle {\n\n    /**\n     * Default constructor with integers as parameters.\n     */\n    constructor(x: Int = 0, y: Int = 0, width: Int, height: Int) : this(\n        x0 = x.toFloat(),\n        y0 = y.toFloat(),\n        width = width.toFloat(),\n        height = height.toFloat()\n    )\n\n    /**\n     * Creates rectangle from two points, since dimensions are Int the second point will be rounded down to accommodate.\n     * The exact corner that each point represents is not enforced but some things might break if it doesn't match this.\n     * @param firstPoint top-left point of the rectangle.\n     * @param secondPoint bottom-right point of the rectangle.\n     */\n    constructor(firstPoint: Pair<Float, Float>, secondPoint: Pair<Float, Float>) : this(\n        x0 = firstPoint.first,\n        y0 = firstPoint.second,\n        width = (secondPoint.first - firstPoint.first),\n        height = (secondPoint.second - firstPoint.second)\n    )\n\n    override fun translated(translateX: Float, translateY: Float): Rectangle =\n        Rectangle(x0 = x0 + translateX, y0 = y0 + translateY, width = width, height = height)\n\n    override fun translated(translateX: Int, translateY: Int): Rectangle =\n        Rectangle(x0 = x0 + translateX, y0 = y0 + translateY, width = width, height = height)\n\n    override fun scaled(multiplier: Float): Rectangle = Rectangle(\n        x0 = x0 * multiplier,\n        y0 = y0 * multiplier,\n        width = width * multiplier,\n        height = height * multiplier\n    )\n\n    override fun overlap(rect: IRectangle): Rectangle =\n        Rectangle(max(x0, rect.x0) to max(y0, rect.y0), min(x1, rect.x1) to min(y1, rect.y1))\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/network/packets/SetCurrentPagePacket.java",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.network.packets;\n\nimport java.util.List;\nimport java.util.Objects;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.inventory.EntityEquipmentSlot;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\n\nimport logisticspipes.LPItems;\nimport logisticspipes.network.abstractpackets.ModernPacket;\nimport logisticspipes.utils.StaticResolve;\nimport network.rs485.logisticspipes.gui.guidebook.IPageData;\nimport network.rs485.logisticspipes.gui.guidebook.PageData;\nimport network.rs485.logisticspipes.guidebook.ItemGuideBook;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\n\n@StaticResolve\npublic class SetCurrentPagePacket extends ModernPacket {\n\n\t@Nullable\n\tprivate IPageData currentPage;\n\n\tprivate EntityEquipmentSlot equipmentSlot;\n\n\tprivate List<? extends IPageData> bookmarks;\n\n\tpublic SetCurrentPagePacket(int id) {\n\t\tsuper(id);\n\t}\n\n\t@Override\n\tpublic void processPacket(EntityPlayer player) {\n\t\tif (currentPage == null) return;\n\t\tItemStack book = player.getItemStackFromSlot(equipmentSlot);\n\t\tif (book.isEmpty() || !(book.getItem() instanceof ItemGuideBook)) return;\n\t\tNBTTagCompound compound;\n\t\tif (book.hasTagCompound()) {\n\t\t\tcompound = Objects.requireNonNull(book.getTagCompound());\n\t\t} else {\n\t\t\tcompound = new NBTTagCompound();\n\t\t}\n\t\tfinal NBTTagCompound nbt = LPItems.itemGuideBook.updateNBT(compound, currentPage, bookmarks);\n\t\tbook.setTagCompound(nbt);\n\t}\n\n\t@Override\n\tpublic void readData(LPDataInput input) {\n\t\tsuper.readData(input);\n\t\tequipmentSlot = input.readEnum(EntityEquipmentSlot.class);\n\t\tcurrentPage = new PageData(input);\n\t\tbookmarks = input.readArrayList(PageData::new);\n\t}\n\n\t@Override\n\tpublic void writeData(LPDataOutput output) {\n\t\tsuper.writeData(output);\n\t\tif (currentPage == null) throw new NullPointerException(\"Current page may not be null\");\n\t\toutput.writeEnum(equipmentSlot);\n\t\tcurrentPage.write(output);\n\t\toutput.writeCollection(bookmarks);\n\t}\n\n\t@Override\n\tpublic ModernPacket template() {\n\t\treturn new SetCurrentPagePacket(getId());\n\t}\n\n\tpublic SetCurrentPagePacket setCurrentPage(IPageData currentPage) {\n\t\tthis.currentPage = currentPage;\n\t\treturn this;\n\t}\n\n\tpublic SetCurrentPagePacket setEquipmentSlot(EntityEquipmentSlot equipmentSlot) {\n\t\tthis.equipmentSlot = equipmentSlot;\n\t\treturn this;\n\t}\n\n\tpublic SetCurrentPagePacket setBookmarks(List<? extends IPageData> bookmarks) {\n\t\tthis.bookmarks = bookmarks;\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/BlockAccessDelegate.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp;\n\nimport net.minecraft.world.IBlockAccess;\n\nimport lombok.experimental.Delegate;\n\npublic class BlockAccessDelegate implements IBlockAccess {\n\n\t@Delegate\n\tprotected final IBlockAccess access;\n\n\tpublic BlockAccessDelegate(IBlockAccess access) {\n\t\tthis.access = access;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/IMCMPProxy.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp;\n\nimport java.util.List;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.math.AxisAlignedBB;\n\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPBlockAccess;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPLTGPCompanion;\n\npublic interface IMCMPProxy {\n\n\tIMCMPLTGPCompanion createMCMPCompanionFor(LogisticsTileGenericPipe pipe);\n\n\tIMCMPBlockAccess createMCMPBlockAccess();\n\n\t@SideOnly(Side.CLIENT)\n\tvoid addQuads(@Nonnull List<BakedQuad> list, IBlockState state, EnumFacing side, long rand);\n\n\tvoid registerTileEntities();\n\n\tboolean checkIntersectionWith(LogisticsTileGenericPipe logisticsTileGenericPipe, AxisAlignedBB aabb);\n\n\tboolean hasParts(LogisticsTileGenericPipe pipeTile);\n\n\t@SideOnly(Side.CLIENT)\n\tvoid renderTileEntitySpecialRenderer(LogisticsTileGenericPipe tileentity, double x, double y, double z, float partialTicks, int destroyStage, float alpha);\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/MCMPProxy.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Optional;\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.material.Material;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.client.renderer.GlStateManager;\nimport net.minecraft.client.renderer.RenderGlobal;\nimport net.minecraft.client.renderer.block.model.BakedQuad;\nimport net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;\nimport net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.world.World;\n\nimport net.minecraftforge.client.event.DrawBlockHighlightEvent;\nimport net.minecraftforge.common.MinecraftForge;\nimport net.minecraftforge.event.world.BlockEvent;\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent;\nimport net.minecraftforge.fml.common.registry.GameRegistry;\nimport net.minecraftforge.fml.relauncher.Side;\nimport net.minecraftforge.fml.relauncher.SideOnly;\n\nimport mcmultipart.MCMultiPart;\nimport mcmultipart.api.event.DrawMultipartHighlightEvent;\nimport mcmultipart.api.multipart.MultipartOcclusionHelper;\nimport mcmultipart.block.BlockMultipartContainer;\nimport mcmultipart.block.TileMultipartContainer;\nimport mcmultipart.client.ModelMultipartContainer;\nimport mcmultipart.multipart.PartInfo;\n\nimport logisticspipes.LPBlocks;\nimport logisticspipes.LPConstants;\nimport logisticspipes.asm.mcmp.MCMPHooks;\nimport logisticspipes.modplugins.mcmp.LPPipeMultipart;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPBlockAccess;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.IMCMPLTGPCompanion;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.LPTileMultipartContainer;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.MCMPBlockAccess;\nimport network.rs485.logisticspipes.proxy.mcmp.subproxy.MCMPLTGPCompanion;\n\npublic class MCMPProxy implements IMCMPProxy {\n\n\t@SideOnly(Side.CLIENT)\n\tprivate ModelMultipartContainer modelMultipartContainer;\n\n\tpublic MCMPProxy() {\n\t\tMCMPHooks.mcmpGetTEHook = (world, pos) -> {\n\t\t\tTileEntity tile = world.getTileEntity(pos);\n\t\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t\tLogisticsTileGenericPipe lpTile = (LogisticsTileGenericPipe) tile;\n\t\t\t\tTileEntity nTile = lpTile.imcmpltgpCompanion.getMCMPTileEntity();\n\t\t\t\tif (nTile != null) {\n\t\t\t\t\treturn nTile;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn tile;\n\t\t};\n\t\tMinecraftForge.EVENT_BUS.register(this);\n\t}\n\n\t@Override\n\tpublic IMCMPLTGPCompanion createMCMPCompanionFor(LogisticsTileGenericPipe pipe) {\n\t\treturn new MCMPLTGPCompanion(pipe);\n\t}\n\n\t@Override\n\tpublic IMCMPBlockAccess createMCMPBlockAccess() {\n\t\treturn new MCMPBlockAccess();\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void addQuads(@Nonnull List<BakedQuad> list, IBlockState state, EnumFacing side, long rand) {\n\t\tif (modelMultipartContainer == null) modelMultipartContainer = new ModelMultipartContainer();\n\t\tlist.addAll(modelMultipartContainer.getQuads(state, side, rand));\n\t}\n\n\t@Override\n\tpublic void registerTileEntities() {\n\t\tGameRegistry.registerTileEntity(LPTileMultipartContainer.class, new ResourceLocation(LPConstants.LP_MOD_ID, \"mcmp_lp_tile_multipart_container\"));\n\t}\n\n\t@Override\n\tpublic boolean checkIntersectionWith(LogisticsTileGenericPipe logisticsTileGenericPipe, AxisAlignedBB aabb) {\n\t\treturn ((TileMultipartContainer) logisticsTileGenericPipe.imcmpltgpCompanion.getMCMPTileEntity()).getParts().values().stream().filter(i -> !(i.getPart() instanceof LPPipeMultipart)).anyMatch(i -> MultipartOcclusionHelper\n\t\t\t\t.testBoxIntersection(i.getPart().getOcclusionBoxes(i), Collections.singletonList(aabb)));\n\t}\n\n\t@Override\n\tpublic boolean hasParts(LogisticsTileGenericPipe pipeTile) {\n\t\treturn ((TileMultipartContainer) pipeTile.imcmpltgpCompanion.getMCMPTileEntity()).getParts().values().stream().anyMatch(i -> !(i.getPart() instanceof LPPipeMultipart));\n\t}\n\n\t@Override\n\t@SideOnly(Side.CLIENT)\n\tpublic void renderTileEntitySpecialRenderer(LogisticsTileGenericPipe tileentity, double x, double y, double z, float partialTicks, int destroyStage,\n\t\t\tfloat alpha) {\n\t\tTileEntitySpecialRenderer<TileEntity> renderer = TileEntityRendererDispatcher.instance\n\t\t\t\t.getRenderer(TileMultipartContainer.class);\n\t\tif (destroyStage < 0 || (tileentity.imcmpltgpCompanion.getMCMPTileEntity() != null && Minecraft.getMinecraft().objectMouseOver != null)) {\n\t\t\trenderer.render(tileentity.imcmpltgpCompanion.getMCMPTileEntity(), x, y, z, partialTicks, destroyStage, alpha);\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\t@SideOnly(Side.CLIENT)\n\tpublic void onDrawHighlight(DrawBlockHighlightEvent event) {\n\t\tif (event instanceof DrawMultipartHighlightEvent) {\n\t\t\treturn;\n\t\t}\n\t\tRayTraceResult hit = event.getTarget();\n\t\tif (hit.typeOfHit != RayTraceResult.Type.BLOCK) {\n\t\t\treturn;\n\t\t}\n\n\t\tBlockPos pos = hit.getBlockPos();\n\t\tEntityPlayer player = event.getPlayer();\n\t\tif (player == null) {\n\t\t\treturn;\n\t\t}\n\t\tWorld world = player.world;\n\t\tif (world == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (world.getBlockState(pos).getBlock() == LPBlocks.pipe) {\n\t\t\tOptional<TileMultipartContainer> tile = BlockMultipartContainer.getTile(world, pos);\n\t\t\tif (!tile.isPresent()) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tint slotID = hit.subHit;\n\t\t\tif (slotID < 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tPartInfo info = tile.get().getParts().get(MCMultiPart.slotRegistry.getValue(slotID));\n\t\t\tif (info == null || !(hit.hitInfo instanceof RayTraceResult)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thit = (RayTraceResult) hit.hitInfo;\n\n\t\t\tfloat partialTicks = event.getPartialTicks();\n\t\t\tif (!MinecraftForge.EVENT_BUS.post(new DrawMultipartHighlightEvent(event.getContext(), player, hit, slotID, partialTicks, info))) {\n\t\t\t\tGlStateManager.enableBlend();\n\t\t\t\tGlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA,\n\t\t\t\t\t\tGlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);\n\t\t\t\tGlStateManager.glLineWidth(2.0F);\n\t\t\t\tGlStateManager.disableTexture2D();\n\t\t\t\tGlStateManager.depthMask(false);\n\t\t\t\tIBlockState state = info.getState();\n\n\t\t\t\tif (state.getMaterial() != Material.AIR && world.getWorldBorder().contains(pos)) {\n\t\t\t\t\tdouble x = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks;\n\t\t\t\t\tdouble y = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks;\n\t\t\t\t\tdouble z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks;\n\t\t\t\t\tRenderGlobal.drawSelectionBoundingBox(info.getPart().getSelectedBoundingBox(info).grow(0.002).offset(-x, -y, -z),\n\t\t\t\t\t\t\t0.0F, 0.0F, 0.0F, 0.4F);\n\t\t\t\t}\n\n\t\t\t\tGlStateManager.depthMask(true);\n\t\t\t\tGlStateManager.enableTexture2D();\n\t\t\t\tGlStateManager.disableBlend();\n\t\t\t}\n\n\t\t\tevent.setCanceled(true);\n\t\t}\n\t}\n\n\t@SubscribeEvent\n\tpublic void onNeighborNotify(BlockEvent.NeighborNotifyEvent event) {\n\t\tTileEntity tile = event.getWorld().getTileEntity(event.getPos());\n\t\tif (tile instanceof LogisticsTileGenericPipe) {\n\t\t\t((LogisticsTileGenericPipe) tile).scheduleNeighborChange();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/subproxy/IMCMPBlockAccess.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp.subproxy;\n\nimport java.util.List;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.BlockStateContainer;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\npublic interface IMCMPBlockAccess {\n\n\tvoid addBlockState(BlockStateContainer.Builder builder);\n\n\tIBlockState getExtendedState(IBlockState state, IBlockAccess worldIn, BlockPos pos);\n\n\tvoid addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entity, boolean isActualState);\n\n\tRayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end);\n\n\tBlock getBlock();\n\n\tvoid addDrops(NonNullList<ItemStack> list, IBlockAccess world, BlockPos pos, IBlockState state, int fortune);\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/subproxy/IMCMPLTGPCompanion.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp.subproxy;\n\nimport javax.annotation.Nullable;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\npublic interface IMCMPLTGPCompanion {\n\n\tboolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, @Nullable EnumFacing facing);\n\n\t@Nullable\n\t<T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable EnumFacing facing);\n\n\tNBTTagCompound getUpdateTag();\n\n\tvoid handleUpdateTag(NBTTagCompound tag);\n\n\tTileEntity getMCMPTileEntity();\n\n\tvoid update();\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/subproxy/LPTileMultipartContainer.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp.subproxy;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\nimport java.util.Set;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.util.ITickable;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.World;\n\nimport lombok.SneakyThrows;\nimport mcmultipart.api.multipart.IMultipartTile;\nimport mcmultipart.api.slot.EnumCenterSlot;\nimport mcmultipart.api.slot.IPartSlot;\nimport mcmultipart.block.TileMultipartContainer;\nimport mcmultipart.multipart.PartInfo;\n\nimport logisticspipes.modplugins.mcmp.LPMCMPAddon;\nimport logisticspipes.modplugins.mcmp.LPMultipartTile;\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\nimport logisticspipes.ticks.LPTickHandler;\n\npublic class LPTileMultipartContainer extends TileMultipartContainer.Ticking {\n\n\tprivate static final Field isInWorldField;\n\tprivate static final Field partsField;\n\tprivate static final Field tickingPartsField;\n\n\tstatic {\n\t\ttry {\n\t\t\tisInWorldField = TileMultipartContainer.class.getDeclaredField(\"isInWorld\");\n\t\t\tpartsField = TileMultipartContainer.class.getDeclaredField(\"parts\");\n\t\t\ttickingPartsField = TileMultipartContainer.Ticking.class.getDeclaredField(\"tickingParts\");\n\t\t} catch (NoSuchFieldException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tisInWorldField.setAccessible(true);\n\t\tpartsField.setAccessible(true);\n\t\ttickingPartsField.setAccessible(true);\n\t}\n\n\tprivate final LogisticsTileGenericPipe pipe;\n\tprivate Map<IPartSlot, PartInfo> parts = null;\n\tprivate PartInfo partInfo = null;\n\n\tprivate final Set<ITickable> superTickingParts;\n\n\t@SneakyThrows({ IllegalAccessException.class })\n\tpublic LPTileMultipartContainer(LogisticsTileGenericPipe pipe) {\n\t\tsuper();\n\t\tthis.pipe = pipe;\n\t\tisInWorldField.set(this, false);\n\t\tthis.setWorld(pipe.getWorld());\n\t\tthis.setPos(pipe.getBlockPos());\n\n\t\tsuperTickingParts = (Set<ITickable>) tickingPartsField.get(this);\n\t}\n\n\t@Override\n\tpublic World getPartWorld() {\n\t\treturn this.getWorld();\n\t}\n\n\t@SuppressWarnings(\"NullableProblems\") // TileEntity#getWorld should be @Nullable\n\t@Nullable\n\t@Override\n\tpublic World getWorld() {\n\t\treturn pipe.hasWorld() ? pipe.getWorld() : super.getWorld();\n\t}\n\n\t@Override\n\tpublic void setWorld(World world) {\n\t\tsuper.setWorld(world);\n\t}\n\n\t@Override\n\tpublic BlockPos getPartPos() {\n\t\treturn pipe.getBlockPos();\n\t}\n\n\t@Override\n\tpublic Map<IPartSlot, PartInfo> getParts() {\n\t\tcheckLocalPartsFieldInit();\n\t\treturn super.getParts();\n\t}\n\n\t@SneakyThrows({ IllegalAccessException.class })\n\tprivate void checkLocalPartsFieldInit() {\n\t\tif (parts == null) {\n\t\t\tparts = (Map<IPartSlot, PartInfo>) partsField.get(this);\n\t\t}\n\t\tif (partInfo == null) {\n\t\t\tpartInfo = new PartInfo(this, EnumCenterSlot.CENTER, LPMCMPAddon.lpPipeMultipart, this.pipe.getWorld().getBlockState(this.pipe.getBlockPos()), new LPMultipartTile(pipe));\n\t\t}\n\t\tparts.put(EnumCenterSlot.CENTER, partInfo);\n\t}\n\n\t@Override\n\tprotected void updateWorldState() {\n\t\tif (this.superTickingParts.isEmpty()) return; //\n\t\t//super.updateWorldState();\n\t\tLPTickHandler.getWorldInfo(getWorld()).setSkipBlockUpdateForWorld(true);\n\t\tIBlockState prevSt = this.getWorld().getBlockState(this.getPos());\n\n\t\tIBlockState st = this.getWorld().getBlockState(this.getPos());\n\t\tthis.getWorld().markAndNotifyBlock(this.getPos(), null, prevSt, st, 1);\n\t\tthis.getWorld().checkLight(this.getPos());\n\t\tLPTickHandler.getWorldInfo(getWorld()).setSkipBlockUpdateForWorld(true);\n\t}\n\n\t@Override\n\tpublic boolean canAddPart(IPartSlot slot, IBlockState state, IMultipartTile tile) {\n\t\tif (!pipe.isMultipartAllowedInPipe()) return false;\n\t\treturn super.canAddPart(slot, state, tile);\n\t}\n\n\t@Override\n\tpublic void addPart(IPartSlot slot, IBlockState state, IMultipartTile tile) {\n\t\tif (!pipe.isMultipartAllowedInPipe()) return;\n\t\tsuper.addPart(slot, state, tile);\n\t}\n\n\t@Override\n\tprotected void add(IPartSlot slot, PartInfo partInfo) {\n\t\tif (!pipe.isMultipartAllowedInPipe()) return;\n\t\tsuper.add(slot, partInfo);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/subproxy/MCMPBlockAccess.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp.subproxy;\n\nimport java.util.List;\n\nimport net.minecraft.block.Block;\nimport net.minecraft.block.state.BlockStateContainer;\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.math.AxisAlignedBB;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.util.math.RayTraceResult;\nimport net.minecraft.util.math.Vec3d;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport mcmultipart.MCMultiPart;\nimport mcmultipart.block.BlockMultipartContainer;\n\npublic class MCMPBlockAccess implements IMCMPBlockAccess {\n\n\tprivate final BlockMultipartContainer multipart = (BlockMultipartContainer) MCMultiPart.multipart;\n\n\t@Override\n\tpublic void addBlockState(BlockStateContainer.Builder builder) {\n\t\tbuilder.add(BlockMultipartContainer.PROPERTY_INFO);\n\t}\n\n\t@Override\n\tpublic IBlockState getExtendedState(IBlockState state, IBlockAccess worldIn, BlockPos pos) {\n\t\treturn multipart.getExtendedState(state, worldIn, pos);\n\t}\n\n\t@Override\n\tpublic void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entity,\n\t\t\tboolean isActualState) {\n\t\tmultipart.addCollisionBoxToList(state, world, pos, entityBox, collidingBoxes, entity, isActualState);\n\t}\n\n\t@Override\n\tpublic RayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end) {\n\t\treturn multipart.collisionRayTrace(state, world, pos, start, end);\n\t}\n\n\t@Override\n\tpublic Block getBlock() {\n\t\treturn multipart;\n\t}\n\n\t@Override\n\tpublic void addDrops(NonNullList<ItemStack> list, IBlockAccess world, BlockPos pos, IBlockState state, int fortune) {\n\t\tlist.addAll(multipart.getDrops(world, pos, state, fortune));\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/subproxy/MCMPLTGPCompanion.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp.subproxy;\n\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.EnumFacing;\n\nimport net.minecraftforge.common.capabilities.Capability;\nimport net.minecraftforge.common.capabilities.CapabilityInject;\n\nimport mcmultipart.api.multipart.ITileMultipartContainerProvider;\nimport mcmultipart.api.ref.MCMPCapabilities;\nimport mcmultipart.block.TileMultipartContainer;\n\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe;\n\npublic class MCMPLTGPCompanion implements IMCMPLTGPCompanion {\n\n\tprivate final LPTileMultipartContainer lpTileMultipartContainer;\n\tprivate final MCMPMultipartContainerProvider lpTileMultipartContainerProvider;\n\n\t@CapabilityInject(ITileMultipartContainerProvider.class)\n\tprivate static Capability<ITileMultipartContainerProvider> TILE_MULTIPART_CONTAINER_PROVIDER_CAPABILITY;\n\n\tpublic MCMPLTGPCompanion(LogisticsTileGenericPipe pipe) {\n\t\tlpTileMultipartContainer = new LPTileMultipartContainer(pipe);\n\t\tif (TILE_MULTIPART_CONTAINER_PROVIDER_CAPABILITY == null) {\n\t\t\tlpTileMultipartContainerProvider = null;\n\t\t} else {\n\t\t\tlpTileMultipartContainerProvider = new MCMPMultipartContainerProvider(lpTileMultipartContainer);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == MCMPCapabilities.MULTIPART_CONTAINER) {\n\t\t\treturn true;\n\t\t}\n\t\tif (capability == TILE_MULTIPART_CONTAINER_PROVIDER_CAPABILITY) {\n\t\t\treturn true;\n\t\t}\n\t\treturn lpTileMultipartContainer.hasCapability(capability, facing);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {\n\t\tif (capability == MCMPCapabilities.MULTIPART_CONTAINER) {\n\t\t\treturn (T) lpTileMultipartContainer;\n\t\t}\n\t\tif (capability == TILE_MULTIPART_CONTAINER_PROVIDER_CAPABILITY) {\n\t\t\treturn (T) lpTileMultipartContainerProvider;\n\t\t}\n\t\treturn lpTileMultipartContainer.getCapability(capability, facing);\n\t}\n\n\t@Override\n\tpublic NBTTagCompound getUpdateTag() {\n\t\treturn lpTileMultipartContainer.getUpdateTag();\n\t}\n\n\t@Override\n\tpublic void handleUpdateTag(NBTTagCompound tag) {\n\t\tlpTileMultipartContainer.handleUpdateTag(tag);\n\t}\n\n\t@Override\n\tpublic TileEntity getMCMPTileEntity() {\n\t\treturn lpTileMultipartContainer;\n\t}\n\n\t@Override\n\tpublic void update() {\n\t\tlpTileMultipartContainer.update();\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/proxy/mcmp/subproxy/MCMPMultipartContainerProvider.java",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy.mcmp.subproxy;\n\nimport mcmultipart.api.multipart.ITileMultipartContainerProvider;\nimport mcmultipart.block.TileMultipartContainer;\n\npublic class MCMPMultipartContainerProvider implements ITileMultipartContainerProvider {\n\n\tprivate final TileMultipartContainer multipartContainer;\n\n\tpublic MCMPMultipartContainerProvider(TileMultipartContainer multipartContainer) {\n\t\tthis.multipartContainer = multipartContainer;\n\t}\n\n\t@Override\n\tpublic TileMultipartContainer getTileMultipartContainer() {\n\t\treturn multipartContainer;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/util/LPDataIOWrapper.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.Collection;\nimport java.util.EnumSet;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.LinkedList;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.stream.IntStream;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.CompressedStreamTools;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.ResourceLocation;\n\nimport io.netty.buffer.ByteBuf;\nimport static io.netty.buffer.Unpooled.buffer;\nimport static io.netty.buffer.Unpooled.wrappedBuffer;\n\nimport logisticspipes.LogisticsPipes;\nimport logisticspipes.network.IReadListObject;\nimport logisticspipes.network.IWriteListObject;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic final class LPDataIOWrapper implements LPDataInput, LPDataOutput {\n\n\tprivate static final Charset UTF_8 = StandardCharsets.UTF_8;\n\tprivate static final HashMap<Long, LPDataIOWrapper> BUFFER_WRAPPER_MAP = new HashMap<>();\n\tByteBuf localBuffer;\n\tprivate int reference;\n\n\tprivate LPDataIOWrapper(ByteBuf buffer) {\n\t\tlocalBuffer = buffer;\n\t}\n\n\t@Nonnull\n\tprivate static LPDataIOWrapper getInstance(ByteBuf buffer) {\n\t\tif (buffer.hasMemoryAddress()) {\n\t\t\tsynchronized (BUFFER_WRAPPER_MAP) {\n\t\t\t\tLPDataIOWrapper instance = BUFFER_WRAPPER_MAP.get(buffer.memoryAddress());\n\t\t\t\tif (instance == null) {\n\t\t\t\t\tinstance = new LPDataIOWrapper(buffer);\n\t\t\t\t\tBUFFER_WRAPPER_MAP.put(buffer.memoryAddress(), instance);\n\t\t\t\t}\n\t\t\t\t++instance.reference;\n\t\t\t\treturn instance;\n\t\t\t}\n\t\t} else {\n\t\t\treturn new LPDataIOWrapper(buffer);\n\t\t}\n\t}\n\n\tpublic static void provideData(byte[] data, LPDataInputConsumer dataInputConsumer) {\n\t\tByteBuf dataBuffer = wrappedBuffer(data);\n\t\tLPDataIOWrapper lpData = getInstance(dataBuffer);\n\n\t\tdataInputConsumer.accept(lpData);\n\n\t\tlpData.unsetBuffer();\n\t\tdataBuffer.release();\n\t}\n\n\t@Nonnull\n\tpublic static byte[] collectData(LPDataOutputConsumer dataOutputConsumer) {\n\t\tByteBuf dataBuffer = buffer();\n\t\tLPDataIOWrapper lpData = getInstance(dataBuffer);\n\n\t\tdataOutputConsumer.accept(lpData);\n\n\t\tlpData.unsetBuffer();\n\n\t\tbyte[] data = new byte[dataBuffer.readableBytes()];\n\t\tdataBuffer.getBytes(0, data);\n\n\t\tdataBuffer.release();\n\t\treturn data;\n\t}\n\n\tpublic static void provideData(ByteBuf dataBuffer, LPDataInputConsumer dataInputConsumer) {\n\t\t// ignore empty data\n\t\tif (dataBuffer.readableBytes() == 0) return;\n\t\tLPDataIOWrapper lpData = getInstance(dataBuffer);\n\n\t\tdataInputConsumer.accept(lpData);\n\n\t\tlpData.unsetBuffer();\n\t}\n\n\tpublic static void writeData(ByteBuf dataBuffer, LPDataOutputConsumer dataOutputConsumer) {\n\t\t// ignore unwritable data\n\t\tif (dataBuffer.writableBytes() == 0) return;\n\t\tLPDataIOWrapper lpData = getInstance(dataBuffer);\n\n\t\tdataOutputConsumer.accept(lpData);\n\n\t\tlpData.unsetBuffer();\n\t}\n\n\tprivate void unsetBuffer() {\n\t\tif (localBuffer.hasMemoryAddress()) {\n\t\t\tsynchronized (BUFFER_WRAPPER_MAP) {\n\t\t\t\tif (--reference < 1) {\n\t\t\t\t\tBUFFER_WRAPPER_MAP.remove(localBuffer.memoryAddress());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlocalBuffer = null;\n\t}\n\n\t@Override\n\tpublic void writeByteArray(@Nullable byte[] arr) {\n\t\tif (arr == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteInt(arr.length);\n\t\t\twriteBytes(arr);\n\t\t}\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic byte[] readByteArray() {\n\t\tfinal int length = readInt();\n\t\tif (length == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn readBytes(length);\n\t}\n\n\t@Override\n\tpublic void writeByte(int b) {\n\t\tlocalBuffer.writeByte(b);\n\t}\n\n\t@Override\n\tpublic void writeByte(byte b) {\n\t\tlocalBuffer.writeByte(b);\n\t}\n\n\t@Override\n\tpublic void writeShort(int s) {\n\t\tlocalBuffer.writeShort(s);\n\t}\n\n\t@Override\n\tpublic void writeShort(short b) {\n\t\tlocalBuffer.writeShort(b);\n\t}\n\n\t@Override\n\tpublic void writeInt(int i) {\n\t\tlocalBuffer.writeInt(i);\n\t}\n\n\t@Override\n\tpublic void writeLong(long l) {\n\t\tlocalBuffer.writeLong(l);\n\t}\n\n\t@Override\n\tpublic void writeFloat(float f) {\n\t\tlocalBuffer.writeFloat(f);\n\t}\n\n\t@Override\n\tpublic void writeDouble(double d) {\n\t\tlocalBuffer.writeDouble(d);\n\t}\n\n\t@Override\n\tpublic void writeBoolean(boolean b) {\n\t\tlocalBuffer.writeBoolean(b);\n\t}\n\n\t@Override\n\tpublic void writeUTF(@Nullable String s) {\n\t\tif (s == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteByteArray(s.getBytes(UTF_8));\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeFacing(@Nullable EnumFacing direction) {\n\t\tif (direction == null) {\n\t\t\twriteByte(Byte.MIN_VALUE);\n\t\t} else {\n\t\t\twriteByte(direction.ordinal());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeResourceLocation(@Nullable ResourceLocation resource) {\n\t\tif (resource == null) {\n\t\t\twriteBoolean(false);\n\t\t} else {\n\t\t\twriteBoolean(true);\n\t\t\twriteUTF(resource.toString());\n\t\t}\n\t}\n\n\t@Override\n\tpublic <T extends Enum<T>> void writeEnumSet(EnumSet<T> types, Class<T> clazz) {\n\t\tT[] parts = clazz.getEnumConstants();\n\t\tfinal int length = parts.length / 8 + (parts.length % 8 == 0 ? 0 : 1);\n\t\tbyte[] set = new byte[length];\n\n\t\tfor (T part : parts) {\n\t\t\tif (types.contains(part)) {\n\t\t\t\tbyte i = (byte) (1 << (part.ordinal() % 8));\n\t\t\t\tset[part.ordinal() / 8] |= i;\n\t\t\t}\n\t\t}\n\t\twriteByteArray(set);\n\t}\n\n\t@Override\n\tpublic void writeBitSet(@Nonnull BitSet bits) {\n\t\twriteLongArray(bits.toLongArray());\n\t}\n\n\t@Override\n\tpublic void writeNBTTagCompound(@Nullable NBTTagCompound tag) {\n\t\tif (tag == null) {\n\t\t\twriteByte(0);\n\t\t} else {\n\t\t\twriteByte(1);\n\t\t\ttry {\n\t\t\t\tByteArrayOutputStream output = new ByteArrayOutputStream();\n\t\t\t\tCompressedStreamTools.writeCompressed(tag, output);\n\t\t\t\twriteByteArray(output.toByteArray());\n\t\t\t} catch (IOException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeBooleanArray(@Nullable boolean[] arr) {\n\t\tif (arr == null) {\n\t\t\twriteInt(-1);\n\t\t} else if (arr.length == 0) {\n\t\t\twriteInt(0);\n\t\t\twriteByteArray(null);\n\t\t} else {\n\t\t\tBitSet bits = new BitSet(arr.length);\n\t\t\tfor (int i = 0; i < arr.length; i++) {\n\t\t\t\tbits.set(i, arr[i]);\n\t\t\t}\n\t\t\twriteInt(arr.length);\n\t\t\twriteByteArray(bits.toByteArray());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeUTFArray(@Nullable String[] arr) {\n\t\tif (arr == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteInt(arr.length);\n\t\t\tfor (String s : arr) {\n\t\t\t\twriteUTF(s);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeIntArray(@Nullable int[] arr) {\n\t\tif (arr == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteInt(arr.length);\n\t\t\tfor (int i : arr) {\n\t\t\t\twriteInt(i);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeItemStack(@Nonnull ItemStack itemstack) {\n\t\tif (itemstack.isEmpty()) {\n\t\t\twriteInt(0);\n\t\t} else {\n\t\t\twriteInt(Item.getIdFromItem(itemstack.getItem()));\n\t\t\twriteInt(itemstack.getCount());\n\t\t\twriteInt(itemstack.getItemDamage());\n\t\t\twriteNBTTagCompound(itemstack.getTagCompound());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeItemIdentifier(@Nullable ItemIdentifier item) {\n\t\tif (item == null) {\n\t\t\twriteInt(0);\n\t\t} else {\n\t\t\twriteInt(Item.getIdFromItem(item.item));\n\t\t\twriteInt(item.itemDamage);\n\t\t\twriteNBTTagCompound(item.tag);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeItemIdentifierStack(@Nullable ItemIdentifierStack stack) {\n\t\tif (stack == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteInt(stack.getStackSize());\n\t\t\twriteItemIdentifier(stack.getItem());\n\t\t}\n\t}\n\n\t@Override\n\tpublic <T> void writeCollection(@Nullable Collection<T> collection, IWriteListObject<T> handler) {\n\t\tif (collection == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteInt(collection.size());\n\t\t\tfor (T obj : collection) {\n\t\t\t\thandler.writeObject(this, obj);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic <T extends Enum<T>> void writeEnum(T obj) {\n\t\twriteInt(obj.ordinal());\n\t}\n\n\t@Override\n\tpublic void writeByteBuf(ByteBuf otherBuffer) {\n\t\twriteInt(otherBuffer.readableBytes());\n\t\tlocalBuffer.writeBytes(otherBuffer, otherBuffer.readableBytes());\n\t}\n\n\t@Override\n\tpublic void writeLongArray(@Nullable long[] arr) {\n\t\tif (arr == null) {\n\t\t\twriteInt(-1);\n\t\t} else {\n\t\t\twriteInt(arr.length);\n\t\t\tfor (long l : arr) {\n\t\t\t\twriteLong(l);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writeBytes(byte[] arr) {\n\t\tlocalBuffer.writeBytes(arr);\n\t}\n\n\t@Override\n\tpublic void writeChannelInformation(ChannelInformation channel) {\n\t\tthis.writeUTF(channel.getName());\n\t\tthis.writeUUID(channel.getChannelIdentifier());\n\t\tthis.writePlayerIdentifier(channel.getOwner());\n\t\tthis.writeEnum(channel.getRights());\n\t\tthis.writeUUID(channel.getResponsibleSecurityID());\n\t}\n\n\t@Override\n\tpublic void writeUUID(@Nullable UUID uuid) {\n\t\tthis.writeBoolean(uuid != null);\n\t\tif (uuid != null) {\n\t\t\tthis.writeLong(uuid.getMostSignificantBits());\n\t\t\tthis.writeLong(uuid.getLeastSignificantBits());\n\t\t}\n\t}\n\n\t@Override\n\tpublic void writePlayerIdentifier(PlayerIdentifier playerIdentifier) {\n\t\tthis.writeUTF(playerIdentifier.getUsername());\n\t\tthis.writeUUID(playerIdentifier.getId());\n\t}\n\n\t@Override\n\tpublic byte readByte() {\n\t\treturn localBuffer.readByte();\n\t}\n\n\t@Override\n\tpublic short readShort() {\n\t\treturn localBuffer.readShort();\n\t}\n\n\t@Override\n\tpublic int readInt() {\n\t\treturn localBuffer.readInt();\n\t}\n\n\t@Override\n\tpublic long readLong() {\n\t\treturn localBuffer.readLong();\n\t}\n\n\t@Override\n\tpublic float readFloat() {\n\t\treturn localBuffer.readFloat();\n\t}\n\n\t@Override\n\tpublic double readDouble() {\n\t\treturn localBuffer.readDouble();\n\t}\n\n\t@Override\n\tpublic boolean readBoolean() {\n\t\treturn localBuffer.readBoolean();\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic String readUTF() {\n\t\tbyte[] arr = readByteArray();\n\t\tif (arr == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn new String(arr, UTF_8);\n\t\t}\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic EnumFacing readFacing() {\n\t\tbyte b = localBuffer.readByte();\n\n\t\tif (b == Byte.MIN_VALUE) {\n\t\t\treturn null;\n\t\t} else if (b < 0 || b >= EnumFacing.VALUES.length) {\n\t\t\tthrow new IndexOutOfBoundsException(\"Invalid value for EnumFacing\");\n\t\t}\n\t\treturn EnumFacing.VALUES[b];\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic ResourceLocation readResourceLocation() {\n\t\tif (readBoolean()) {\n\t\t\treturn new ResourceLocation(Objects.requireNonNull(readUTF()));\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <T extends Enum<T>> EnumSet<T> readEnumSet(Class<T> clazz) {\n\t\tEnumSet<T> types = EnumSet.noneOf(clazz);\n\t\tbyte[] arr = readByteArray();\n\t\tif (arr != null) {\n\t\t\tT[] parts = clazz.getEnumConstants();\n\t\t\tfor (T part : parts) {\n\t\t\t\tif ((arr[part.ordinal() / 8] & (1 << (part.ordinal() % 8))) != 0) {\n\t\t\t\t\ttypes.add(part);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn types;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic BitSet readBitSet() {\n\t\tfinal long[] words = readLongArray();\n\t\tif (words == null) {\n\t\t\treturn new BitSet();\n\t\t} else {\n\t\t\treturn BitSet.valueOf(words);\n\t\t}\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic NBTTagCompound readNBTTagCompound() {\n\t\tboolean isEmpty = (readByte() == 0);\n\t\tif (isEmpty) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\treturn CompressedStreamTools.readCompressed(new ByteArrayInputStream(Objects.requireNonNull(readByteArray())));\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic boolean[] readBooleanArray() {\n\t\tfinal int bitCount = localBuffer.readInt();\n\t\tif (bitCount == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tbyte[] data = readByteArray();\n\t\tif (bitCount == 0) {\n\t\t\treturn new boolean[0];\n\t\t} else if (data == null) {\n\t\t\tthrow new NullPointerException(\"Boolean's byte array is null\");\n\t\t}\n\n\t\tBitSet bits = BitSet.valueOf(data);\n\n\t\tfinal boolean[] arr = new boolean[bitCount];\n\t\tIntStream.range(0, bitCount).forEach(i -> arr[i] = bits.get(i));\n\t\treturn arr;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic String[] readUTFArray() {\n\t\tfinal int length = localBuffer.readInt();\n\t\tif (length == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfinal String[] arr = new String[length];\n\t\tIntStream.range(0, length).forEach(i -> arr[i] = readUTF());\n\t\treturn arr;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic int[] readIntArray() {\n\t\tfinal int length = localBuffer.readInt();\n\t\tif (length == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfinal int[] arr = new int[length];\n\t\tIntStream.range(0, length).forEach(i -> arr[i] = localBuffer.readInt());\n\t\treturn arr;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic byte[] readBytes(int length) {\n\t\tbyte[] arr = new byte[length];\n\t\tlocalBuffer.readBytes(arr, 0, length);\n\t\treturn arr;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic ItemIdentifier readItemIdentifier() {\n\t\tfinal int itemId = readInt();\n\t\tif (itemId == 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tint damage = readInt();\n\t\tNBTTagCompound tag = readNBTTagCompound();\n\t\treturn ItemIdentifier.get(Item.getItemById(itemId), damage, tag);\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic ItemIdentifierStack readItemIdentifierStack() {\n\t\tint stacksize = readInt();\n\t\tif (stacksize == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tItemIdentifier item = readItemIdentifier();\n\t\tif (item == null) {\n\t\t\tLogisticsPipes.log.error(\"Read null ItemIdentifier in readItemIdentifierStack\");\n\t\t\treturn null;\n\t\t}\n\t\treturn new ItemIdentifierStack(item, stacksize);\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ItemStack readItemStack() {\n\t\tfinal int itemId = readInt();\n\t\tif (itemId == 0) {\n\t\t\treturn ItemStack.EMPTY;\n\t\t}\n\n\t\tint stackSize = readInt();\n\t\tint damage = readInt();\n\t\tItemStack stack = new ItemStack(Item.getItemById(itemId), stackSize, damage);\n\t\t// may be null, see code\n\t\tstack.setTagCompound(readNBTTagCompound());\n\t\treturn stack;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> ArrayList<T> readArrayList(IReadListObject<T> reader) {\n\t\tint size = readInt();\n\t\tif (size == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tArrayList<T> list = new ArrayList<>(size);\n\t\tfor (int i = 0; i < size; i++) {\n\t\t\tlist.add(reader.readObject(this));\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> LinkedList<T> readLinkedList(IReadListObject<T> reader) {\n\t\tint size = readInt();\n\t\tif (size == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tLinkedList<T> list = new LinkedList<>();\n\t\tfor (int i = 0; i < size; i++) {\n\t\t\tlist.add(reader.readObject(this));\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> Set<T> readSet(IReadListObject<T> handler) {\n\t\tint size = readInt();\n\t\tif (size == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tSet<T> set = new HashSet<>(size);\n\t\tfor (int i = 0; i < size; i++) {\n\t\t\tset.add(handler.readObject(this));\n\t\t}\n\t\treturn set;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T> NonNullList<T> readNonNullList(IReadListObject<T> reader, @Nonnull T fillItem) {\n\t\tint size = readInt();\n\t\tif (size == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tNonNullList<T> list = NonNullList.withSize(size, fillItem);\n\t\tfor (int i = 0; i < size; i++) {\n\t\t\tT obj = reader.readObject(this);\n\t\t\tif (obj != null) list.set(i, obj);\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic <T extends Enum<T>> T readEnum(Class<T> clazz) {\n\t\treturn clazz.getEnumConstants()[localBuffer.readInt()];\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ByteBuf readByteBuf() {\n\t\tbyte[] arr = readByteArray();\n\t\tif (arr == null) {\n\t\t\tthrow new NullPointerException(\"Buffer may not be null, but read null\");\n\t\t} else {\n\t\t\treturn wrappedBuffer(arr);\n\t\t}\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic long[] readLongArray() {\n\t\tfinal int length = localBuffer.readInt();\n\t\tif (length == -1) {\n\t\t\treturn null;\n\t\t}\n\n\t\tfinal long[] arr = new long[length];\n\t\tIntStream.range(0, length).forEach(i -> arr[i] = localBuffer.readLong());\n\t\treturn arr;\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic ChannelInformation readChannelInformation() {\n\t\treturn new ChannelInformation(this.readUTF(), this.readUUID(), this.readPlayerIdentifier(), this.readEnum(ChannelInformation.AccessRights.class), this.readUUID());\n\t}\n\n\t@Nullable\n\t@Override\n\tpublic UUID readUUID() {\n\t\tif (!this.readBoolean()) {\n\t\t\treturn null;\n\t\t}\n\t\treturn new UUID(this.readLong(), this.readLong());\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic PlayerIdentifier readPlayerIdentifier() {\n\t\treturn PlayerIdentifier.get(this.readUTF(), this.readUUID());\n\t}\n\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/util/LPDataInput.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util;\n\nimport java.util.ArrayList;\nimport java.util.BitSet;\nimport java.util.EnumSet;\nimport java.util.LinkedList;\nimport java.util.Set;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.NonNullList;\nimport net.minecraft.util.ResourceLocation;\n\nimport io.netty.buffer.ByteBuf;\n\nimport logisticspipes.network.IReadListObject;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface LPDataInput {\n\n\t@Nullable\n\tbyte[] readByteArray();\n\n\t/**\n\t * @see java.io.DataInput#readByte()\n\t */\n\tbyte readByte();\n\n\t/**\n\t * @see java.io.DataInput#readShort()\n\t */\n\tshort readShort();\n\n\t/**\n\t * @see java.io.DataInput#readInt()\n\t */\n\tint readInt();\n\n\t/**\n\t * @see java.io.DataInput#readLong()\n\t */\n\tlong readLong();\n\n\t/**\n\t * @see java.io.DataInput#readFloat()\n\t */\n\tfloat readFloat();\n\n\t/**\n\t * @see java.io.DataInput#readDouble()\n\t */\n\tdouble readDouble();\n\n\t/**\n\t * @see java.io.DataInput#readBoolean()\n\t */\n\tboolean readBoolean();\n\n\t/**\n\t * @see java.io.DataInput#readUTF()\n\t */\n\t@Nullable\n\tString readUTF();\n\n\t@Nullable\n\tEnumFacing readFacing();\n\n\t@Nullable\n\tResourceLocation readResourceLocation();\n\n\t@Nonnull\n\t<T extends Enum<T>> EnumSet<T> readEnumSet(Class<T> clazz);\n\n\t@Nonnull\n\tBitSet readBitSet();\n\n\t@Nullable\n\tNBTTagCompound readNBTTagCompound();\n\n\t@Nullable\n\tboolean[] readBooleanArray();\n\n\t@Nullable\n\tString[] readUTFArray();\n\n\t@Nullable\n\tint[] readIntArray();\n\n\t@Nonnull\n\tbyte[] readBytes(int length);\n\n\t@Nullable\n\tItemIdentifier readItemIdentifier();\n\n\t@Nullable\n\tItemIdentifierStack readItemIdentifierStack();\n\n\t@Nonnull\n\tItemStack readItemStack();\n\n\t@Nullable\n\t<T> ArrayList<T> readArrayList(IReadListObject<T> reader);\n\n\t@Nullable\n\t<T> LinkedList<T> readLinkedList(IReadListObject<T> reader);\n\n\t@Nullable\n\t<T> Set<T> readSet(IReadListObject<T> handler);\n\n\t@Nullable\n\t<T> NonNullList<T> readNonNullList(IReadListObject<T> reader, @Nonnull T fillItem);\n\n\t@Nullable\n\t<T extends Enum<T>> T readEnum(Class<T> clazz);\n\n\t@Nonnull\n\tByteBuf readByteBuf();\n\n\t@Nullable\n\tlong[] readLongArray();\n\n\t@Nonnull\n\tChannelInformation readChannelInformation();\n\n\t@Nullable\n\tUUID readUUID();\n\n\t@Nonnull\n\tPlayerIdentifier readPlayerIdentifier();\n\n\tdefault void readSerializable(LPSerializable serializable) {\n\t\tserializable.read(this);\n\t}\n\n\tinterface LPDataInputConsumer {\n\n\t\tvoid accept(LPDataInput dataInput);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/util/LPDataOutput.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util;\n\nimport java.util.BitSet;\nimport java.util.Collection;\nimport java.util.EnumSet;\nimport java.util.UUID;\nimport javax.annotation.Nonnull;\nimport javax.annotation.Nullable;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.EnumFacing;\nimport net.minecraft.util.ResourceLocation;\n\nimport io.netty.buffer.ByteBuf;\n\nimport logisticspipes.network.IWriteListObject;\nimport logisticspipes.routing.channels.ChannelInformation;\nimport logisticspipes.utils.PlayerIdentifier;\nimport logisticspipes.utils.item.ItemIdentifier;\nimport logisticspipes.utils.item.ItemIdentifierStack;\n\npublic interface LPDataOutput {\n\n\t/**\n\t * @see java.io.DataOutput#writeByte(int)\n\t */\n\tvoid writeByte(int b);\n\n\tvoid writeByte(byte b);\n\n\t/**\n\t * @see java.io.DataOutput#writeShort(int)\n\t */\n\tvoid writeShort(int s);\n\n\tvoid writeShort(short s);\n\n\t/**\n\t * @see java.io.DataOutput#writeInt(int)\n\t */\n\tvoid writeInt(int i);\n\n\t/**\n\t * @see java.io.DataOutput#writeLong(long)\n\t */\n\tvoid writeLong(long l);\n\n\t/**\n\t * @see java.io.DataOutput#writeFloat(float)\n\t */\n\tvoid writeFloat(float f);\n\n\t/**\n\t * @see java.io.DataOutput#writeDouble(double)\n\t */\n\tvoid writeDouble(double d);\n\n\t/**\n\t * @see java.io.DataOutput#writeBoolean(boolean)\n\t */\n\tvoid writeBoolean(boolean b);\n\n\t/**\n\t * Uses UTF-8 and not UTF-16.\n\t *\n\t * @see java.io.DataOutput#writeUTF(String)\n\t */\n\tvoid writeUTF(@Nullable String s);\n\n\tvoid writeByteArray(@Nullable byte[] arr);\n\n\tvoid writeByteBuf(ByteBuf buffer);\n\n\tvoid writeIntArray(@Nullable int[] arr);\n\n\tvoid writeLongArray(@Nullable long[] arr);\n\n\tvoid writeBooleanArray(@Nullable boolean[] arr);\n\n\tvoid writeUTFArray(@Nullable String[] arr);\n\n\tvoid writeFacing(@Nullable EnumFacing direction);\n\n\tvoid writeResourceLocation(@Nullable ResourceLocation resource);\n\n\t<T extends Enum<T>> void writeEnumSet(EnumSet<T> types, Class<T> clazz);\n\n\tvoid writeBitSet(@Nonnull BitSet bits);\n\n\tvoid writeNBTTagCompound(@Nullable NBTTagCompound tag);\n\n\tvoid writeItemStack(@Nonnull ItemStack itemstack);\n\n\tvoid writeItemIdentifier(@Nullable ItemIdentifier item);\n\n\tvoid writeItemIdentifierStack(@Nullable ItemIdentifierStack stack);\n\n\t<T> void writeCollection(@Nullable Collection<T> collection, IWriteListObject<T> handler);\n\n\tdefault <T extends LPFinalSerializable> void writeCollection(Collection<T> collection) {\n\t\twriteCollection(collection, LPDataOutput::writeSerializable);\n\t}\n\n\t<T extends Enum<T>> void writeEnum(T obj);\n\n\tvoid writeBytes(byte[] arr);\n\n\tvoid writeChannelInformation(ChannelInformation channel);\n\n\tvoid writeUUID(@Nullable UUID uuid);\n\n\tvoid writePlayerIdentifier(PlayerIdentifier playerIdentifier);\n\n\tdefault void writeSerializable(LPFinalSerializable finalSerializable) {\n\t\tfinalSerializable.write(this);\n\t}\n\n\tinterface LPDataOutputConsumer {\n\n\t\tvoid accept(LPDataOutput dataOutput);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/util/LPFinalSerializable.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util;\n\npublic interface LPFinalSerializable {\n\n\tvoid write(LPDataOutput output);\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/util/LPSerializable.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util;\n\npublic interface LPSerializable extends LPFinalSerializable {\n\n\tvoid read(LPDataInput input);\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/util/items/ItemStackLoader.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util.items;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.item.ItemStack;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.util.datafix.FixTypes;\n\nimport net.minecraftforge.fml.common.FMLCommonHandler;\n\npublic class ItemStackLoader {\n\n\t@Nonnull\n\tpublic static ItemStack loadAndFixItemStackFromNBT(NBTTagCompound nbt) {\n\t\tNBTTagCompound fixed = FMLCommonHandler.instance().getDataFixer().process(FixTypes.ITEM_INSTANCE, nbt);\n\t\treturn new ItemStack(fixed);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/world/CoordinateUtils.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.world;\n\nimport net.minecraft.util.EnumFacing;\n\npublic final class CoordinateUtils {\n\n\tprivate CoordinateUtils() {}\n\n\tpublic static DoubleCoordinates add(DoubleCoordinates coords, EnumFacing direction) {\n\t\tcoords.setXCoord(coords.getXCoord() + direction.getDirectionVec().getX());\n\t\tcoords.setYCoord(coords.getYCoord() + direction.getDirectionVec().getY());\n\t\tcoords.setZCoord(coords.getZCoord() + direction.getDirectionVec().getZ());\n\t\treturn coords;\n\t}\n\n\tpublic static DoubleCoordinates add(DoubleCoordinates coords, EnumFacing direction, double times) {\n\t\tcoords.setXCoord(coords.getXCoord() + direction.getDirectionVec().getX() * times);\n\t\tcoords.setYCoord(coords.getYCoord() + direction.getDirectionVec().getY() * times);\n\t\tcoords.setZCoord(coords.getZCoord() + direction.getDirectionVec().getZ() * times);\n\t\treturn coords;\n\t}\n\n\tpublic static DoubleCoordinates sum(DoubleCoordinates coords, EnumFacing direction) {\n\t\tDoubleCoordinates ret = new DoubleCoordinates(coords);\n\t\treturn CoordinateUtils.add(ret, direction);\n\t}\n\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/world/DoubleCoordinates.java",
    "content": "/*\n * Copyright (c) 2016  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2016  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.world;\n\nimport javax.annotation.Nonnull;\n\nimport net.minecraft.block.state.IBlockState;\nimport net.minecraft.entity.Entity;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\nimport net.minecraft.world.IBlockAccess;\nimport net.minecraft.world.World;\n\nimport lombok.Data;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\nimport logisticspipes.utils.IPositionRotateble;\nimport network.rs485.logisticspipes.util.LPDataInput;\nimport network.rs485.logisticspipes.util.LPDataOutput;\nimport network.rs485.logisticspipes.util.LPSerializable;\n\n@Data\npublic class DoubleCoordinates implements IPositionRotateble, ICoordinates, LPSerializable {\n\n\tprivate double xCoord;\n\tprivate double yCoord;\n\tprivate double zCoord;\n\n\tpublic DoubleCoordinates() {\n\t\tsetXCoord(0.0);\n\t\tsetYCoord(0.0);\n\t\tsetZCoord(0.0);\n\t}\n\n\tpublic DoubleCoordinates(double xCoord, double yCoord, double zCoord) {\n\t\tsetXCoord(xCoord);\n\t\tsetYCoord(yCoord);\n\t\tsetZCoord(zCoord);\n\t}\n\n\tpublic DoubleCoordinates(LPDataInput input) {\n\t\tread(input);\n\t}\n\n\tpublic DoubleCoordinates(ICoordinates coords) {\n\t\tthis(coords.getXDouble(), coords.getYDouble(), coords.getZDouble());\n\t}\n\n\tpublic DoubleCoordinates(TileEntity tile) {\n\t\tthis(tile.getPos());\n\t}\n\n\tpublic DoubleCoordinates(CoreUnroutedPipe pipe) {\n\t\tthis(pipe.getX(), pipe.getY(), pipe.getZ());\n\t}\n\n\tpublic DoubleCoordinates(IPipeInformationProvider pipe) {\n\t\tthis(pipe.getX(), pipe.getY(), pipe.getZ());\n\t}\n\n\tpublic DoubleCoordinates(CoordinatesPacket packet) {\n\t\tthis(packet.getPosX(), packet.getPosY(), packet.getPosZ());\n\t}\n\n\tpublic DoubleCoordinates(Entity entity) {\n\t\tthis(entity.posX, entity.posY, entity.posZ);\n\t}\n\n\tpublic DoubleCoordinates(BlockPos pos) {\n\t\tthis(pos.getX(), pos.getY(), pos.getZ());\n\t}\n\n\tpublic static DoubleCoordinates readFromNBT(String prefix, NBTTagCompound nbt) {\n\t\tif (nbt.hasKey(prefix + \"xPos\") && nbt.hasKey(prefix + \"yPos\") && nbt.hasKey(prefix + \"zPos\")) {\n\t\t\treturn new DoubleCoordinates(nbt.getDouble(prefix + \"xPos\"), nbt.getDouble(prefix + \"yPos\"), nbt.getDouble(prefix + \"zPos\"));\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic double getXDouble() {\n\t\treturn getXCoord();\n\t}\n\n\t@Override\n\tpublic double getYDouble() {\n\t\treturn getYCoord();\n\t}\n\n\t@Override\n\tpublic double getZDouble() {\n\t\treturn getZCoord();\n\t}\n\n\t@Override\n\tpublic int getXInt() {\n\t\treturn (int) getXCoord();\n\t}\n\n\t@Override\n\tpublic int getYInt() {\n\t\treturn (int) getYCoord();\n\t}\n\n\t@Override\n\tpublic int getZInt() {\n\t\treturn (int) getZCoord();\n\t}\n\n\tpublic BlockPos getBlockPos() {\n\t\treturn new BlockPos(getXCoord(), getYCoord(), getZCoord());\n\t}\n\n\tpublic TileEntity getTileEntity(IBlockAccess world) {\n\t\treturn world.getTileEntity(getBlockPos());\n\t}\n\n\t@Override\n\tpublic String toString() {\n\t\treturn \"(\" + getXCoord() + \", \" + getYCoord() + \", \" + getZCoord() + \")\";\n\t}\n\n\tpublic String toIntBasedString() {\n\t\treturn \"(\" + getXCoord() + \", \" + getYCoord() + \", \" + getZCoord() + \")\";\n\t}\n\n\t@Nonnull\n\tpublic IBlockState getBlockState(IBlockAccess world) {\n\t\treturn world.getBlockState(getBlockPos());\n\t}\n\n\tpublic boolean blockExists(World world) {\n\t\treturn !world.isAirBlock(getBlockPos());\n\t}\n\n\tpublic double distanceTo(DoubleCoordinates targetPos) {\n\t\treturn Math.sqrt(Math.pow(targetPos.getXCoord() - getXCoord(), 2) + Math.pow(targetPos.getYCoord() - getYCoord(), 2) + Math\n\t\t\t\t.pow(targetPos.getZCoord() - getZCoord(), 2));\n\t}\n\n\tpublic DoubleCoordinates center() {\n\t\tDoubleCoordinates coords = new DoubleCoordinates();\n\t\tcoords.setXCoord(getXInt() + 0.5);\n\t\tcoords.setYCoord(getYInt() + 0.5);\n\t\tcoords.setYCoord(getZInt() + 0.5);\n\t\treturn this;\n\t}\n\n\tpublic void writeToNBT(String prefix, NBTTagCompound nbt) {\n\t\tnbt.setDouble(prefix + \"xPos\", xCoord);\n\t\tnbt.setDouble(prefix + \"yPos\", yCoord);\n\t\tnbt.setDouble(prefix + \"zPos\", zCoord);\n\t}\n\n\tpublic DoubleCoordinates add(DoubleCoordinates toAdd) {\n\t\tsetXCoord(getXCoord() + toAdd.getXCoord());\n\t\tsetYCoord(getYCoord() + toAdd.getYCoord());\n\t\tsetZCoord(getZCoord() + toAdd.getZCoord());\n\t\treturn this;\n\t}\n\n\tpublic void setBlockToAir(World world) {\n\t\tworld.setBlockToAir(getBlockPos());\n\t}\n\n\t@Override\n\tpublic void rotateLeft() {\n\t\tdouble tmp = getZCoord();\n\t\tsetZCoord(-getXCoord());\n\t\tsetXCoord(tmp);\n\t}\n\n\t@Override\n\tpublic void rotateRight() {\n\t\tdouble tmp = getXCoord();\n\t\tsetXCoord(-getZCoord());\n\t\tsetZCoord(tmp);\n\t}\n\n\t@Override\n\tpublic void mirrorX() {\n\t\tsetXCoord(-getXCoord());\n\t}\n\n\t@Override\n\tpublic void mirrorZ() {\n\t\tsetZCoord(-getZCoord());\n\t}\n\n\tpublic double getLength() {\n\t\treturn Math.sqrt(getXDouble() * getXDouble() + getYDouble() * getYDouble() + getZDouble() * getZDouble());\n\t}\n\n\t@Override\n\tpublic void read(LPDataInput input) {\n\t\txCoord = input.readDouble();\n\t\tyCoord = input.readDouble();\n\t\tzCoord = input.readDouble();\n\t}\n\n\t@Override\n\tpublic void write(LPDataOutput output) {\n\t\toutput.writeDouble(xCoord);\n\t\toutput.writeDouble(yCoord);\n\t\toutput.writeDouble(zCoord);\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/world/DoubleCoordinatesType.java",
    "content": "package network.rs485.logisticspipes.world;\n\nimport net.minecraft.entity.Entity;\nimport net.minecraft.tileentity.TileEntity;\nimport net.minecraft.util.math.BlockPos;\n\nimport lombok.Getter;\n\nimport logisticspipes.network.abstractpackets.CoordinatesPacket;\nimport logisticspipes.pipes.basic.CoreUnroutedPipe;\nimport logisticspipes.routing.pathfinder.IPipeInformationProvider;\n\npublic class DoubleCoordinatesType<T> extends DoubleCoordinates {\n\n\t@Getter\n\tprivate T type;\n\n\tpublic DoubleCoordinatesType(double xCoord, double yCoord, double zCoord, T type) {\n\t\tsuper(xCoord, yCoord, zCoord);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(ICoordinates coords, T type) {\n\t\tsuper(coords);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(TileEntity tile, T type) {\n\t\tsuper(tile);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(CoreUnroutedPipe pipe, T type) {\n\t\tsuper(pipe);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(IPipeInformationProvider pipe, T type) {\n\t\tsuper(pipe);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(CoordinatesPacket packet, T type) {\n\t\tsuper(packet);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(Entity entity, T type) {\n\t\tsuper(entity);\n\t\tthis.type = type;\n\t}\n\n\tpublic DoubleCoordinatesType(BlockPos pos, T type) {\n\t\tsuper(pos);\n\t\tthis.type = type;\n\t}\n\n\t@Deprecated // Only called by reflection\n\tpublic DoubleCoordinatesType(double xCoord, double yCoord, double zCoord) {\n\t\tthis(xCoord, yCoord, zCoord, null);\n\t}\n\n\tpublic DoubleCoordinatesType<T> add(DoubleCoordinates toAdd) {\n\t\tsetXCoord(getXCoord() + toAdd.getXCoord());\n\t\tsetYCoord(getYCoord() + toAdd.getYCoord());\n\t\tsetZCoord(getZCoord() + toAdd.getZCoord());\n\t\treturn this;\n\t}\n}\n"
  },
  {
    "path": "src/main/java/network/rs485/logisticspipes/world/ICoordinates.java",
    "content": "/*\n * Copyright (c) 2015  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the MIT license:\n *\n * Copyright (c) 2015  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular MIT license in your project, replace this copyright notice (this line and any lines below and NOT the copyright line above) with the lines from the original MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this file and associated documentation files (the \"Source Code\"), to deal in the Source Code without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Source Code, and to permit persons to whom the Source Code is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Source Code, which also can be distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.world;\n\npublic interface ICoordinates {\n\n\tdouble getXDouble();\n\n\tdouble getYDouble();\n\n\tdouble getZDouble();\n\n\tint getXInt();\n\n\tint getYInt();\n\n\tint getZInt();\n}\n"
  },
  {
    "path": "src/main/kotlin/logisticspipes/pipes/PipeFluidBasic.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage logisticspipes.pipes\n\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.network.GuiIDs\nimport logisticspipes.textures.Textures\nimport logisticspipes.utils.FluidSinkReply.FixedFluidPriority\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.Item\nimport network.rs485.logisticspipes.FluidSinkPipe\n\nclass PipeFluidBasic(item: Item) : FluidSinkPipe(item, \"Fluids to sink\", 1) {\n\n    override val priority: FixedFluidPriority = FixedFluidPriority.FLUID_SINK\n\n    override fun getCenterTexture(): Textures.TextureType = Textures.LOGISTICSPIPE_LIQUID_BASIC\n\n    override fun onWrenchClicked(entityplayer: EntityPlayer) {\n        entityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Fluid_Basic_ID, world, x, y, z)\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/logisticspipes/pipes/PipeFluidTerminus.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage logisticspipes.pipes\n\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.network.GuiIDs\nimport logisticspipes.network.packets.pipe.PipePropertiesUpdate\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.textures.Textures\nimport logisticspipes.utils.FluidSinkReply.FixedFluidPriority\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.Item\nimport network.rs485.logisticspipes.FluidSinkPipe\n\nclass PipeFluidTerminus(item: Item) : FluidSinkPipe(item, \"Fluids to terminate\", 9) {\n\n    override val priority: FixedFluidPriority = FixedFluidPriority.TERMINUS\n\n    override fun getCenterTexture(): Textures.TextureType = Textures.LOGISTICSPIPE_LIQUID_TERMINUS\n\n    override fun onWrenchClicked(entityplayer: EntityPlayer) {\n        // only run on the server\n        MainProxy.sendPacketToPlayer(PipePropertiesUpdate.fromPropertyHolder(this).setBlockPos(pos), entityplayer)\n        entityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Fluid_Terminus_ID, world, x, y, z)\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/logisticspipes/pipes/PipeFluidUtil.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage logisticspipes.pipes\n\nimport logisticspipes.interfaces.ISpecialTankAccessHandler\nimport logisticspipes.interfaces.ITankUtil\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe\nimport logisticspipes.proxy.SimpleServiceLocator\nimport logisticspipes.utils.FluidIdentifier\nimport logisticspipes.utils.FluidIdentifierStack\nimport logisticspipes.utils.SpecialTankUtil\nimport logisticspipes.utils.TankUtil\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport logisticspipes.utils.tuples.Pair\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraftforge.fluids.capability.CapabilityFluidHandler\nimport net.minecraftforge.fluids.capability.IFluidTankProperties\nimport network.rs485.logisticspipes.connection.getTankUtil\nimport kotlin.streams.toList\n\nobject PipeFluidUtil {\n\n    fun getTankUtilForTE(tile: TileEntity?, dirOnEntity: EnumFacing?): ITankUtil? {\n        if (SimpleServiceLocator.specialTankHandler.hasHandlerFor(tile)) {\n            val handler = SimpleServiceLocator.specialTankHandler.getTankHandlerFor(tile)\n            if (handler is ISpecialTankAccessHandler) {\n                if (tile!!.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dirOnEntity)) {\n                    val fluidHandler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dirOnEntity)\n                    if (fluidHandler != null) {\n                        return SpecialTankUtil(fluidHandler, tile, handler)\n                    }\n                }\n            }\n        }\n        if (tile != null && tile.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dirOnEntity)) {\n            val fluidHandler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dirOnEntity)\n            if (fluidHandler != null) {\n                return TankUtil(fluidHandler)\n            }\n        }\n        return null\n    }\n\n    fun FluidRoutedPipe.getAdjacentTanks(listNearbyPipes: Boolean) =\n        availableAdjacent.fluidTanks()\n            .filter { isConnectableTank(it.tileEntity, it.direction, listNearbyPipes) }\n            .flatMap { adjacent ->\n                adjacent.getTankUtil()?.let { listOf(Pair(adjacent, it)) } ?: emptyList()\n            }\n\n\n    fun FluidRoutedPipe.getAllTankTiles(): List<TileEntity> = getAdjacentTanks(false)\n        .flatMap { pair -> SimpleServiceLocator.specialTankHandler.getBaseTileFor(pair.component1().tileEntity) }\n\n    fun PipeFluidSatellite.fluidsToItemList(): List<ItemIdentifierStack> {\n        val fluidIdentStacks = getAdjacentTanks(false)\n            .flatMap { (_, util) -> util.tanks().toList() }\n            .mapNotNull { tank: IFluidTankProperties -> FluidIdentifierStack.getFromStack(tank.contents) }\n        val distinctionSet = HashSet<FluidIdentifier>()\n        val outputList = ArrayList<ItemIdentifierStack>()\n        for (identStack in fluidIdentStacks) {\n            if (distinctionSet.add(identStack.fluid)) {\n                outputList.add(identStack.fluid.itemIdentifier.makeStack(identStack.amount))\n            } else {\n                outputList.find { it.item == identStack.fluid.itemIdentifier }!!.stackSize += identStack.amount\n            }\n        }\n        return outputList\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/logisticspipes/routing/AsyncRouting.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage logisticspipes.routing\n\nobject AsyncRouting {\n    fun getDistance(sourceRouter: ServerRouter, destinationRouter: IRouter): List<ExitRoute>? {\n        return if (sourceRouter._routeTable.size <= destinationRouter.simpleID) {\n            null\n        } else {\n            sourceRouter._routeTable[destinationRouter.simpleID]\n        }\n    }\n\n    fun ServerRouter.updateServerRouterLsa() {\n        if (connectionNeedsChecking != 0 && checkAdjacentUpdate()) {\n            updateLsa()\n        }\n    }\n\n    fun ServerRouter.needsRoutingTableUpdate(): Boolean = _LSAVersion > ServerRouter._lastLSAVersion[simpleID]\n\n    fun updateRoutingTable(serverRouter: ServerRouter) {\n        if (serverRouter._LSAVersion > ServerRouter._lastLSAVersion[serverRouter.simpleID]) {\n            serverRouter.CreateRouteTable(serverRouter._LSAVersion)\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/debug/OpenGLDebugger.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.debug\n\nimport com.google.common.reflect.Reflection\nimport logisticspipes.LogisticsPipes\nimport org.lwjgl.opengl.GL11\nimport org.lwjgl.opengl.GL31\nimport org.lwjgl.opengl.GL32\nimport org.lwjgl.util.glu.GLU\nimport java.awt.*\nimport java.awt.event.KeyEvent\nimport java.awt.event.WindowAdapter\nimport java.awt.event.WindowEvent\nimport java.util.*\nimport java.util.concurrent.locks.ReentrantLock\nimport javax.swing.*\nimport javax.swing.table.DefaultTableCellRenderer\nimport javax.swing.table.DefaultTableModel\nimport kotlin.concurrent.withLock\n\nprivate class ChangeTrackingSortedMap<K : Comparable<K>, V : Any> {\n    private val orderedKeys = ArrayList<K>()\n    private val values = ArrayList<V>()\n    private val sessionUpdates = ArrayList<Int>()\n    private val sessionInsertions = ArrayList<Int>()\n    private var sessionStarted: Boolean = false\n\n    val size: Int\n        get() = orderedKeys.size\n\n    fun startSession() {\n        sessionUpdates.clear()\n        sessionInsertions.clear()\n        sessionStarted = true\n    }\n\n    fun put(key: K, value: V) {\n        if (!sessionStarted) {\n            throw IllegalStateException(\"Session not started. Only modify map after session start.\")\n        }\n        val keyIndex = binarySearch(key)\n        if (keyIndex < 0) {\n            val addIndex = -(keyIndex + 1)\n            orderedKeys.add(addIndex, key)\n            values.add(addIndex, value)\n            sessionInsertions.add(addIndex)\n        } else if (values[keyIndex] != value) {\n            orderedKeys[keyIndex] = key\n            values[keyIndex] = value\n            sessionUpdates.add(keyIndex)\n        }\n    }\n\n    fun binarySearch(key: K): Int = Collections.binarySearch(orderedKeys, key)\n\n    fun stopSession() {\n        sessionStarted = false\n    }\n\n    fun getKeyOrNull(index: Int): K? = orderedKeys.getOrNull(index)\n    fun getValueOrNull(index: Int): V? = values.getOrNull(index)\n    fun wasUpdated(index: Int) = sessionUpdates.contains(index)\n    fun wasAdded(index: Int) = sessionInsertions.contains(index)\n}\n\nprivate enum class GLType(val niceName: String, val getterFunction: (Int) -> Any?) {\n    BOOLEAN(\"boolean\", GL11::glGetBoolean),\n    FLOAT(\"float\", GL11::glGetFloat),\n    DOUBLE(\"double\", GL11::glGetDouble),\n    INTEGER(\"int\", GL11::glGetInteger),\n    INTEGER64(\"long\", GL32::glGetInteger64);\n}\n\nprivate data class GLVariable(val pname: Int, val type: GLType) : Comparable<GLVariable> {\n    override fun compareTo(other: GLVariable): Int =\n        pname.compareTo(other.pname).takeUnless { it == 0 } ?: type.compareTo(other.type)\n\n    fun getName(nicePName: String?): String = (nicePName ?: pname.toString()) + \" [${type.niceName}]\"\n}\ninterface IOpenGLDebugger {\n    var printOnCycle: Int\n    fun start()\n    fun stop()\n    fun cycle()\n}\n\nclass OpenGLDebugger(override var printOnCycle: Int) : IOpenGLDebugger {\n    private val probeGUIThread: Thread\n    private var cycleCount = 0\n    private var started = false\n    private val glStuff = ChangeTrackingSortedMap<GLVariable, Any>()\n    private val glVariablesToCheck = ArrayList<GLVariable>()\n    private val debuggerLock = ReentrantLock()\n    private val glVariablesCondition = debuggerLock.newCondition()\n    private var glVariablesUpdated = false\n\n    private inner class SpecialTableModel : DefaultTableModel() {\n        override fun isCellEditable(row: Int, column: Int): Boolean {\n            return false\n        }\n\n        override fun getColumnName(column: Int): String {\n            return when (column) {\n                0 -> \"Key\"\n                1 -> \"Value\"\n                else -> \"\"\n            }\n        }\n\n        override fun getRowCount(): Int {\n            return glStuff.size\n        }\n\n        override fun getColumnCount(): Int {\n            return 2\n        }\n\n        override fun getValueAt(rowIndex: Int, columnIndex: Int): Any {\n            return glStuff.getKeyOrNull(rowIndex)?.let { glVariable ->\n                when (columnIndex) {\n                    0 -> glVariable.getName(niceToHave[glVariable.pname])\n                    1 -> glStuff.getValueOrNull(rowIndex) ?: \"<NULL>\"\n                    else -> \"\"\n                }\n            } ?: \"<NOT FOUND>\"\n        }\n    }\n\n    private inner class SpecialTableCellRenderer : DefaultTableCellRenderer() {\n        override fun getTableCellRendererComponent(\n            table: JTable?,\n            value: Any,\n            isSelected: Boolean,\n            hasFocus: Boolean,\n            row: Int,\n            column: Int\n        ): Component {\n            if (table == null) {\n                return this\n            }\n            background = null\n            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column)\n            if (glStuff.wasUpdated(row)) {\n                background = Color.YELLOW\n            } else if (glStuff.wasAdded(row)) {\n                background = Color.GREEN\n            }\n            return this\n        }\n    }\n\n    private inner class ProbeGUI : JDialog(), Runnable {\n        private val mainPanel: JPanel\n        private val variableMonitorTable: JTable\n        private val closeButton: JButton\n\n        init {\n            for (info in UIManager.getInstalledLookAndFeels()) {\n                if (\"Windows\" == info.name) {\n                    try {\n                        UIManager.setLookAndFeel(info.className)\n                    } catch (e: ReflectiveOperationException) {\n                        e.printStackTrace()\n                    } catch (e: UnsupportedLookAndFeelException) {\n                        e.printStackTrace()\n                    }\n                    break\n                }\n            }\n            mainPanel = JPanel()\n            closeButton = JButton().apply {\n                text = \"Close\"\n            }\n            variableMonitorTable =\n                JTable().apply {\n                    isEnabled = false\n                    model = SpecialTableModel()\n                    columnModel.getColumn(0).cellRenderer = SpecialTableCellRenderer()\n                }\n            setupUI()\n            type = Type.UTILITY\n            contentPane = mainPanel\n            getRootPane().defaultButton = closeButton\n            defaultCloseOperation = DO_NOTHING_ON_CLOSE\n            addWindowListener(object : WindowAdapter() {\n                override fun windowClosing(e: WindowEvent) {\n                    stop()\n                }\n            })\n            closeButton.addActionListener { stop() }\n            mainPanel.registerKeyboardAction(\n                { stop() },\n                KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),\n                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT\n            )\n        }\n\n        override fun run() {\n            glVariablesToCheck.clear()\n            glVariablesToCheck.addAll(\n                niceToHave.keys.flatMap { key ->\n                    GLType.values().map { glType -> GLVariable(key, glType) }\n                }\n            )\n            pack()\n            isVisible = true\n            while (started) {\n                debuggerLock.withLock {\n                    try {\n                        while (!glVariablesUpdated) {\n                            glVariablesCondition.await()\n                        }\n                        glVariablesUpdated = false\n                        updateVariables()\n                    } catch (e: InterruptedException) {\n                        e.printStackTrace()\n                    }\n                }\n            }\n        }\n\n        private fun updateVariables() {\n            val dtm = variableMonitorTable.model as DefaultTableModel\n            dtm.fireTableDataChanged()\n        }\n\n        private fun setupUI() = mainPanel.apply {\n            layout = GridBagLayout()\n            border = BorderFactory.createTitledBorder(\n                BorderFactory.createEmptyBorder(5, 5, 5, 5),\n                \"null\",\n            )\n\n            add(\n                closeButton,\n                GridBagConstraints().apply {\n                    gridx = 2\n                    gridy = 1\n                    fill = GridBagConstraints.HORIZONTAL\n                    insets = Insets(0, 5, 0, 0)\n                },\n            )\n\n            add(\n                JTextField().apply {\n                    text = \"Search…\"\n                    // TODO: add functionality\n                },\n                GridBagConstraints().apply {\n                    gridx = 0\n                    gridy = 1\n                    weightx = 1.0\n                    anchor = GridBagConstraints.WEST\n                    fill = GridBagConstraints.HORIZONTAL\n                },\n            )\n\n            add(\n                JScrollPane().apply {\n                    horizontalScrollBarPolicy = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER\n                    setViewportView(variableMonitorTable)\n                },\n                GridBagConstraints().apply {\n                    gridx = 0\n                    gridy = 0\n                    gridwidth = 3\n                    weightx = 1.0\n                    weighty = 1.0\n                    fill = GridBagConstraints.BOTH\n                    insets = Insets(0, 0, 5, 0)\n                },\n            )\n        }\n    }\n\n    init {\n        require(printOnCycle >= 1) { \"Print per cycle must be at least 1\" }\n        probeGUIThread = Thread(\n            /* target = */ {\n                synchronized(niceToHave) {\n                    if (niceToHave.isEmpty()) {\n                        updateNiceToHave()\n                    }\n                }\n                ProbeGUI().run()\n            },\n            /* name = */ \"LogisticsPipes GLDebug Probe #$probeID\",\n        )\n        probeID++\n    }\n\n    override fun start() {\n        if (!started) {\n            started = true\n            cycleCount = 0\n            probeGUIThread.start()\n        }\n    }\n\n    override fun stop() {\n        if (started) {\n            debuggerLock.withLock {\n                started = false\n                glVariablesUpdated = true\n                glVariablesCondition.signal()\n            }\n        }\n    }\n\n    override fun cycle() {\n        if (!started) {\n            start()\n        }\n        ++cycleCount\n        if (cycleCount % printOnCycle == 0) {\n            saveOpenGLStuff()\n            cycleCount = 0\n        }\n    }\n\n    private fun saveOpenGLStuff() {\n        debuggerLock.withLock {\n            glStuff.startSession()\n            val toRemove = glVariablesToCheck.filter { variable ->\n                LogisticsPipes.log.warn(\"Getting ${variable.getName(niceToHave[variable.pname])}\")\n                val value = variable.type.getterFunction(variable.pname)\n                val glError = GL11.glGetError()\n                val isInvalid = glError == GL11.GL_INVALID_ENUM\n                if (glError != GL11.GL_NO_ERROR) {\n                    LogisticsPipes.log.warn(\"  got error ${GLU.gluErrorString(glError)}\")\n                }\n                value?.takeUnless { isInvalid }?.also {\n                    glStuff.put(variable, it)\n                }\n                return@filter isInvalid\n            }.toSet()\n            glVariablesToCheck.removeAll(toRemove)\n            glStuff.stopSession()\n            glVariablesUpdated = true\n            glVariablesCondition.signal()\n        }\n    }\n\n    companion object {\n        private val niceToHave: HashMap<Int, String> = HashMap()\n        private var probeID = 0\n\n        private fun updateNiceToHave() {\n            niceToHave.clear()\n            var crawlerVersion = 11\n            var almostEnd = false\n            var end = false\n            while (!end) {\n                val packageGL = String.format(\"%s%d\", \"GL\", crawlerVersion)\n                val nextGL = String.format(\"%s.%s\", \"org.lwjgl.opengl\", packageGL)\n                try {\n                    crawlerVersion++\n                    val glClass = GL11::class.java.classLoader.loadClass(nextGL)\n                    @Suppress(\"UnstableApiUsage\")\n                    Reflection.initialize(glClass)\n                    almostEnd = false\n                    for (f in glClass.declaredFields) {\n                        try {\n                            if (f.type != Int::class.javaPrimitiveType) {\n                                continue\n                            }\n                            val id = f.getInt(null)\n                            if (id == GL31.GL_INVALID_INDEX) {\n                                continue\n                            }\n                            val nice = f.name\n                            if (nice.endsWith(\"BIT\")) {\n                                continue\n                            }\n\n                            // All the things that are being replaced are not that bad\n                            if (niceToHave.containsKey(id) && niceToHave[id] != nice) {\n                                System.out.printf(\n                                    \"NiceToHave: ID %d exists. Replacing %s with %s!!%n\",\n                                    id,\n                                    niceToHave.remove(id),\n                                    nice\n                                )\n                            }\n                            niceToHave[id] = String.format(\"%s.%s\", packageGL, nice)\n                        } catch (e: IllegalArgumentException) {\n                            System.out.printf(\"NiceToHave: Illegal Argument!%nNiceToHave: %s%n\", e)\n                            e.printStackTrace()\n                        } catch (e: IllegalAccessException) {\n                            System.out.printf(\"NiceToHave: Illegal Access!%nNiceToHave: %s%n\", e)\n                            e.printStackTrace()\n                        }\n                    }\n                } catch (e: ClassNotFoundException) {\n                    if (almostEnd) {\n                        end = true\n                    } else {\n                        almostEnd = true\n                        crawlerVersion = (crawlerVersion / 10 + 1) * 10\n                    }\n                }\n            }\n        }\n    }\n}\n\n@Suppress(\"unused\")\nobject GlobalOpenGLDebugger : IOpenGLDebugger by OpenGLDebugger(60)\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/debug/PerformanceMeter.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.debug\n\nimport java.time.Duration\n\nclass PerformanceMeter(val label: String, private val meanCalcCallCount: Int, private val printToConsole: Boolean) {\n    private val meanCalcGroup: LongArray = LongArray(meanCalcCallCount)\n    private var currentGroupIndex: Int = 0\n\n    val sum: Duration\n        get() {\n            val durationSum = meanCalcGroup.sum()\n            return if (durationSum == 0L) Duration.ZERO else Duration.ofNanos(durationSum)\n        }\n\n    val calculatedMean: Duration\n        get() = sum.dividedBy(meanCalcCallCount.toLong())\n\n    private fun increaseGroupIndex() {\n        currentGroupIndex++\n        if (currentGroupIndex >= meanCalcCallCount) {\n            currentGroupIndex = 0\n\n            if (printToConsole) {\n                println(\"[PerformanceMeter.$label] Sum: $sum of $meanCalcCallCount measures - Mean time: $calculatedMean\")\n            }\n        }\n    }\n\n    fun newPerfValue(nanoDuration: Long) {\n        meanCalcGroup[currentGroupIndex] = nanoDuration\n        increaseGroupIndex()\n    }\n\n    fun newPerfValue(duration: Duration) {\n        newPerfValue(duration.toNanos())\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/grow/ChunkedChannel.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.grow\n\nimport kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.channels.trySendBlocking\nimport java.util.function.Supplier\n\nabstract class ChunkedChannel<T, O>(val channel: Channel<T>) : Supplier<Boolean> {\n\n    /**\n     * Returns a session object for this run.\n     */\n    abstract fun newSession(): O\n\n    /**\n     * Returns true, if there is more to do. False otherwise.\n     */\n    abstract fun hasWork(session: O): Boolean\n\n    /**\n     * Returns a [List] of type T based on the current session.\n     */\n    abstract fun nextChunk(session: O): List<T>\n\n    /**\n     * @return true, if there is more work to do and this should be re-called (again).\n     */\n    override fun get(): Boolean {\n        try {\n            val session = newSession()\n            val channelResults = nextChunk(session).map(channel::trySendBlocking)\n            channelResults.find { it.isFailure && !it.isClosed }?.getOrThrow()\n            if (channelResults.any { it.isClosed }) return false\n            if (hasWork(session)) return true\n            channel.close()\n        } catch (e: Exception) {\n            channel.close(e)\n        }\n        return false\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/grow/Coroutines.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.grow\n\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.launch\nimport net.minecraftforge.fml.common.FMLCommonHandler\n\nobject Coroutines {\n    val io = Dispatchers.IO\n    val ioScope\n        get() = CoroutineScope(io)\n    val default = Dispatchers.Default\n    val asynchronousScope\n        get() = CoroutineScope(default)\n    val server = ServerTickDispatcher\n    val serverScope\n        get() = CoroutineScope(server)\n\n    fun scheduleServerTask(inTicks: Int, task: Runnable) {\n        val runTick = FMLCommonHandler.instance().minecraftServerInstance.tickCounter + inTicks\n\n        fun waitForTick() {\n            if (FMLCommonHandler.instance().minecraftServerInstance.tickCounter >= runTick) {\n                task.run()\n            } else {\n                server.scheduleNextTick(::waitForTick)\n            }\n        }\n\n        serverScope.launch {\n            waitForTick()\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/grow/ServerTickDispatcher.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.grow\n\nimport kotlinx.coroutines.*\nimport logisticspipes.LogisticsPipes\nimport java.util.concurrent.ConcurrentLinkedQueue\nimport kotlin.coroutines.CoroutineContext\n\nobject ServerTickDispatcher : CoroutineDispatcher() {\n    private val coroutineQueue = ConcurrentLinkedQueue<Runnable>()\n    private val toSchedule = mutableListOf<Runnable>()\n\n    fun serverStart() {\n        val startupJob = Coroutines.serverScope.launch {\n            LogisticsPipes.log.info(\"Hello from the server tick\")\n        }\n        Coroutines.asynchronousScope.async {\n            LogisticsPipes.log.info(\"Waiting for server tick\")\n            startupJob.join()\n            LogisticsPipes.log.info(\"Server tick complete! Hello from the async scope\")\n        }.invokeOnCompletion { throwable ->\n            throwable?.stackTraceToString()?.also { stacktrace ->\n                LogisticsPipes.log.fatal(\"Error when greeting server tick scope:\\n$stacktrace\")\n            }\n        }\n    }\n\n    fun cleanup() =\n        cancelChildren(CancellationException(\"cleanup was called on ServerTickContext\"))\n\n    fun tick() {\n        val start = System.nanoTime()\n        // failsafe to exit after 1 second\n        while (coroutineQueue.isNotEmpty() && (System.nanoTime() - start) < 1_000_000_000) {\n            coroutineQueue.poll().run()\n        }\n        if (System.nanoTime() - start >= 1_000_000_000) {\n            println(\"Logistics Pipes ServerTickContext hang for a second. Dumping coroutines:\")\n            coroutineQueue.forEach(::println)\n        }\n        synchronized(toSchedule) {\n            coroutineQueue.addAll(toSchedule)\n            toSchedule.clear()\n        }\n    }\n\n    override fun dispatch(context: CoroutineContext, block: Runnable) {\n        coroutineQueue.add(block)\n    }\n\n    fun scheduleNextTick(block: Runnable) {\n        synchronized(toSchedule) {\n            toSchedule.add(block)\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/FluidSinkPipe.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes\n\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty\nimport network.rs485.logisticspipes.property.Property\nimport network.rs485.logisticspipes.property.PropertyHolder\nimport logisticspipes.interfaces.routing.IFluidSink\nimport logisticspipes.pipes.PipeFluidUtil.getAdjacentTanks\nimport logisticspipes.pipes.basic.fluid.FluidRoutedPipe\nimport logisticspipes.transport.PipeFluidTransportLogistics\nimport logisticspipes.utils.FluidIdentifier\nimport logisticspipes.utils.FluidIdentifierStack\nimport logisticspipes.utils.FluidSinkReply\nimport logisticspipes.utils.PlayerCollectionList\nimport logisticspipes.utils.item.ItemIdentifierInventory\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.Item\n\nabstract class FluidSinkPipe(\n    item: Item, inventoryName: String, inventorySize: Int\n) : FluidRoutedPipe(item), IFluidSink, PropertyHolder, IStore {\n\n    private val guiOpenedBy = PlayerCollectionList()\n\n    // FIXME: after 1.12 give this a proper tag key\n    val sinkInv = ItemIdentifierInventoryProperty(ItemIdentifierInventory(inventorySize, inventoryName, 1, true), \"\")\n\n    override val properties: List<Property<*>> = listOf(sinkInv)\n\n    abstract val priority: FluidSinkReply.FixedFluidPriority\n\n    override fun sinkAmount(stack: FluidIdentifierStack): FluidSinkReply? {\n        if (!guiOpenedBy.isEmpty) {\n            return null // don't sink when the gui is open\n        }\n\n        for (i in sinkInv.indices) {\n            val identStack = sinkInv.getIDStackInSlot(i) ?: continue\n            if (stack.fluid != FluidIdentifier.get(identStack.item)) {\n                continue\n            }\n            val onTheWay: Int = this.countOnRoute(stack.fluid)\n            var freeSpace = -onTheWay.toLong()\n            for (pair in getAdjacentTanks(true)) {\n                val dirOrdinal = pair.component1().direction.ordinal\n                val tank = (transport as PipeFluidTransportLogistics).sideTanks[dirOrdinal]\n                freeSpace += pair.component2().getFreeSpaceInsideTank(stack.fluid).toLong()\n                freeSpace += stack.fluid.getFreeSpaceInsideTank(tank).toLong()\n                if (freeSpace >= stack.amount) {\n                    return FluidSinkReply(priority, stack.amount.toLong())\n                }\n            }\n            return FluidSinkReply(priority, freeSpace)\n        }\n        return null\n    }\n\n    fun guiOpenedByPlayer(player: EntityPlayer?) {\n        guiOpenedBy.add(player)\n    }\n\n    fun guiClosedByPlayer(player: EntityPlayer?) {\n        guiOpenedBy.remove(player)\n    }\n\n    override fun canInsertFromSideToTanks(): Boolean = true\n\n    override fun canInsertToTanks(): Boolean = true\n\n    override fun canReceiveFluid(): Boolean = false\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/SatellitePipe.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes\n\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport net.minecraft.tileentity.TileEntity\nimport javax.annotation.Nullable\n\ninterface SatellitePipe {\n    @Nullable\n    val container: TileEntity?\n\n    val itemList: List<ItemIdentifierStack>\n\n    val satellitesOfType: Set<SatellitePipe>\n\n    var satellitePipeName: String\n\n    fun updateWatchers()\n\n    fun ensureAllSatelliteStatus()\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/compat/BarrelInventoryHandler.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.compat\n\nimport logisticspipes.proxy.specialinventoryhandler.SpecialInventoryHandler\nimport logisticspipes.utils.item.ItemIdentifier\nimport net.minecraft.item.ItemStack\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraftforge.common.capabilities.Capability\nimport net.minecraftforge.common.capabilities.CapabilityInject\nimport network.rs485.logisticspipes.inventory.ProviderMode\nimport pl.asie.charset.api.storage.IBarrel\n\nclass CharsetImplementationFactory : SpecialInventoryHandler.Factory {\n\n    companion object {\n        @JvmStatic\n        @CapabilityInject(IBarrel::class)\n        val barrelCapability: Capability<IBarrel>? = null\n    }\n\n    override fun init(): Boolean = true\n\n    override fun isType(tile: TileEntity, dir: EnumFacing?): Boolean = barrelCapability?.let { tile.hasCapability(it, dir) } ?: false\n\n    override fun getUtilForTile(\n            tile: TileEntity,\n            direction: EnumFacing?,\n            mode: ProviderMode\n    ): SpecialInventoryHandler = BarrelInventoryHandler(tile.getCapability(barrelCapability!!, direction)!!, mode)\n\n}\n\nclass BarrelInventoryHandler(val tile: IBarrel, val mode: ProviderMode) : SpecialInventoryHandler() {\n\n    override fun decrStackSize(slot: Int, amount: Int): ItemStack {\n        if (slot != 0) return ItemStack.EMPTY\n        return tile.extractItem(amount, false)\n    }\n\n    override fun containsUndamagedItem(item: ItemIdentifier): Boolean =\n            ItemIdentifier.get(getItem()).undamaged.equals(item)\n\n    override fun add(stack: ItemStack, orientation: EnumFacing?, doAdd: Boolean): ItemStack {\n        if (tile.shouldInsertToSide(orientation) && (isEmpty() || isValidItem(ItemIdentifier.get(stack)))) {\n            val leftover = tile.insertItem(stack, !doAdd)\n            return if (leftover.isEmpty) {\n                stack\n            } else {\n                assert(leftover.item == stack.item)\n                stack.copy().also { it.count -= leftover.count }\n            }\n        }\n        return stack\n    }\n\n    override fun getMultipleItems(itemIdent: ItemIdentifier, count: Int): ItemStack {\n        if (!isEmpty() && isValidItem(itemIdent)) {\n            if (itemCount(itemIdent) >= count) {\n                return tile.extractItem(count, false)\n            }\n        }\n        return ItemStack.EMPTY\n    }\n\n    override fun getSingleItem(itemIdent: ItemIdentifier): ItemStack = getMultipleItems(itemIdent, 1)\n\n    override fun getItems(): MutableSet<ItemIdentifier> = mutableSetOf(ItemIdentifier.get(getItem()))\n\n    override fun getItemsAndCount(): MutableMap<ItemIdentifier, Int> =\n            mutableMapOf(getIdentifier() to itemCount(getIdentifier()))\n\n    override fun getSizeInventory(): Int = 1\n\n    override fun getStackInSlot(slot: Int): ItemStack {\n        if (slot != 0) return ItemStack.EMPTY\n        val stack = getItem()\n        stack.count = itemCount(getIdentifier())\n        return if (stack.isEmpty) ItemStack.EMPTY\n        else stack\n    }\n\n    override fun roomForItem(stack: ItemStack): Int {\n        val identifier = ItemIdentifier.get(stack)\n        return if (isValidItem(identifier)) {\n            tile.maxItemCount - itemCount(identifier)\n        } else 0\n    }\n\n    override fun itemCount(itemIdent: ItemIdentifier): Int {\n        return if (!isEmpty() && isValidItem(itemIdent)) tile.itemCount.providerMode()\n        else 0\n    }\n\n    /**\n     * Correct amount for current provider mode.\n     */\n    private fun Int.providerMode(): Int {\n        return if (mode.hideOnePerType || mode.hideOnePerStack) (this - 1)\n        else this\n    }\n\n    /**\n     * Checks if the barrel is empty.\n     */\n    private fun isEmpty() = getItem().isEmpty\n\n    /**\n     * Checks if the item matches the one inside the barrel.\n     */\n    private fun isValidItem(itemIdent: ItemIdentifier) = itemIdent.equals(ItemIdentifier.get(getItem()))\n\n    /**\n     * Returns an ItemStack with the same item as the one in the barrel.\n     */\n    private fun getItem(): ItemStack = tile.extractItem(1, true)\n\n    /**\n     * Returns the ItemIdentifier from the getItem method.\n     */\n    private fun getIdentifier(): ItemIdentifier = ItemIdentifier.get(getItem())\n}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/compat/JEIAdvancedGuiHandler.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.compat\n\nimport network.rs485.logisticspipes.gui.BaseGuiContainer\nimport mezz.jei.api.gui.IAdvancedGuiHandler\nimport java.awt.Rectangle\n\nclass JEIAdvancedGuiHandler : IAdvancedGuiHandler<BaseGuiContainer> {\n\n    override fun getGuiContainerClass(): Class<BaseGuiContainer> = BaseGuiContainer::class.java\n\n    override fun getGuiExtraAreas(guiContainer: BaseGuiContainer): MutableList<Rectangle> =\n        guiContainer.getExtraGuiAreas().map { rect ->\n            Rectangle(rect.roundedLeft, rect.roundedTop, rect.roundedWidth, rect.roundedHeight)\n        }.toMutableList()\n}\n\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/compat/JEIGhostIngredientHandler.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.compat\n\nimport network.rs485.logisticspipes.gui.BaseGuiContainer\nimport mezz.jei.api.gui.IGhostIngredientHandler\n\nclass JEIGhostIngredientHandler : IGhostIngredientHandler<BaseGuiContainer> {\n\n    override fun <I : Any?> getTargets(\n        gui: BaseGuiContainer,\n        ingredient: I,\n        doStart: Boolean,\n    ): MutableList<IGhostIngredientHandler.Target<I>> = gui.getFilterSlots()\n\n    override fun onComplete() {}\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/compat/TheOneProbeIntegration.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.compat\n\nimport io.netty.buffer.ByteBuf\nimport logisticspipes.LPConstants\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.modules.*\nimport logisticspipes.pipes.*\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.pipes.basic.CoreUnroutedPipe\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe\nimport logisticspipes.pipes.unrouted.PipeItemsBasicTransport\nimport logisticspipes.proxy.MainProxy\nimport mcjty.theoneprobe.api.*\nimport net.minecraft.block.state.IBlockState\nimport net.minecraft.client.Minecraft\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.ItemStack\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.text.TextFormatting\nimport net.minecraft.world.World\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory\nimport network.rs485.logisticspipes.module.AsyncAdvancedExtractor\nimport network.rs485.logisticspipes.module.AsyncExtractorModule\nimport network.rs485.logisticspipes.util.LPDataIOWrapper\nimport network.rs485.logisticspipes.util.LPDataInput\nimport network.rs485.logisticspipes.util.LPDataOutput\nimport network.rs485.logisticspipes.util.TextUtil\nimport java.util.*\nimport java.util.function.Function\nimport kotlin.properties.Delegates\n\nclass TheOneProbeIntegration : Function<ITheOneProbe, Void?> {\n\n    /** general translation key prefix for The One Probe translation keys */\n    private val prefix = \"top.logisticspipes.\"\n    /** very simple translation key regex */\n    private val translationKeyRegex = Regex(\"([a-z]+\\\\.)+[a-z]+\")\n    private var lpTextElementId by Delegates.notNull<Int>()\n    private var renderText: ((x: Int, y: Int, txt: String) -> Int)? = null\n\n    override fun apply(probe: ITheOneProbe): Void? {\n        lpTextElementId = probe.registerElementFactory(::LPText)\n        MainProxy.runOnClient(null) {\n            Runnable {\n                renderText = try {\n                    val renderHelper = Class.forName(\"mcjty.theoneprobe.rendering.RenderHelper\")\n                    val renderTextMethod = renderHelper.getDeclaredMethod(\n                        \"renderText\",\n                        Minecraft::class.java,\n                        Int::class.java,\n                        Int::class.java,\n                        String::class.java\n                    );\n                    // returns the width of the rendered text\n                    { x, y, txt -> renderTextMethod.invoke(null, Minecraft.getMinecraft(), x, y, txt) as Int }\n                } catch (e: ReflectiveOperationException) {\n                    LogisticsPipes.log.error(\"Could not acquire RenderHelper.renderText\", e)\n                    null\n                }\n            }\n        }\n\n        probe.registerProvider(PipeInfoProvider())\n        LogisticsPipes.log.info(\"The One Probe integration loaded.\")\n        return null\n    }\n\n    private inner class PipeInfoProvider : IProbeInfoProvider {\n\n        override fun getID(): String = \"${LPConstants.LP_MOD_ID}:pipe_info_provider\"\n\n        override fun addProbeInfo(\n            mode: ProbeMode,\n            probeInfo: IProbeInfo?,\n            player: EntityPlayer?,\n            world: World,\n            blockState: IBlockState?,\n            data: IProbeHitData?,\n        ) {\n            if (probeInfo == null || blockState == null || data == null) return\n            when (blockState.block) {\n                is LogisticsBlockGenericPipe -> {\n                    val isModule = false\n                    val pipe = LogisticsBlockGenericPipe.getPipe(world, data.pos)\n                    when (pipe) {\n                        is PipeItemsFirewall -> addFirewallPipeInfo(pipe, probeInfo)\n                        is PipeLogisticsChassis -> addChassisPipeInfo(pipe, probeInfo, mode)\n                        is PipeItemsBasicTransport -> addBasicTransportPipeInfo(pipe, probeInfo)\n                        is PipeItemsSatelliteLogistics -> addSatellitePipeInfo(pipe, probeInfo)\n                        is PipeItemsBasicLogistics -> addItemSinkModuleInfo(\n                            module = pipe.logisticsModule,\n                            probeInfo = probeInfo,\n                            mode = ProbeMode.EXTENDED,\n                            isModule = isModule\n                        )\n                        is PipeItemsSupplierLogistics -> addActiveSupplierModuleInfo(\n                            module = pipe.logisticsModule,\n                            probeInfo = probeInfo,\n                            mode = ProbeMode.EXTENDED,\n                            isModule = isModule\n                        )\n                        is PipeItemsCraftingLogistics -> addCraftingModuleInfo(\n                            module = pipe.logisticsModule,\n                            probeInfo = probeInfo,\n                            mode = ProbeMode.EXTENDED,\n                            isModule = isModule\n                        )\n                        is PipeItemsProviderLogistics -> addProviderModuleInfo(\n                            module = pipe.logisticsModule,\n                            probeInfo = probeInfo,\n                            mode = ProbeMode.EXTENDED,\n                            isModule = isModule\n                        )\n                        is PipeItemsSystemDestinationLogistics -> Unit // TODO pipe doesn't work atm\n                        is PipeItemsSystemEntranceLogistics -> Unit // TODO pipe doesn't work atm\n                        is PipeItemsRemoteOrdererLogistics -> Unit\n                        is PipeItemsRequestLogistics -> Unit\n                        else -> {\n                            if (LogisticsPipes.isDEBUG()) {\n                                probeInfo.text(\"Not implemented.\")\n                                probeInfo.text(pipe.javaClass.name)\n                            }\n                        }\n                    }\n                    defaultInfo(pipe, probeInfo, mode)\n                }\n            }\n        }\n\n        private fun addFirewallPipeInfo(pipe: PipeItemsFirewall, probeInfo: IProbeInfo) {\n            val allowed = \"${prefix}pipe.firewall.allowed\"\n            val blocked = \"${prefix}pipe.firewall.blocked\"\n            if (!pipe.inv.isEmpty) {\n                probeInfo.element(LPText(\"${prefix}pipe.firewall.filtering\").apply {\n                    arguments.add(pipe.inv.itemsAndCount.count { it.value > 0 }.toString())\n                    arguments.add(if (pipe.isBlocking) blocked else allowed)\n                })\n            }\n            listOf(\n                \"pipe.firewall.providing\" to pipe.isBlockProvider,\n                \"pipe.firewall.crafting\" to pipe.isBlockCrafter,\n                \"pipe.firewall.sorting\" to pipe.isBlockSorting,\n                \"pipe.firewall.power\" to pipe.isBlockPower,\n            ).forEach {\n                probeInfo.element(LPText(prefix + it.first).apply {\n                    arguments.add(if (it.second) blocked else allowed)\n                })\n            }\n        }\n\n        private fun addSatellitePipeInfo(pipe: PipeItemsSatelliteLogistics, probeInfo: IProbeInfo) {\n            val satellitePipeName = pipe.satellitePipeName\n            if (satellitePipeName.isNotBlank()) {\n                probeInfo.element(LPText(\"${prefix}pipe.satellite.name\").apply { arguments.add(satellitePipeName) })\n            } else {\n                probeInfo.element(LPText(\"${prefix}pipe.satellite.no_name\"))\n            }\n        }\n\n        private fun addBasicTransportPipeInfo(pipe: PipeItemsBasicTransport, logisticsPipesInfoContainer: IProbeInfo) {\n            val connections = pipe.container?.pipeConnectionsBuffer?.count { it } ?: 0\n            if (connections > 2) {\n                logisticsPipesInfoContainer.element(LPText(\"${prefix}pipe.unrouted.too_many_connections\"))\n            }\n        }\n\n        private fun defaultInfo(pipe: CoreUnroutedPipe, probeInfo: IProbeInfo, mode: ProbeMode) {\n            if (mode == ProbeMode.EXTENDED) {\n                addUpgradesInfo(pipe, probeInfo, mode)\n            }\n        }\n\n        private fun addUpgradesInfo(pipe: CoreUnroutedPipe, probeInfo: IProbeInfo, mode: ProbeMode) {\n            if (pipe is CoreRoutedPipe) {\n                if (mode == ProbeMode.EXTENDED) {\n                    val upgradeManagerInv = pipe.originalUpgradeManager.inv\n                    val upgrades = (0 until upgradeManagerInv.sizeInventory).mapNotNull { slotId ->\n                        upgradeManagerInv.getStackInSlot(slotId).takeIf { !it.isEmpty }?.displayName\n                    }\n                    if (upgrades.isNotEmpty()) {\n                        probeInfo.element(LPText(\"${prefix}general.upgrades\").apply {\n                            arguments.add(\n                                upgrades.joinToString(\n                                    separator = \"\\$WHITE, \\$AQUA\",\n                                    prefix = \"\\$AQUA\",\n                                    postfix = \"\\$WHITE;\",\n                                    limit = 3\n                                )\n                            )\n                        })\n                    } else {\n                        probeInfo.element(LPText(\"${prefix}general.no_upgrades\"))\n                    }\n                }\n            }\n        }\n\n        private fun addChassisPipeInfo(pipe: PipeLogisticsChassis, probeInfo: IProbeInfo, mode: ProbeMode) {\n            val chassisColumn = probeInfo.vertical()\n            val modules = (0 until pipe.chassieSize).mapNotNull { slotId ->\n                val module = pipe.getSubModule(slotId)\n                val stack = pipe.getModuleInventory().getStackInSlot(slotId)\n                if (module == null) null\n                else module to stack\n            }\n            if (modules.isNotEmpty()) {\n                if (mode == ProbeMode.EXTENDED) {\n                    modules.forEach { (module, stack) ->\n                        val infoCol = chassisColumn.addItemWithText(stack)\n                        val isModule = true\n                        when (module) {\n                            is ModuleItemSink -> addItemSinkModuleInfo(module, infoCol, mode, isModule)\n                            is ModuleProvider -> addProviderModuleInfo(module, infoCol, mode, isModule)\n                            is ModuleCrafter -> addCraftingModuleInfo(module, infoCol, mode, isModule)\n                            is ModuleActiveSupplier -> addActiveSupplierModuleInfo(module, infoCol, mode, isModule)\n                            is AsyncExtractorModule -> addExtractorModuleInfo(module, infoCol, mode)\n                            is AsyncAdvancedExtractor -> addAdvancedExtractorModuleInfo(module, infoCol, mode)\n                            is ModulePassiveSupplier -> addFilteringListItemIdentifierInfo(\n                                probeInfo = infoCol,\n                                mode = mode,\n                                positiveTranslationKey = \"${prefix}module.passive_supplier.filter\",\n                                negativeTranslationKey = \"${prefix}module.passive_supplier.no_filter\",\n                                items = module.filterInventory,\n                                isModule = isModule\n                            )\n                            is ModuleTerminus -> addFilteringListItemIdentifierInfo(\n                                probeInfo = infoCol,\n                                mode = mode,\n                                positiveTranslationKey = \"${prefix}module.terminus.filter\",\n                                negativeTranslationKey = \"${prefix}module.terminus.no_filter\",\n                                items = module.filterInventory,\n                                isModule = isModule\n                            )\n                            is ModuleEnchantmentSinkMK2 -> addFilteringListItemIdentifierInfo(\n                                probeInfo = infoCol,\n                                mode = mode,\n                                positiveTranslationKey = \"${prefix}module.enchantment_sink.filter\",\n                                negativeTranslationKey = \"${prefix}module.enchantment_sink.no_filter\",\n                                items = module.filterInventory,\n                                isModule = isModule\n                            )\n                            is ModuleCreativeTabBasedItemSink -> addFilteringListStringInfo(\n                                probeInfo = infoCol,\n                                mode = mode,\n                                positiveTranslationKey = \"${prefix}module.creative_tab_item_sink.filter\",\n                                negativeTranslationKey = \"${prefix}module.creative_tab_item_sink.no_filter\",\n                                strings = module.tabList,\n                                isModule = isModule\n                            )\n                            is ModuleModBasedItemSink -> addFilteringListStringInfo(\n                                probeInfo = infoCol,\n                                mode = mode,\n                                positiveTranslationKey = \"${prefix}module.mod_item_sink.filter\",\n                                negativeTranslationKey = \"${prefix}module.mod_item_sink.no_filter\",\n                                strings = module.modList,\n                                isModule = isModule\n                            )\n                            is ModuleOreDictItemSink -> addFilteringListStringInfo(\n                                probeInfo = infoCol,\n                                mode = mode,\n                                positiveTranslationKey = \"${prefix}module.ore_item_sink.filter\",\n                                negativeTranslationKey = \"${prefix}module.ore_item_sink.no_filter\",\n                                strings = module.oreList,\n                                isModule = isModule\n                            )\n                        }\n                    }\n                } else {\n                    val infoRow = probeInfo.horizontal()\n                    modules.forEach { (_, stack) ->\n                        infoRow.item(stack)\n                    }\n                }\n            } else {\n                chassisColumn.element(LPText(\"${prefix}pipe.chassis.no_modules\"))\n            }\n        }\n\n        private fun addItemSinkModuleInfo(\n            module: ModuleItemSink,\n            probeInfo: IProbeInfo,\n            mode: ProbeMode,\n            isModule: Boolean\n        ) {\n            if (mode == ProbeMode.EXTENDED) {\n                if (module.isDefaultRoute) {\n                    probeInfo.element(LPText(\"${prefix}general.is_default_route\").apply {\n                        baseFormatting.addAll(italic(isModule))\n                        prepend = prepend(isModule)\n                    })\n                } else if (isModule) {\n                    probeInfo.element(LPText(\"${prefix}general.is_not_default_route\").apply {\n                        baseFormatting.addAll(italic(isModule))\n                        prepend = prepend(isModule)\n                    })\n                }\n            }\n        }\n\n        private fun addActiveSupplierModuleInfo(\n            module: ModuleActiveSupplier,\n            probeInfo: IProbeInfo,\n            mode: ProbeMode,\n            isModule: Boolean\n        ) {\n            if (mode == ProbeMode.EXTENDED) {\n                if (module.inventory.isEmpty) {\n                    probeInfo.element(LPText(\"${prefix}module.active_supplier.no_filter\").apply {\n                        baseFormatting.addAll(italic(isModule))\n                        prepend = prepend(isModule)\n                    })\n                } else {\n                    probeInfo.element(LPText(\"${prefix}module.active_supplier.mode\").apply {\n                        baseFormatting.addAll(italic(isModule))\n                        prepend = prepend(isModule)\n                        arguments.add(module.requestMode.value.name)\n                    })\n                    addFilteringListItemIdentifierInfo(\n                        probeInfo = probeInfo,\n                        mode = mode,\n                        positiveTranslationKey = \"${prefix}module.active_supplier.filter\",\n                        negativeTranslationKey = \"\",\n                        items = module.inventory,\n                        isModule = isModule\n                    )\n                }\n            }\n        }\n\n        private fun addExtractorModuleInfo(module: AsyncExtractorModule, probeInfo: IProbeInfo, mode: ProbeMode) {\n            if (mode == ProbeMode.EXTENDED) {\n                addSneakyExtractorInfo(module.sneakyDirection, probeInfo)\n            }\n        }\n\n        private fun addAdvancedExtractorModuleInfo(\n            module: AsyncAdvancedExtractor,\n            probeInfo: IProbeInfo,\n            mode: ProbeMode\n        ) {\n            val isModule = true\n            if (mode == ProbeMode.EXTENDED) {\n                addFilteringListItemIdentifierInfo(\n                    probeInfo = probeInfo,\n                    mode = mode,\n                    positiveTranslationKey = if (module.itemsIncluded.value) {\n                        \"${prefix}module.advanced_extractor.only\"\n                    } else {\n                        \"${prefix}module.advanced_extractor.but\"\n                    },\n                    negativeTranslationKey = if (module.itemsIncluded.value) {\n                        \"${prefix}module.advanced_extractor.none\"\n                    } else {\n                        \"${prefix}module.advanced_extractor.all\"\n                    },\n                    items = module.getFilterInventory(),\n                    isModule = isModule\n                )\n                addSneakyExtractorInfo(module.sneakyDirection, probeInfo)\n            }\n        }\n\n        private fun addSneakyExtractorInfo(\n            direction: EnumFacing?,\n            probeInfo: IProbeInfo,\n        ) {\n            val isModule = true\n            if (direction != null) {\n                probeInfo.element(LPText(\"${prefix}module.extractor.side\").apply {\n                    baseFormatting.addAll(italic(isModule))\n                    prepend = prepend(isModule)\n                    arguments.add(direction.name2)\n                })\n            }\n        }\n\n        private fun addProviderModuleInfo(\n            module: ModuleProvider,\n            probeInfo: IProbeInfo,\n            mode: ProbeMode,\n            isModule: Boolean\n        ) {\n            if (mode == ProbeMode.EXTENDED) {\n                addFilteringListItemIdentifierInfo(\n                    probeInfo = probeInfo,\n                    mode = mode,\n                    positiveTranslationKey = if (module.isExclusionFilter.value) {\n                        \"${prefix}module.provider.but\"\n                    } else {\n                        \"${prefix}module.provider.only\"\n                    },\n                    // TODO change this if the behaviour ever changes \"module.provider.none\"\n                    negativeTranslationKey = \"${prefix}module.provider.all\",\n                    items = module.filterInventory,\n                    isModule = isModule\n                )\n                if (!isModule) {\n                    probeInfo.element(LPText(\"${prefix}module.provider.mode\"))\n                }\n                probeInfo.element(LPText(module.providerMode.value.modeTranslationKey).apply {\n                    baseFormatting.addAll(italic(isModule))\n                    prepend = prepend(isModule)\n                })\n            }\n        }\n\n        private fun addCraftingModuleInfo(\n            module: ModuleCrafter,\n            probeInfo: IProbeInfo,\n            mode: ProbeMode,\n            isModule: Boolean\n        ) {\n            if (mode == ProbeMode.EXTENDED) {\n                if (module.craftedItem != null) {\n                    val fuzzyText = if (module.hasFuzzyUpgrade()) \" \\$GOLD[Fuzzy]\\$WHITE\" else \"\"\n                    if (module.hasByproductUpgrade() && module.byproductItem != null) {\n                        probeInfo.element(LPText(\"${prefix}module.crafting.result_with_byproduct\").apply {\n                            baseFormatting.addAll(italic(isModule))\n                            prepend = prepend(isModule)\n                            append = fuzzyText\n                            arguments.add(module.craftedItem!!.friendlyName)\n                            arguments.add(module.byproductItem!!.friendlyName)\n                        })\n                    } else {\n                        probeInfo.element(LPText(\"${prefix}module.crafting.result\").apply {\n                            baseFormatting.addAll(italic(isModule))\n                            prepend = prepend(isModule)\n                            append = fuzzyText\n                            arguments.add(module.craftedItem!!.friendlyName)\n                        })\n                    }\n                } else {\n                    probeInfo.element(LPText(\"${prefix}module.crafting.no_result\").apply {\n                        baseFormatting.addAll(italic(isModule))\n                        prepend = prepend(isModule)\n                    })\n                }\n            }\n        }\n\n        private fun addFilteringListItemIdentifierInfo(\n            probeInfo: IProbeInfo,\n            mode: ProbeMode,\n            positiveTranslationKey: String,\n            negativeTranslationKey: String,\n            items: IItemIdentifierInventory,\n            isModule: Boolean,\n            color: TextFormatting = TextFormatting.WHITE\n        ) {\n            addFilteringListStringInfo(\n                probeInfo = probeInfo,\n                mode = mode,\n                positiveTranslationKey = positiveTranslationKey,\n                negativeTranslationKey = negativeTranslationKey,\n                strings = items.itemsAndCount.mapNotNull {\n                    if (it.value > 0) it.key.friendlyName else null\n                },\n                isModule = isModule,\n                color = color\n            )\n        }\n\n        private fun addFilteringListStringInfo(\n            probeInfo: IProbeInfo,\n            mode: ProbeMode,\n            positiveTranslationKey: String,\n            negativeTranslationKey: String,\n            strings: List<String>,\n            limit: Int = 3,\n            isModule: Boolean,\n            color: TextFormatting = TextFormatting.WHITE\n        ) {\n            if (mode == ProbeMode.EXTENDED) {\n                if (strings.isNotEmpty() && positiveTranslationKey.isNotBlank()) {\n                    probeInfo.element(LPText(positiveTranslationKey).apply {\n                        baseFormatting.addAll(italic(isModule, color))\n                        prepend = prepend(isModule)\n                        arguments.add(\n                            strings.joinToString(\n                                separator = \"\\$WHITE, \\$AQUA\",\n                                prefix = \"\\$AQUA\",\n                                postfix = \"\\$WHITE\",\n                                limit = limit\n                            )\n                        )\n                    })\n                } else if (negativeTranslationKey.isNotBlank()) {\n                    probeInfo.element(LPText(negativeTranslationKey).apply {\n                        baseFormatting.addAll(italic(isModule))\n                        prepend = prepend(isModule)\n                    })\n                }\n            }\n        }\n\n        /**\n         * Adds a item icon/text combo.\n         * @param itemStack item to be displayed.\n         * @param text to be displayed, will display the item's translated name if blank.\n         */\n        fun IProbeInfo.addItemWithText(itemStack: ItemStack, text: String = \"\"): IProbeInfo {\n            val resultLine =\n                horizontal(defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER).spacing(3))\n            resultLine.vertical().item(itemStack)\n            val textColumn = resultLine.vertical()\n            if (text.isBlank()) {\n                textColumn.itemLabel(itemStack)\n            } else {\n                textColumn.text(text)\n            }\n            return textColumn\n        }\n\n        fun italic(italic: Boolean, color: TextFormatting = TextFormatting.WHITE): EnumSet<TextFormatting> =\n            if (italic) EnumSet.of(TextFormatting.ITALIC, color) else EnumSet.of(color)\n\n        fun prepend(isModule: Boolean): String = if (isModule) \"- \" else \"\"\n    }\n\n    inner class LPText : IElement {\n        var append: String = \"\"\n        var prepend: String = \"\"\n        val baseFormatting: EnumSet<TextFormatting> = EnumSet.noneOf(TextFormatting::class.java)\n        val arguments: MutableList<String> = ArrayList<String>()\n        var key: String? = null\n\n        /**\n         * Only for clients.\n         */\n        val translated\n            get() = TextUtil.translate(\n                key = key!!,\n                baseFormatting = baseFormatting,\n                prepend = translateIfApplicable(prepend),\n                append = translateIfApplicable(append),\n                args = arguments.map { translateIfApplicable(it) }.toTypedArray(),\n            )\n\n        private fun translateIfApplicable(text: String) =\n            if (translationKeyRegex.matches(text)) TextUtil.translate(text) else text\n\n        constructor(key: String) {\n            this.key = key\n        }\n\n        constructor(buf: ByteBuf) {\n            try {\n                LPDataIOWrapper.provideData(buf) { input ->\n                    key = input.readUTF()\n                    input.readArrayList(LPDataInput::readUTF)?.filterNotNull()?.also { arguments.addAll(it) }\n                    baseFormatting.addAll(input.readEnumSet(TextFormatting::class.java))\n                    input.readUTF()?.also { prepend = it }\n                    input.readUTF()?.also { append = it }\n                }\n            } catch (e: Exception) {\n                LogisticsPipes.log.error(\"Problem when reading buffer for TheOneProbe\", e)\n            }\n        }\n\n        override fun toBytes(buf: ByteBuf) = try {\n            LPDataIOWrapper.writeData(buf) {\n                it.writeUTF(key)\n                it.writeCollection(arguments, LPDataOutput::writeUTF)\n                it.writeEnumSet(baseFormatting, TextFormatting::class.java)\n                it.writeUTF(prepend)\n                it.writeUTF(append)\n            }\n        } catch (e: Exception) {\n            LogisticsPipes.log.error(\"Problem when writing buffer for TheOneProbe\", e)\n        }\n\n        /**\n         * Obviously only for clients.\n         */\n        override fun render(x: Int, y: Int) {\n            renderText?.invoke(x, y, translated)\n        }\n\n        /**\n         * Only for clients.\n         */\n        override fun getWidth(): Int {\n            return Minecraft.getMinecraft()?.fontRenderer?.getStringWidth(translated) ?: 0\n        }\n\n        override fun getHeight(): Int {\n            return 10\n        }\n\n        override fun getID(): Int {\n            return lpTextElementId\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/config/ClientConfiguration.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.config\n\nimport network.rs485.logisticspipes.util.LPDataInput\nimport network.rs485.logisticspipes.util.LPDataOutput\nimport network.rs485.logisticspipes.util.LPSerializable\n\nopen class ClientConfiguration : LPSerializable {\n    var renderPipeDistance = 48\n    var renderPipeContentDistance = 24\n\n    override fun write(output: LPDataOutput) {\n        output.writeInt(renderPipeDistance)\n        output.writeInt(renderPipeContentDistance)\n    }\n\n    override fun read(input: LPDataInput) {\n        renderPipeDistance = input.readInt()\n        renderPipeContentDistance = input.readInt()\n    }\n\n    fun merge(configuration: ClientConfiguration) {\n        renderPipeDistance = configuration.renderPipeDistance\n        renderPipeContentDistance = configuration.renderPipeContentDistance\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/config/PlayerConfiguration.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.config\n\nclass PlayerConfiguration : ClientConfiguration() {\n    var hasCraftedLPItem = false\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/config/ServerConfiguration.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.config\n\nimport com.google.gson.*\nimport com.google.gson.annotations.JsonAdapter\nimport logisticspipes.utils.PlayerIdentifier\nimport java.lang.reflect.Type\nimport java.util.*\n\nprivate class ServerConfigurationAdapter : JsonSerializer<Map<PlayerIdentifier, PlayerConfiguration>>, JsonDeserializer<Map<PlayerIdentifier, PlayerConfiguration>> {\n    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Map<PlayerIdentifier, PlayerConfiguration>? {\n        if (json.isJsonNull) {\n            return null\n        } else if (!json.isJsonObject) {\n            throw JsonParseException(\"Expected an object from a map\")\n        }\n\n        return json.asJsonObject.entrySet().associate { (key, value) ->\n            if (value !is JsonObject) throw JsonParseException(\"Expected values in map object to be objects\")\n            Pair(\n                    PlayerIdentifier.get(value[\"name\"].asString, UUID.fromString(key)),\n                    context.deserialize<PlayerConfiguration>(value[\"config\"], PlayerConfiguration::class.java)\n            )\n        }\n    }\n\n    override fun serialize(src: Map<PlayerIdentifier, PlayerConfiguration>?, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {\n        if (src == null) {\n            return JsonNull.INSTANCE\n        }\n\n        return JsonObject().apply {\n            src.keys.forEach {\n                this.add(it.id.toString(), JsonObject().apply {\n                    this.add(\"name\", JsonPrimitive(it.username))\n                    this.add(\"config\", context.serialize(src[it], PlayerConfiguration::class.java))\n                })\n            }\n        }\n    }\n}\n\ninternal class ServerConfiguration {\n    @JsonAdapter(ServerConfigurationAdapter::class)\n    var playerConfigurations: Map<PlayerIdentifier, PlayerConfiguration> = emptyMap()\n}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/config/ServerConfigurationManager.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.config\n\nimport com.google.gson.Gson\nimport com.google.gson.JsonParseException\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.utils.PlayerIdentifier\nimport net.minecraftforge.fml.common.FMLCommonHandler\nimport java.io.File\nimport java.io.FileNotFoundException\nimport java.nio.file.Files\nimport java.nio.file.StandardCopyOption\nimport java.util.*\n\nclass ServerConfigurationManager {\n    private val fileName = \"logisticspipes.json\"\n\n    private val configFile: File\n    private val gson = Gson()\n    private val internalRepresentation: ServerConfiguration\n\n    init {\n        configFile = File(FMLCommonHandler.instance().savesDirectory, fileName)\n        internalRepresentation = try {\n            configFile.bufferedReader(Charsets.UTF_8).use {\n                gson.fromJson(gson.newJsonReader(it), ServerConfiguration::class.java)\n            }\n        } catch (e: JsonParseException) {\n            LogisticsPipes.log.error(\"Cannot read LP configuration! Moving current configuration away and starting a new one!\")\n            Files.move(configFile.toPath(), getTimedFile(\".bkp\").toPath())\n            ServerConfiguration()\n        } catch (e: FileNotFoundException) {\n            LogisticsPipes.log.info(\"Starting a new LP configuration\")\n            ServerConfiguration()\n        }\n    }\n\n    fun getPlayers(): Set<PlayerIdentifier> {\n        return internalRepresentation.playerConfigurations.keys\n    }\n\n    fun getPlayerConfiguration(identifier: PlayerIdentifier): PlayerConfiguration {\n        return internalRepresentation.playerConfigurations[identifier] ?: PlayerConfiguration()\n    }\n\n    fun setClientConfiguration(identifier: PlayerIdentifier, configuration: ClientConfiguration) {\n        val newConfigurations = internalRepresentation.playerConfigurations.toMutableMap()\n        newConfigurations.computeIfAbsent(identifier) { PlayerConfiguration() }.merge(configuration)\n        internalRepresentation.playerConfigurations = newConfigurations\n        writeChange()\n    }\n\n    fun setPlayerConfiguration(identifier: PlayerIdentifier, configuration: PlayerConfiguration) {\n        val newConfigurations = HashMap(internalRepresentation.playerConfigurations)\n        newConfigurations[identifier] = configuration\n        internalRepresentation.playerConfigurations = newConfigurations\n        writeChange()\n    }\n\n    private fun writeChange() {\n        val tmpFile = getTimedFile(\".tmp\")\n        try {\n            tmpFile.bufferedWriter(Charsets.UTF_8).use {\n                val jsonElement = gson.toJsonTree(internalRepresentation, ServerConfiguration::class.java)\n                gson.toJson(jsonElement, gson.newJsonWriter(it))\n            }\n            Files.move(tmpFile.toPath(), configFile.toPath(), StandardCopyOption.REPLACE_EXISTING)\n        } finally {\n            Files.deleteIfExists(tmpFile.toPath())\n        }\n    }\n\n    private fun getTimedFile(suffix: String = \"\"): File {\n        val time = Calendar.getInstance().timeInMillis.toString()\n        return File(configFile.parentFile, \"${configFile.name}.$time$suffix\")\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/AdjacentFactory.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.proxy.SimpleServiceLocator\nimport net.minecraft.util.EnumFacing\nimport network.rs485.logisticspipes.world.WorldCoordinatesWrapper\n\nobject AdjacentFactory {\n    fun createAdjacentCache(parent: CoreRoutedPipe): Adjacent {\n        val connectedTileEntities = WorldCoordinatesWrapper(parent.container!!).connectedTileEntities()\n            .filter { SimpleServiceLocator.pipeInformationManager.isNotAPipe(it.tileEntity) && !parent.isSideBlocked(it.direction, false) }\n\n        // FIXME: container.canPipeConnect(neighbor.getTileEntity(), neighbor.getDirection()))\n        // the above will check InventoryUtil.getSizeInventory() > 0 (which is wrong)\n        // it is similar to SimpleServiceLocator.pipeInformationManager.isNotAPipe\n        return when {\n            connectedTileEntities.isEmpty() -> NoAdjacent\n            // FIXME: check when to use FLUID/ITEM/UNDEFINED\n            connectedTileEntities.size == 1 -> SingleAdjacent(parent, connectedTileEntities[0].direction, ConnectionType.UNDEFINED)\n            else -> DynamicAdjacent(parent, arrayOfNulls<ConnectionType>(EnumFacing.VALUES.size).also { arr ->\n                connectedTileEntities.forEach { neighbor -> arr[neighbor.direction.index] = ConnectionType.UNDEFINED }\n            })\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/AdjacentUtil.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport logisticspipes.interfaces.ISlotUpgradeManager\n\nfun Adjacent.sneakyInventoryUtils(upgradeManager: ISlotUpgradeManager) =\n    inventories().map { it.sneakyInsertion().from(upgradeManager).getInventoryUtil() }\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/DynamicAdjacent.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.math.BlockPos\nimport java.util.*\n\nclass DynamicAdjacent(private val parent: CoreRoutedPipe, private val cache: Array<ConnectionType?>) : Adjacent {\n    override fun connectedPos(): Map<BlockPos, ConnectionType> = cache\n        .mapIndexedNotNull { index, type -> type?.let { parent.pos.offset(EnumFacing.VALUES[index]) to type } }\n        .let { it.associateTo(LinkedHashMap(it.size)) { pair -> pair } }\n\n    override fun get(direction: EnumFacing): ConnectionType? = cache[direction.index]\n\n    override fun optionalGet(direction: EnumFacing): Optional<ConnectionType> = Optional.ofNullable(cache[direction.index])\n\n    override fun neighbors(): Map<NeighborTileEntity<TileEntity>, ConnectionType> = cache\n        .mapIndexedNotNull { index, connectionType ->\n            connectionType?.let {\n                EnumFacing.VALUES[index].let { dir ->\n                    parent.world.getTileEntity(parent.pos.offset(dir))?.let { LPNeighborTileEntity(it, dir) to connectionType }\n                }\n            }\n        }\n        .let { it.associateTo(LinkedHashMap(it.size)) { pair -> pair } }\n\n    override fun inventories() = cache\n        .filter { it?.isItem() ?: false }\n        .mapIndexedNotNull { index, _ ->\n            EnumFacing.VALUES[index].let { dir ->\n                parent.world.getTileEntity(parent.pos.offset(dir))?.let { it to dir }\n            }\n        }\n        .mapNotNull { (tile, dir) -> LPNeighborTileEntity(tile, dir).takeIf { it.canHandleItems() } }\n\n    override fun fluidTanks(): List<NeighborTileEntity<TileEntity>> = cache\n        .filter { it?.isFluid() ?: false }\n        .mapIndexedNotNull { index, _ ->\n            EnumFacing.VALUES[index].let { dir ->\n                parent.world.getTileEntity(parent.pos.offset(dir))?.let { it to dir }\n            }\n        }\n        .mapNotNull { (tile, dir) -> LPNeighborTileEntity(tile, dir).takeIf { it.canHandleFluids() } }\n\n    override fun toString(): String = \"DynamicAdjacent(${EnumFacing.VALUES.withIndex().joinToString { \"{${it.value.name2}: ${cache[it.index]}}\" }})\"\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/LPNeighborTileEntity.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport logisticspipes.interfaces.IInventoryUtil\nimport logisticspipes.interfaces.ITankUtil\nimport logisticspipes.pipes.PipeFluidUtil\nimport logisticspipes.pipes.basic.LogisticsTileGenericPipe\nimport logisticspipes.proxy.SimpleServiceLocator\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport java.util.*\nimport javax.annotation.Nonnull\nimport javax.annotation.Nullable\n\n@Nullable\nfun <T : TileEntity> NeighborTileEntity<T>.getInventoryUtil(): IInventoryUtil? =\n    SimpleServiceLocator.inventoryUtilFactory.getInventoryUtil(tileEntity, getOurDirection())\n\n@Nullable\nfun <T : TileEntity> NeighborTileEntity<T>.getTankUtil(): ITankUtil? =\n    PipeFluidUtil.getTankUtilForTE(tileEntity, getOurDirection())\n\n@Nonnull\nfun <T : TileEntity> NeighborTileEntity<T>.sneakyInsertion(): LPNeighborTileEntitySneakyInsertion<T> =\n    LPNeighborTileEntitySneakyInsertion(tileEntity, direction)\n\n@Nonnull\nfun <T : TileEntity, C : T> NeighborTileEntity<T>.optionalIs(clazz: Class<C>): Optional<LPNeighborTileEntity<C>> =\n    if (clazz.isInstance(tileEntity)) {\n        Optional.of(LPNeighborTileEntity(clazz.cast(tileEntity), direction))\n    } else {\n        Optional.empty()\n    }\n\nopen class LPNeighborTileEntity<T : TileEntity>(\n    tileEntity: T,\n    direction: EnumFacing,\n) : NeighborTileEntity<T>(tileEntity, direction) {\n\n    override fun isLogisticsPipe(): Boolean = tileEntity is LogisticsTileGenericPipe\n\n    override fun canHandleItems(): Boolean = getInventoryUtil() != null\n\n    override fun canHandleFluids(): Boolean = getTankUtil() != null\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/LPNeighborTileEntitySneakyInsertion.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport logisticspipes.interfaces.ISlotUpgradeManager\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\n\nclass LPNeighborTileEntitySneakyInsertion<T : TileEntity>(tileEntity: T, direction: EnumFacing) :\n        LPNeighborTileEntity<T>(tileEntity, direction) {\n    private var sneakyDirection: EnumFacing = super.getOurDirection()\n\n    override fun getOurDirection(): EnumFacing {\n        return sneakyDirection\n    }\n\n    fun from(direction: EnumFacing): LPNeighborTileEntitySneakyInsertion<T> {\n        sneakyDirection = direction\n        return this\n    }\n\n    fun from(upgradeManager: ISlotUpgradeManager?): LPNeighborTileEntitySneakyInsertion<T> {\n        if (upgradeManager?.hasSneakyUpgrade() == true) sneakyDirection = upgradeManager.sneakyOrientation\n        return this\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/NoAdjacent.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.math.BlockPos\nimport java.util.*\n\nobject NoAdjacent : Adjacent {\n    override fun connectedPos(): Map<BlockPos, ConnectionType> = emptyMap()\n    override fun get(direction: EnumFacing): ConnectionType? = null\n    override fun optionalGet(direction: EnumFacing): Optional<ConnectionType> = Optional.empty()\n    override fun neighbors(): Map<NeighborTileEntity<TileEntity>, ConnectionType> = emptyMap()\n    override fun inventories(): List<NeighborTileEntity<TileEntity>> = emptyList()\n    override fun fluidTanks(): List<NeighborTileEntity<TileEntity>> = emptyList()\n    override fun toString(): String = \"NoAdjacent\"\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/PipeInventoryConnectionChecker.kt",
    "content": "/*\n * Copyright (c) 2019  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.tileentity.TileEntityHopper\nimport net.minecraftforge.fml.common.Loader\n\nclass PipeInventoryConnectionChecker {\n    private val allowedConnectionClasses = mutableSetOf<Class<*>>()\n    private val cachedClasses = mutableMapOf<Class<TileEntity>, Boolean>()\n\n    init {\n        allowedConnectionClasses.add(TileEntityHopper::class.java)\n        checkAndAddClass(\"gregtech\", \"gregtech.api.block.BlockStateTileEntity\")\n    }\n\n    private fun checkAndAddClass(modId: String, className: String) {\n        if (Loader.isModLoaded(modId)) {\n            try {\n                val clazz = Class.forName(className)\n                addSupportedClassType(clazz)\n            } catch (_: ClassNotFoundException) {\n            }\n        }\n    }\n\n    fun addSupportedClassType(clazz: Class<*>) {\n        allowedConnectionClasses.add(clazz)\n    }\n\n    fun shouldLPProvideInventoryTo(tile: TileEntity): Boolean {\n        return cachedClasses.computeIfAbsent(tile.javaClass) {\n            var clazz = it as Class<*>\n            while (clazz.superclass != Object::class.java) {\n                if (allowedConnectionClasses.contains(clazz)) {\n                    return@computeIfAbsent true\n                }\n                clazz = clazz.superclass\n            }\n            return@computeIfAbsent false\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/connection/SingleAdjacent.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.connection\n\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.math.BlockPos\nimport java.util.*\n\nclass SingleAdjacent(private val parent: CoreRoutedPipe, val dir: EnumFacing, private val adjacentType: ConnectionType) : Adjacent {\n    override fun connectedPos(): Map<BlockPos, ConnectionType> = mapOf(parent.pos.offset(dir) to adjacentType)\n\n    override fun get(direction: EnumFacing): ConnectionType? = adjacentType.takeIf { dir == direction }\n\n    override fun optionalGet(direction: EnumFacing): Optional<ConnectionType> {\n        return if (dir == direction) {\n            Optional.of(adjacentType)\n        } else {\n            Optional.empty()\n        }\n    }\n\n    override fun neighbors(): Map<NeighborTileEntity<TileEntity>, ConnectionType> =\n        parent.world.getTileEntity(parent.pos.offset(dir))\n            ?.let { mapOf(LPNeighborTileEntity(it, dir) to adjacentType) }\n            ?: emptyMap()\n\n    override fun inventories(): List<NeighborTileEntity<TileEntity>> =\n        if (adjacentType.isItem()) {\n            listOfNotNull(parent.world.getTileEntity(parent.pos.offset(dir))?.let { tile ->\n                LPNeighborTileEntity(tile, dir).takeIf { it.canHandleItems() }\n            })\n        } else emptyList()\n\n    override fun fluidTanks(): List<NeighborTileEntity<TileEntity>> =\n        if (adjacentType.isFluid()) {\n            listOfNotNull(parent.world.getTileEntity(parent.pos.offset(dir))?.let { tile ->\n                LPNeighborTileEntity(tile, dir).takeIf { it.canHandleFluids() }\n            })\n        } else emptyList()\n\n    override fun toString(): String = \"SingleAdjacent(${dir.name2}: $adjacentType)\"\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/BaseGuiContainer.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.guidebook.MouseInteractable\nimport network.rs485.logisticspipes.gui.guidebook.Screen\nimport network.rs485.logisticspipes.gui.widget.FuzzyItemSlot\nimport network.rs485.logisticspipes.gui.widget.FuzzySelectionWidget\nimport network.rs485.logisticspipes.gui.widget.GhostSlot\nimport network.rs485.logisticspipes.gui.widget.Tooltipped\nimport network.rs485.logisticspipes.inventory.container.LPBaseContainer\nimport network.rs485.logisticspipes.util.IRectangle\nimport logisticspipes.modules.LogisticsModule\nimport logisticspipes.utils.gui.DummySlot\nimport mezz.jei.api.gui.IGhostIngredientHandler\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.gui.inventory.GuiContainer\nimport net.minecraft.client.renderer.GlStateManager\nimport net.minecraft.client.renderer.RenderHelper\nimport net.minecraft.inventory.ClickType\nimport net.minecraft.inventory.Slot\nimport kotlin.math.roundToInt\n\nabstract class BaseGuiContainer(\n    private val baseContainer: LPBaseContainer<LogisticsModule>,\n    val xOffset: Int = 0,\n    val yOffset: Int = 0,\n    private val widgetScreen: WidgetScreen,\n) : GuiContainer(baseContainer), Drawable by widgetScreen {\n\n    // TODO\n    // Make it so only the highest \"z\" widget can be drawn as hovered - hovered state should be managed by gui class.\n\n    open val fuzzySelector: FuzzySelectionWidget? = null\n\n    override fun initGui() {\n        widgetScreen.initGuiWidget(this@BaseGuiContainer, super<GuiContainer>.width, super<GuiContainer>.height)\n\n        // To use minecraft's slot and item rendering. Might remove later.\n        guiLeft = widgetScreen.widgetContainer.absoluteBody.roundedLeft\n        guiTop = widgetScreen.widgetContainer.absoluteBody.roundedTop\n\n        // Clear button and widget lists\n        buttonList.clear()\n        mc.player.openContainer = inventorySlots\n    }\n    /**\n     * Draw what is supposed to not be important to the gui and is behind everything else.\n     * Origin is top left corner of the minecraft window.\n     * @param mouseX mouse position on X axis.\n     * @param mouseY mouse position on Y axis.\n     * @param partialTicks time so animations don't have to depend on game ticks which can be unstable.\n     */\n    open fun drawBackgroundLayer(mouseX: Int, mouseY: Int, partialTicks: Float) {\n        drawDefaultBackground()\n        GuiDrawer.drawGuiContainerBackground(absoluteBody, guiLeft to guiTop, inventorySlots)\n    }\n\n    /**\n     * Draw the area in between the back and fore grounds, good place to draw buttons.\n     * Origin is the top left corner of the gui.\n     * @param mouseX mouse position on X axis.\n     * @param mouseY mouse position on Y axis.\n     * @param partialTicks time so animations don't have to depend on game ticks which can be unstable.\n     */\n    open fun drawFocalgroundLayer(mouseX: Float, mouseY: Float, partialTicks: Float) {}\n\n    /**\n     * Draw the top layer of the screen, it could be tooltips, items on slots or even titles and text.\n     * Origin is the top left corner of the gui.\n     * @param mouseX mouse position on X axis.\n     * @param mouseY mouse position on Y axis.\n     * @param partialTicks time so animations don't have to depend on game ticks which can be unstable.\n     */\n    open fun drawForegroundLayer(mouseX: Float, mouseY: Float, partialTicks: Float) {\n        widgetScreen.widgetContainer.draw(mouseX, mouseY, partialTicks, Screen.absoluteBody)\n        (widgetScreen.hoveredWidget as? Tooltipped)?.getTooltipText()?.takeIf { it.isNotEmpty() }?.also {\n            drawHoveringText(it, mouseX.roundToInt(), mouseY.roundToInt())\n        } ?: renderHoveredToolTip(mouseX.roundToInt(), mouseY.roundToInt())\n    }\n\n    // Call super and call all the normally used methods.\n    override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) {\n        super.drawScreen(mouseX, mouseY, partialTicks)\n        val floatMouseX: Float = mouseX.toFloat()\n        val floatMouseY: Float = mouseY.toFloat()\n        GlStateManager.pushMatrix()\n        GlStateManager.disableLighting()\n        GlStateManager.disableDepth()\n        drawFocalgroundLayer(floatMouseX, floatMouseY, partialTicks)\n        GlStateManager.translate(0.0f, 0.0f, 10.0f)\n        RenderHelper.disableStandardItemLighting()\n        widgetScreen.updateHoveredState(floatMouseX, floatMouseY)\n        drawForegroundLayer(floatMouseX, floatMouseY, partialTicks)\n        RenderHelper.disableStandardItemLighting()\n        fuzzySelector?.let { fuzzySelector ->\n            if (hoveredSlot == null && fuzzySelector.active && !fuzzySelector.isMouseHovering(\n                    floatMouseX,\n                    floatMouseY,\n                )\n            ) {\n                fuzzySelector.active = false\n                fuzzySelector.currentSlot = null\n            } else if (hoveredSlot != null && hoveredSlot != fuzzySelector.currentSlot && hoveredSlot is FuzzyItemSlot) {\n                val slot = hoveredSlot as FuzzyItemSlot\n                fuzzySelector.active = true\n                fuzzySelector.currentSlot = slot\n                fuzzySelector.setPos(guiLeft + slot.xPos, guiTop + slot.yPos + 17)\n            }\n            fuzzySelector.draw(floatMouseX, floatMouseY, partialTicks, Screen.screen)\n        }\n        RenderHelper.enableStandardItemLighting()\n        GlStateManager.enableLighting()\n        GlStateManager.enableDepth()\n        GlStateManager.popMatrix()\n    }\n\n    override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {\n        if (fuzzySelector?.mouseClicked(\n                mouseX = mouseX.toFloat(),\n                mouseY = mouseY.toFloat(),\n                mouseButton = mouseButton,\n            ) == true\n        ) {\n            return\n        }\n        val currentHovered = widgetScreen.hoveredWidget\n        if (currentHovered is MouseInteractable) {\n            if (currentHovered.mouseClicked(\n                    mouseX = mouseX.toFloat(),\n                    mouseY = mouseY.toFloat(),\n                    mouseButton = mouseButton,\n                )\n            ) {\n                currentHovered.playPressedSound(mc.soundHandler)\n            }\n        }\n        super.mouseClicked(mouseX, mouseY, mouseButton)\n    }\n\n    override fun handleMouseClick(slotIn: Slot?, slotId: Int, mouseButton: Int, type: ClickType) {\n        if (slotIn is DummySlot || slotIn is GhostSlot) {\n            inventorySlots.slotClick(slotId, mouseButton, type, mc.player)\n        } else if (type == ClickType.QUICK_MOVE && baseContainer.tryTransferSlotToGhostSlot(slotId)) {\n            // transfer to ghost slot succeeded\n        } else {\n            super.handleMouseClick(slotIn, slotId, mouseButton, type)\n        }\n    }\n\n    // Update screen size square when resolution changes.\n    override fun setWorldAndResolution(mc: Minecraft, width: Int, height: Int) {\n        super.setWorldAndResolution(mc, width, height)\n    }\n\n    // Redirect vanilla background method to drawBackgroundLayer()\n    override fun drawGuiContainerBackgroundLayer(partialTicks: Float, mouseX: Int, mouseY: Int) {\n        drawBackgroundLayer(mouseX, mouseY, partialTicks)\n    }\n\n    fun List<Drawable>.draw(mouseX: Float, mouseY: Float, partialTicks: Float, visibleArea: IRectangle) =\n        forEach {\n            it.draw(mouseX, mouseY, partialTicks, visibleArea)\n        }\n\n    /**\n     * Returns of JEI targets for ghost items and fluids to be placed on.\n     */\n    abstract fun <I> getFilterSlots(): MutableList<IGhostIngredientHandler.Target<I>>\n\n    /**\n     * Returns a list of rectangles that overflow from the main gui area, so that JEI can avoid it.\n     */\n    abstract fun getExtraGuiAreas(): List<IRectangle>\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/BaseGuiScreen.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport net.minecraft.client.gui.GuiScreen\n\nclass BaseGuiScreen(private val widgetScreen: WidgetScreen) : GuiScreen(), Drawable by widgetScreen {\n\n    override fun initGui() {\n        widgetScreen.initGuiWidget(this, widgetScreen.width, widgetScreen.height)\n\n        // Clear button and widget lists\n        buttonList.clear()\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/DslExtension.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport net.minecraft.inventory.Slot\n\nabstract class InventorySlotsBase : GuiComponent() {\n    var slots: List<Slot> = emptyList()\n}\n\nclass CustomSlots : InventorySlotsBase() {\n    var columns: Int = 1\n    var rows: Int = 1\n}\n\nfun ComponentContainer.customSlots(init: CustomSlots.() -> Unit) = initComponent(CustomSlots(), init)\n\nclass PlayerSlots : InventorySlotsBase()\n\nfun ComponentContainer.playerSlots(init: PlayerSlots.() -> Unit) = initComponent(PlayerSlots(), init)\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/GuiDrawer.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport network.rs485.logisticspipes.gui.font.LPFontRenderer\nimport network.rs485.logisticspipes.gui.guidebook.Screen\nimport network.rs485.logisticspipes.gui.guidebook.x\nimport network.rs485.logisticspipes.gui.guidebook.y\nimport network.rs485.logisticspipes.gui.widget.FuzzyItemSlot\nimport network.rs485.logisticspipes.util.FuzzyFlag\nimport network.rs485.logisticspipes.util.FuzzyUtil\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.Rectangle\nimport network.rs485.logisticspipes.util.math.BorderedRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport network.rs485.markdown.defaultDrawableState\nimport logisticspipes.LPConstants\nimport logisticspipes.utils.Color\nimport logisticspipes.utils.MinecraftColor\nimport org.lwjgl.opengl.GL11\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.gui.FontRenderer\nimport net.minecraft.client.renderer.BufferBuilder\nimport net.minecraft.client.renderer.GlStateManager\nimport net.minecraft.client.renderer.Tessellator\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats\nimport net.minecraft.client.renderer.vertex.VertexFormat\nimport net.minecraft.inventory.Container\nimport net.minecraft.inventory.Slot\nimport net.minecraft.util.ResourceLocation\nimport java.lang.Float.min\nimport kotlin.math.abs\n\n/**\n * Drawing methods to help with Guis\n */\nobject GuiDrawer {\n\n    private const val BORDER: Int = 4\n    private const val NORMAL_SLOT_SIZE = 18\n\n    private val guiAtlas = Texture(ResourceLocation(LPConstants.LP_MOD_ID, \"textures/gui/gui.png\"), 256)\n    private val guiNormalPatternTexture =\n        Texture(ResourceLocation(LPConstants.LP_MOD_ID, \"textures/gui/normal.png\"), 64)\n    private val guiLightPattern = Texture(ResourceLocation(LPConstants.LP_MOD_ID, \"textures/gui/light.png\"), 64)\n    private val guiHoveredPatternTexture = Texture(ResourceLocation(LPConstants.LP_MOD_ID, \"textures/gui/blue.png\"), 64)\n\n    private val guiDarkPatternTexture = Texture(ResourceLocation(LPConstants.LP_MOD_ID, \"textures/gui/dark.png\"), 64)\n\n    private var currentTexture: Texture = guiAtlas\n\n    // TODO update constructor params\n    private val guiBackgroundTexture = Rectangle(0, 96, 16, 16)\n    private val guiBlankTexture = Rectangle(2, 2, 2, 2)\n    private val slotNormalTexture = Rectangle(0, 112, 18, 18)\n    private val slotDiskTexture = Rectangle(18, 112, 36, 18)\n    private val slotProgrammerTexture = Rectangle(36, 112, 18, 18)\n    private val slotSmallTexture = Rectangle(54, 112, 8, 8)\n    private val slotBigTexture = Rectangle(0, 130, 26, 26)\n\n    private val guiGuidebookFrame = Rectangle(0, 0, 64, 64)\n    private val guiGuidebookSlider = Rectangle(96, 64, 16, 16)\n\n    private val buttonBorderTextureLight = Rectangle(0, 64, 8, 8)\n    private val buttonBorderTextureNormal = Rectangle(8, 64, 8, 8)\n    private val buttonBorderTextureDark = Rectangle(0, 72, 8, 8)\n    private val buttonBorderTextureHovered = Rectangle(8, 72, 8, 8)\n\n    private val tessellator: Tessellator get() = Tessellator.getInstance()\n    private val buffer: BufferBuilder get() = tessellator.buffer\n    private val textureManager = Minecraft.getMinecraft().renderEngine\n    private var isDrawing: Boolean = false\n\n    val lpFontRenderer: LPFontRenderer by lazy {\n        LPFontRenderer.get(\"ter-u12n\")\n    }\n    val mcFontRenderer: FontRenderer by lazy {\n        Minecraft.getMinecraft().fontRenderer\n    }\n\n    fun getFuzzyColor(fuzzyFlag: FuzzyFlag) = when (fuzzyFlag) {\n        FuzzyFlag.IGNORE_DAMAGE -> Color.FUZZY_IGNORE_DAMAGE_COLOR.value\n        FuzzyFlag.IGNORE_NBT -> Color.FUZZY_IGNORE_NBT_COLOR.value\n        FuzzyFlag.USE_ORE_DICT -> Color.FUZZY_ORE_DICT_COLOR.value\n        FuzzyFlag.USE_ORE_CATEGORY -> Color.FUZZY_ORE_CATEGORY_COLOR.value\n    }\n\n    /**\n     * Draws the default minecraft gui look matching the given rectangle and renders the\n     * inventory slots based on the point to match minecraft's guiTop and guiLeft variables\n     * which might not match the rectangle's position.\n     * @param guiArea rectangle representing the background panel.\n     * @param topLeft point defining the origin of the slots.\n     * @param container container with slots to draw.\n     */\n\n    fun drawGuiContainerBackground(guiArea: IRectangle, topLeft: Pair<Int, Int>, container: Container) {\n        setTexture(guiAtlas)\n        start()\n        putGuiBackgroundBase(guiArea)\n        putContainerSlots(topLeft, container)\n        finish()\n    }\n\n    /**\n     * Draws the default minecraft gui look in the given rectangle area.\n     * @param guiArea rectangle representing the background panel.\n     */\n    fun drawGuiBackground(guiArea: IRectangle) {\n        setTexture(guiAtlas)\n        start()\n        putGuiBackgroundBase(guiArea)\n        finish()\n    }\n\n    // Container specific buffer code\n\n    private fun putGuiBackgroundBase(guiArea: IRectangle) {\n        val borderedGuiQuads = BorderedRectangle(guiArea, BORDER).quads\n        val borderedTexQuads = BorderedRectangle(guiBackgroundTexture, BORDER).quads\n        for ((i, quad) in borderedGuiQuads.withIndex()) {\n            putTexturedQuad(quad, borderedTexQuads[i], -1)\n        }\n    }\n\n    private fun putContainerSlots(offset: Pair<Int, Int>, container: Container) {\n        for (slot in container.inventorySlots) {\n            when (slot) {\n                is FuzzyItemSlot -> putFuzzySlot(slot, offset)\n                else -> putNormalSlot(slot, offset)\n            }\n        }\n    }\n\n    private fun putFuzzySlot(slot: FuzzyItemSlot, offset: Pair<Int, Int>) {\n        putNormalSlot(slot, offset)\n        val slotTopLeft = slot.xPos + offset.x to slot.yPos + offset.y\n        val flags = slot.flagGetter.invoke()\n        slot.usedFlags.filter { flag -> FuzzyUtil.get(flags, flag) }.forEach { flag: FuzzyFlag ->\n            val color = getFuzzyColor(flag)\n            when (flag) {\n                FuzzyFlag.IGNORE_DAMAGE -> {\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y - 1f),\n                        size = 9f,\n                        color = color,\n                        vertical = false,\n                    )\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y - 1f),\n                        size = 9f,\n                        color = color,\n                        vertical = true,\n                    )\n                }\n\n                FuzzyFlag.IGNORE_NBT -> {\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y + 16f),\n                        size = 9f,\n                        color = color,\n                        vertical = false,\n                    )\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y + 16f),\n                        size = -8f,\n                        color = color,\n                        vertical = true,\n                    )\n                }\n\n                FuzzyFlag.USE_ORE_DICT -> {\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y - 1f),\n                        size = 9f,\n                        color = color,\n                        vertical = false,\n                    )\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y - 1f),\n                        size = 9f,\n                        color = color,\n                        vertical = true,\n                    )\n                }\n\n                FuzzyFlag.USE_ORE_CATEGORY -> {\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y - 1f),\n                        size = 9f,\n                        color = color,\n                        vertical = false,\n                    )\n                    putLine(\n                        from = (slotTopLeft.x - 1f to slotTopLeft.y - 1f),\n                        size = 9f,\n                        color = color,\n                        vertical = true,\n                    )\n                }\n            }\n\n        }\n    }\n\n    private fun putNormalSlot(slot: Slot, offset: Pair<Int, Int>) {\n        putTexturedQuad(\n            MutableRectangle(\n                slot.xPos + offset.x,\n                slot.yPos + offset.y,\n                NORMAL_SLOT_SIZE,\n                NORMAL_SLOT_SIZE,\n            ).translate(-1),\n            slotNormalTexture,\n            MinecraftColor.WHITE.colorCode,\n        )\n    }\n\n    // Button specific draw code\n\n    fun drawGuiTexturedRect(rect: IRectangle, text: IRectangle, blend: Boolean, color: Int) {\n        if (blend) {\n            GlStateManager.enableBlend()\n            GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)\n        } else {\n            GlStateManager.disableBlend()\n        }\n        setTexture(guiAtlas)\n        start()\n        putTexturedQuad(rect, text, color)\n        finish()\n        if (blend) GlStateManager.disableBlend()\n    }\n\n    fun drawBorderedTile(\n        rect: IRectangle,\n        hovered: Boolean,\n        enabled: Boolean,\n        light: Boolean,\n        thickerBottomBorder: Boolean,\n    ) {\n        GlStateManager.enableBlend()\n        GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)\n        GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f)\n\n        val border = 2\n\n        val bottomBorder = if (thickerBottomBorder) border + 1 else border\n\n        val (buttonBackgroundTexture, buttonBorderTexture) = when {\n            !enabled -> {\n                guiDarkPatternTexture to buttonBorderTextureDark\n            }\n\n            hovered -> {\n                guiHoveredPatternTexture to buttonBorderTextureHovered\n            }\n\n            light -> {\n                guiLightPattern to buttonBorderTextureLight\n            }\n\n            else -> {\n                guiNormalPatternTexture to buttonBorderTextureNormal\n            }\n        }\n\n        setTexture(buttonBackgroundTexture)\n        start()\n        putScaledTexturedQuad(rect, 0f to 0f, -1)\n        finish()\n\n        setTexture(guiAtlas)\n        start()\n        val borderedGuiQuads = BorderedRectangle(rect, border, border, bottomBorder, border).borderQuads\n        val borderedTexQuads = BorderedRectangle(buttonBorderTexture, border, border, border, border).borderQuads\n        for ((i, quad) in borderedGuiQuads.withIndex()) {\n            putTexturedQuad(quad, borderedTexQuads[i], -1)\n        }\n        finish()\n\n        GlStateManager.disableBlend()\n    }\n\n    fun drawGuideBookFrame(rect: IRectangle, slider: IRectangle) {\n        GlStateManager.enableBlend()\n        GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)\n        GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f)\n\n        val borderedGui = BorderedRectangle(rect, 24)\n        val borderedGuiTexQuads = BorderedRectangle(guiGuidebookFrame, 24).borderQuads\n        val borderedSlider = BorderedRectangle(slider, 1, 0, 1, 0).quads.filter { it.width > 0.5 && it.height > 0.5 }\n        val borderedSliderTexQuads =\n            BorderedRectangle(guiGuidebookSlider, 1, 0, 1, 0).quads.filter { it.width > 0.5 && it.height > 0.5 }\n\n        setTexture(guiAtlas)\n        start()\n        for ((i, quad) in (borderedGui.borderQuads + borderedSlider).withIndex()) {\n            putTexturedQuad(quad, (borderedGuiTexQuads + borderedSliderTexQuads)[i], -1)\n        }\n        finish()\n\n        GlStateManager.disableBlend()\n    }\n\n    /**\n     * Draws a stylized tooltip at the specified position, and clamps to the edges (to be tested).\n     * @param text  text to be displayed in the tooltip;\n     * @param x     x position at the center of the tooltip, in case no clamping needs to be done;\n     * @param y     y position of the top of the tooltip;\n     * @param z     z position of the tooltip.\n     */\n    fun drawTextTooltip(\n        text: List<String>,\n        x: Int,\n        y: Int,\n        z: Float,\n        horizontalAlign: HorizontalAlignment,\n        verticalAlign: VerticalAlignment,\n    ) {\n        if (text.isEmpty() || text.all { it.isBlank() }) return\n\n        val border = 4\n        val horizontalPadding = 2\n        val verticalPadding = 1\n\n        // Calculate tooltip size\n        val outerArea = MutableRectangle(\n            width = (text.maxOfOrNull { lpFontRenderer.getStringWidth(it) } ?: 0) + 2 * (border + horizontalPadding),\n            height = (text.size * lpFontRenderer.getFontHeight()) + 2 * (verticalPadding + border),\n        )\n\n        // Align tooltip accordingly\n        outerArea.setPos(\n            when (horizontalAlign) {\n                HorizontalAlignment.CENTER -> x - outerArea.roundedWidth / 2\n                HorizontalAlignment.LEFT -> x\n                HorizontalAlignment.RIGHT -> x - outerArea.roundedWidth\n            },\n            when (verticalAlign) {\n                VerticalAlignment.CENTER -> y - outerArea.roundedHeight / 2\n                VerticalAlignment.TOP -> y\n                VerticalAlignment.BOTTOM -> y - outerArea.roundedHeight\n            },\n        )\n\n        // Constrain position to available screen space\n        if (outerArea.x0 < 0) outerArea.translate(translateX = -outerArea.x0)\n        if (outerArea.x1 > Screen.absoluteBody.roundedWidth) outerArea.translate(translateX = Screen.absoluteBody.roundedWidth - outerArea.x1)\n        if (outerArea.y0 < 0) outerArea.translate(translateY = -outerArea.y0)\n        if (outerArea.y1 > Screen.absoluteBody.roundedHeight) outerArea.translate(translateY = Screen.absoluteBody.roundedHeight - outerArea.y1)\n\n\n        // Define required quads and texture quads.\n        val borderedTooltipQuads = BorderedRectangle(\n            outerArea,\n            border,\n        ).quads\n        val borderedTexQuads = BorderedRectangle(\n            Rectangle(112, 32, 16, 16),\n            border,\n        ).quads\n\n        GlStateManager.translate(0.0f, 0.0f, z)\n        GlStateManager.enableAlpha()\n\n        // Draw background\n        setTexture(guiAtlas)\n        start()\n        for ((i, quad) in borderedTooltipQuads.withIndex()) {\n            putTexturedQuad(quad, borderedTexQuads[i], -1)\n        }\n        finish()\n\n        val textX = outerArea.roundedX + border + horizontalPadding\n        val textY = outerArea.roundedY + border + verticalPadding\n\n        // Draw text\n        text.fold(textY) { yOffset, line ->\n            lpFontRenderer.drawString(\n                line,\n                textX.toFloat(),\n                yOffset.toFloat(),\n                defaultDrawableState.color,\n                defaultDrawableState.format,\n                1.0f,\n            )\n        }\n        GlStateManager.translate(0.0f, 0.0f, -z)\n    }\n\n    fun drawGuideBookBackground(rect: IRectangle) {\n        val borderedGui = BorderedRectangle(rect, 24)\n        setTexture(guiDarkPatternTexture)\n        start()\n        putScaledTexturedQuad(borderedGui.inner.translate(-8).grow(16), 0f to 0f, -1)\n        finish()\n    }\n\n    fun drawSliderButton(body: IRectangle, texture: IRectangle) {\n        setTexture(guiAtlas)\n\n        val quads = BorderedRectangle(\n            MutableRectangle.fromRectangle(body).apply {\n                grow(4, 0)\n                translate(-2, 0)\n            },\n            2,\n        )\n        val textures = BorderedRectangle(\n            MutableRectangle.fromRectangle(texture).apply {\n                grow(4, 0)\n                translate(-2, 0)\n            },\n            2,\n        )\n\n        start()\n        putTexturedQuad(quads.top, textures.top, -1)\n        putRepeatingTexturedQuad(quads.inner, textures.inner, -1)\n        putTexturedQuad(quads.bottom, textures.bottom, -1)\n        finish()\n    }\n\n    // Text specific draw code\n\n    fun drawCenteredString(text: String, x: Int, y: Int, color: Int, shadow: Boolean) {\n        val xOffset = mcFontRenderer.getStringWidth(text) / 2\n        mcFontRenderer.drawString(text, x.toFloat() - xOffset, y.toFloat(), color, shadow)\n    }\n\n    // Untextured draw code\n\n\n    fun drawInteractionIndicator(mouseX: Float, mouseY: Float) {\n        GlStateManager.disableTexture2D()\n        GlStateManager.translate(0.0f, 0.0f, 100f)\n        start(DefaultVertexFormats.POSITION_COLOR)\n        putQuad(\n            Rectangle(mouseX + 4f to mouseY - 5f, mouseX + 5f to mouseY - 2f),\n            MinecraftColor.WHITE.colorCode,\n        )\n        putQuad(\n            Rectangle(mouseX + 3f to mouseY - 4f, mouseX + 6f to mouseY - 3f),\n            MinecraftColor.WHITE.colorCode,\n        )\n        finish()\n        GlStateManager.enableTexture2D()\n        GlStateManager.translate(0.0f, 0.0f, -100f)\n    }\n\n    fun drawRect(area: IRectangle, color: Int) {\n        GlStateManager.disableTexture2D()\n        GlStateManager.disableAlpha()\n        start(DefaultVertexFormats.POSITION_COLOR)\n        putQuad(area, color)\n        finish()\n        GlStateManager.enableAlpha()\n        GlStateManager.enableTexture2D()\n    }\n\n    fun drawHorizontalGradientRect(area: IRectangle, colorLeft: Int, colorRight: Int) {\n        drawGradientQuad(area, colorRight, colorLeft, colorLeft, colorRight)\n    }\n\n    fun drawVerticalGradientRect(area: IRectangle, colorTop: Int, colorBottom: Int) {\n        drawGradientQuad(area, colorTop, colorTop, colorBottom, colorBottom)\n    }\n\n    fun drawLine(start: Pair<Float, Float>, finish: Pair<Float, Float>, color: Int, thickness: Float) {\n        GlStateManager.disableTexture2D()\n        GlStateManager.disableAlpha()\n        start(DefaultVertexFormats.POSITION_COLOR)\n        putLine(start, finish, color, thickness)\n        finish()\n        GlStateManager.enableAlpha()\n        GlStateManager.enableTexture2D()\n    }\n\n    fun drawOutlineRect(rect: IRectangle, color: Int) {\n        GlStateManager.disableTexture2D()\n        GlStateManager.disableAlpha()\n        start(DefaultVertexFormats.POSITION_COLOR)\n        putOutlineQuad(rect, color)\n        finish()\n        GlStateManager.enableAlpha()\n        GlStateManager.enableTexture2D()\n    }\n\n    private fun drawGradientQuad(\n        area: IRectangle,\n        colorTopRight: Int,\n        colorTopLeft: Int,\n        colorBottomLeft: Int,\n        colorBottomRight: Int,\n    ) {\n        GlStateManager.disableTexture2D()\n        GlStateManager.enableBlend()\n        GlStateManager.disableAlpha()\n        GlStateManager.tryBlendFuncSeparate(\n            GlStateManager.SourceFactor.SRC_ALPHA,\n            GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA,\n            GlStateManager.SourceFactor.ONE,\n            GlStateManager.DestFactor.ZERO,\n        )\n        GlStateManager.shadeModel(GL11.GL_SMOOTH)\n        start(DefaultVertexFormats.POSITION_COLOR)\n        buffer.pos(area.topRight).rgba(colorTopRight).endVertex()\n        buffer.pos(area.topLeft).rgba(colorTopLeft).endVertex()\n        buffer.pos(area.bottomLeft).rgba(colorBottomRight).endVertex()\n        buffer.pos(area.bottomRight).rgba(colorBottomLeft).endVertex()\n        finish()\n        GlStateManager.shadeModel(GL11.GL_FLAT)\n        GlStateManager.disableBlend()\n        GlStateManager.enableAlpha()\n        GlStateManager.enableTexture2D()\n    }\n\n    // Buffer specific code\n\n    private fun putRepeatingTexturedQuad(rect: IRectangle, texture: IRectangle, color: Int) {\n        val tile = MutableRectangle(\n            x = rect.left,\n            y = rect.top,\n            _width = min(rect.width, texture.width),\n            _height = min(rect.height, texture.height),\n        )\n        for (x in 0 until rect.roundedWidth step tile.roundedWidth) {\n            for (y in 0 until rect.roundedHeight step tile.roundedHeight) {\n                putScaledTexturedQuad(\n                    rect = if (rect.contains(tile)) {\n                        tile\n                    } else {\n                        rect.overlap(tile)\n                    },\n                    texture = texture.topLeft,\n                    color = color,\n                )\n                tile.translate(0f, tile.height)\n            }\n            tile.setPos(newX = tile.left, newY = rect.top)\n            tile.translate(tile.width, 0f)\n        }\n    }\n\n    private fun putScaledTexturedQuad(rect: IRectangle, texture: Pair<Float, Float>, color: Int) {\n        putTexturedQuad(rect, Rectangle(texture.first, texture.second, rect.width, rect.height), color)\n    }\n\n    private fun putTexturedQuad(rect: IRectangle, texture: IRectangle, color: Int) {\n        if (buffer.vertexFormat == DefaultVertexFormats.POSITION_TEX_COLOR) {\n            val scaledUV = texture.scaled(currentTexture.factor)\n            buffer.pos(rect.topRight).tex(scaledUV.topRight).rgba(color).endVertex()\n            buffer.pos(rect.topLeft).tex(scaledUV.topLeft).rgba(color).endVertex()\n            buffer.pos(rect.bottomLeft).tex(scaledUV.bottomLeft).rgba(color).endVertex()\n            buffer.pos(rect.bottomRight).tex(scaledUV.bottomRight).rgba(color).endVertex()\n        }\n    }\n\n    private fun putLine(\n        from: Pair<Float, Float>,\n        to: Pair<Float, Float>,\n        color: Int,\n        thickness: Float = 1.0f,\n        vertical: Boolean = false,\n    ) {\n        if (!vertical) {\n            putQuad(Rectangle(from, to.first to to.second + thickness), color)\n        } else {\n            putQuad(Rectangle(from, to.first + thickness to to.second), color)\n        }\n    }\n\n    private fun putLine(from: Pair<Float, Float>, size: Float, color: Int, thickness: Float = 1.0f, vertical: Boolean) {\n        var newFrom = from\n        var newSize = size\n        if (size == 0f) {\n            return\n        } else if (size < 0f) {\n            if (vertical) {\n                newFrom = newFrom.x to newFrom.y + newSize\n                newSize = abs(newSize)\n            }\n        }\n        putLine(\n            from = newFrom,\n            to = (if (!vertical) newFrom.x + newSize else newFrom.x) to (if (!vertical) newFrom.y else newFrom.y + newSize),\n            color = color,\n            thickness = thickness,\n            vertical = vertical,\n        )\n    }\n\n\n    private fun putOutlineQuad(rect: IRectangle, color: Int, thickness: Float = 1.0f) {\n        putLine(rect.topLeft, rect.topRight, color, thickness)\n        putLine(rect.bottomLeft, rect.bottomRight, color, thickness)\n        putLine(rect.topLeft, rect.bottomLeft, color, thickness, vertical = true)\n        putLine(rect.topRight, rect.bottomRight, color, thickness, vertical = true)\n    }\n\n    private fun putQuad(rect: IRectangle, color: Int) {\n        if (buffer.vertexFormat == DefaultVertexFormats.POSITION_TEX_COLOR) {\n            putTexturedQuad(rect, guiBlankTexture, color)\n        } else if (buffer.vertexFormat == DefaultVertexFormats.POSITION_COLOR) {\n            buffer.pos(rect.topRight).rgba(color).endVertex()\n            buffer.pos(rect.topLeft).rgba(color).endVertex()\n            buffer.pos(rect.bottomLeft).rgba(color).endVertex()\n            buffer.pos(rect.bottomRight).rgba(color).endVertex()\n        }\n    }\n\n    /**\n     * Starts the BufferBuilder if it was not started already.\n     */\n    private fun start(vertexFormats: VertexFormat = DefaultVertexFormats.POSITION_TEX_COLOR) {\n        if (!isDrawing) {\n            buffer.begin(GL11.GL_QUADS, vertexFormats)\n            isDrawing = true\n        }\n    }\n\n    /**\n     * Draws the buffered quads if the buffer is currently open.\n     */\n    private fun finish() {\n        if (isDrawing) {\n            tessellator.draw()\n            isDrawing = false\n        }\n    }\n\n    /**\n     * Binds another texture keeping track of it's size\n     * @param texture texture to be bound.\n     */\n    private fun setTexture(texture: Texture) {\n        currentTexture = texture\n        textureManager.bindTexture(currentTexture.resource)\n    }\n\n    /**\n     * Cleanly splits the integer into the 4 rgba components and applies those to the BufferBuilder\n     * Uses BufferBuilder.color(I,I,I,I) because BufferBuilder.color(F,F,F,F) will just multiply the floats back into integers.\n     * @param color rgba color to be used\n     * @return the buffer itself.\n     */\n    private fun BufferBuilder.rgba(color: Int): BufferBuilder {\n        val a = (color shr 24 and 255)\n        val r = (color shr 16 and 255)\n        val g = (color shr 8 and 255)\n        val b = (color and 255)\n        return this.color(r, g, b, a)\n    }\n\n    /**\n     * Takes in a Float pair to insert texture coordinates onto the draw buffer\n     * Uses BufferBuilder.tex(D,D)\n     * @param point coordinate on the texture (scaled from 0-1)\n     * @return the buffer itself.\n     */\n    private fun BufferBuilder.tex(point: Pair<Float, Float>): BufferBuilder =\n        tex(point.first.toDouble(), point.second.toDouble())\n\n    /**\n     * Takes in a Float pair to insert screen coordinates onto the draw buffer\n     * Uses BufferBuilder.pos(D,D)\n     * @param point coordinate to be inserted in the buffer.\n     * @return the buffer itself.\n     */\n    private fun BufferBuilder.pos(point: Pair<Float, Float>): BufferBuilder =\n        pos(point.first.toDouble(), point.second.toDouble(), 0.0)\n}\n\nprivate class Texture(val resource: ResourceLocation, size: Int) {\n    val factor: Float = 1.0f / size\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/GuiRenderer.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.widget.*\n\nobject GuiRenderer : WidgetRenderer<WidgetContainer> {\n\n    private fun createWidget(container: WidgetContainer, component: GuiComponent): LPGuiWidget? = when (component) {\n        is PropertyLabel<*, *> -> LabelWidget(\n            parent = container,\n            width = component.width,\n            xPosition = component.horizontalAlignment,\n            yPosition = component.verticalAlignment,\n            xSize = component.horizontalSize,\n            margin = component.margin,\n            text = component.text,\n            textColor = component.textColor,\n            textAlignment = component.textAlignment,\n            extendable = component.extendable,\n            backgroundColor = component.backgroundColor,\n        ).apply {\n            component.onPropertyUpdate { newText ->\n                updateText(newText)\n            }\n        }\n\n        is PropertyButton<*, *> -> TextButton(\n            parent = container,\n            xPosition = component.horizontalAlignment,\n            yPosition = component.verticalAlignment,\n            xSize = Size.GROW,\n            ySize = Size.FIXED,\n            margin = component.margin,\n            text = component.text,\n            enabled = component.enabled,\n            onClickAction = {\n                component.action.invoke()\n                return@TextButton true\n            },\n        ).apply {\n            component.onPropertyUpdate { newText ->\n                text = newText\n            }\n        }\n\n        is Label -> LabelWidget(\n            parent = container,\n            width = component.width,\n            xPosition = component.horizontalAlignment,\n            yPosition = component.verticalAlignment,\n            xSize = component.horizontalSize,\n            margin = component.margin,\n            text = component.text,\n            textColor = component.textColor,\n            textAlignment = component.textAlignment,\n            extendable = component.extendable,\n            backgroundColor = component.backgroundColor,\n        )\n\n        is Button -> TextButton(\n            parent = container,\n            xPosition = component.horizontalAlignment,\n            yPosition = component.verticalAlignment,\n            xSize = Size.GROW,\n            ySize = Size.FIXED,\n            margin = component.margin,\n            text = component.text,\n            enabled = component.enabled,\n            onClickAction = {\n                // FIXME: filter mouse button\n                component.action.invoke()\n                return@TextButton true\n            },\n        )\n\n        is CustomSlots -> SlotGroup(\n            parent = container,\n            xPosition = component.horizontalAlignment,\n            yPosition = component.verticalAlignment,\n            margin = component.margin,\n            slots = component.slots,\n            columns = component.columns,\n            rows = component.rows,\n        )\n\n        is PlayerSlots -> PlayerInventorySlotGroup(\n            parent = container,\n            xPosition = component.horizontalAlignment,\n            yPosition = component.verticalAlignment,\n            margin = component.margin,\n            slots = component.slots,\n        )\n\n        is ComponentContainer -> createContainer(\n            container = component,\n            parent = container,\n        )\n\n        else -> println(\"[GuiRenderer.createWidget] Ignoring $component\").let { null }\n    }\n\n    private fun createContainer(\n        container: ComponentContainer,\n        parent: Drawable? = null,\n    ): WidgetContainer {\n        val list = mutableListOf<LPGuiWidget>()\n        val result = when (container) {\n            is HContainer -> HorizontalWidgetContainer(list, parent, container.margin, container.gap)\n            is VContainer -> VerticalWidgetContainer(list, parent, container.margin, container.gap)\n            is OptionalComponent -> {\n                if (container.vertical) {\n                    VerticalWidgetContainer(list, parent, container.margin, container.gap)\n                } else {\n                    HorizontalWidgetContainer(list, parent, container.margin, container.gap)\n                }\n            }\n\n            else -> throw IllegalArgumentException(\"\")\n        }\n        container.children.forEach { child ->\n            createWidget(result, child)?.also { list.add(it) }\n        }\n        return result\n    }\n\n    override fun render(componentContainer: ComponentContainer): WidgetContainer =\n        createContainer(componentContainer)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/WidgetContainer.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport logisticspipes.LogisticsPipes\nimport network.rs485.logisticspipes.gui.guidebook.*\nimport network.rs485.logisticspipes.gui.widget.LPGuiWidget\nimport network.rs485.logisticspipes.util.IRectangle\n\nabstract class WidgetContainer(\n    val children: List<LPGuiWidget>,\n    override var parent: Drawable? = null,\n    margin: Margin? = null,\n    var gap: Int,\n) : MouseHoverable, LPGuiWidget(\n    parent = parent ?: Screen,\n    xPosition = HorizontalAlignment.LEFT,\n    yPosition = VerticalAlignment.TOP,\n    xSize = Size.GROW,\n    ySize = Size.GROW,\n    margin = margin ?: Margin.NONE,\n) {\n\n    override fun <T : Drawable> createChild(childGetter: () -> T): T {\n        if (LogisticsPipes.isDEBUG()) {\n            LogisticsPipes.log.warn(\"createChild called on WidgetContainer, but WidgetContainer does not support lazy child creation\")\n            Throwable().printStackTrace()\n        }\n        return childGetter()\n    }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        //LPGuiDrawer.drawOutlineRect(MutableRectangle.fromRectangle(absoluteBody).grow(-1), MinecraftColor.CYAN.colorCode)\n        children.forEach {\n            it.draw(mouseX = mouseX, mouseY = mouseY, delta = delta, visibleArea = visibleArea)\n        }\n    }\n\n    /**\n     * This method will place the children in their final positions.\n     * The container's size should be defined before running this.\n     * @return the width and height of the container.\n     */\n    abstract fun placeChildren(): Pair<Int, Int>\n\n    fun getHovered(mouseX: Float, mouseY: Float): MouseHoverable? {\n        for (child in children) {\n            if (child is WidgetContainer) {\n                child.getHovered(mouseX, mouseY)?.let {\n                    return it\n                }\n            } else if (child is MouseHoverable && child.isMouseHovering(mouseX, mouseY)) {\n                return child\n            }\n        }\n        return null\n    }\n\n}\n\nclass HorizontalWidgetContainer(\n    children: List<LPGuiWidget>,\n    parent: Drawable? = null,\n    margin: Margin? = null,\n    gap: Int,\n) : WidgetContainer(\n    children = children,\n    parent = parent,\n    margin = margin,\n    gap = gap\n) {\n\n    override val maxWidth: Int = Int.MAX_VALUE\n    override val maxHeight: Int = Int.MAX_VALUE\n\n    override fun initWidget() {\n        setSize(minWidth, minHeight)\n        children.forEach { it.initWidget() }\n    }\n\n    private fun growChildren() {\n        val canGrow = children.filter { it.xSize == Size.GROW || it.ySize == Size.GROW }\n        canGrow.forEach {\n            if (it.xSize == Size.GROW) {\n                it.setSize(it.width + (width - minWidth) / canGrow.count(), it.height)\n            }\n            if (it.ySize == Size.GROW) {\n                it.setSize(newHeight = height - it.margin.vertical)\n            }\n        }\n    }\n\n    override fun placeChildren(): Pair<Int, Int> {\n        growChildren()\n        var xOffset = 0\n        for (child in children) {\n            xOffset += if (child is WidgetContainer) {\n                child.setPos(xOffset + child.margin.left, 0)\n                child.placeChildren().x + margin.horizontal + gap\n            } else {\n                child.setPos(\n                    xOffset + child.margin.left,\n                    when (child.yPosition) {\n                        VerticalAlignment.TOP -> 0\n                        VerticalAlignment.BOTTOM -> height - child.height\n                        VerticalAlignment.CENTER -> (height - child.height) / 2\n                    }\n                ).x + child.margin.horizontal + gap\n            }\n        }\n        return width to height\n    }\n\n    override val minWidth: Int\n        get() = children.sumOf { drawable ->\n            drawable.minWidth + drawable.margin.horizontal + gap\n        } - gap\n\n    override val minHeight: Int\n        get() = (children.maxOfOrNull { drawable ->\n            drawable.minHeight\n        } ?: 0)\n}\n\nclass VerticalWidgetContainer(\n    children: List<LPGuiWidget>,\n    parent: Drawable? = null,\n    margin: Margin? = null,\n    gap: Int,\n) : WidgetContainer(\n    children = children,\n    parent = parent,\n    margin = margin,\n    gap = gap\n) {\n\n    override val maxWidth: Int = Int.MAX_VALUE\n    override val maxHeight: Int = Int.MAX_VALUE\n\n    override fun initWidget() {\n        setSize(minWidth, minHeight)\n        children.forEach { it.initWidget() }\n    }\n\n    private fun growChildren() {\n        val canGrow = children.filter { it.xSize == Size.GROW || it.ySize == Size.GROW }\n        canGrow.forEach {\n            if (it.xSize == Size.GROW) {\n                it.setSize(newWidth = width)\n            }\n            if (it.ySize == Size.GROW) {\n                it.setSize(newHeight = it.height + (height - minHeight) / canGrow.count())\n            }\n        }\n    }\n\n    override fun placeChildren(): Pair<Int, Int> {\n        growChildren()\n        var yOffset = 0\n        for (child in children) {\n            yOffset += if (child is WidgetContainer) {\n                child.setPos(0, yOffset + child.margin.top)\n                child.placeChildren().y + child.margin.vertical + gap\n            } else {\n                child.setPos(\n                    when (child.xPosition) {\n                        HorizontalAlignment.LEFT -> 0\n                        HorizontalAlignment.RIGHT -> width - child.width\n                        HorizontalAlignment.CENTER -> (width - child.width) / 2\n                    },\n                    yOffset + child.margin.top\n                ).y + child.margin.vertical + gap\n            }\n        }\n        return width to height\n    }\n\n    override val minWidth: Int\n        get() = (children.maxOfOrNull { drawable ->\n            drawable.minWidth\n        } ?: 0)\n    override val minHeight: Int\n        get() = children.sumOf { drawable ->\n            drawable.minHeight + drawable.margin.vertical + gap\n        } - gap\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/WidgetScreen.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui\n\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.guidebook.MouseHoverable\nimport network.rs485.logisticspipes.gui.guidebook.Screen\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\nabstract class WidgetScreen : Drawable {\n\n    private val widgets: ComponentContainer by lazy { constructWidgetContainer() }\n\n    final override var parent: Drawable? = Screen\n    override val relativeBody: MutableRectangle = MutableRectangle()\n    var hoveredWidget: MouseHoverable? = null\n        private set\n\n    var widgetContainer: WidgetContainer = VerticalWidgetContainer(emptyList(), parent, Margin.DEFAULT, 0)\n        private set\n\n    protected abstract fun constructWidgetContainer(): ComponentContainer\n\n    fun initGuiWidget(parent: Drawable, width: Int, height: Int, xOffset: Int = 0, yOffset: Int = 0) {\n        // In case the screen size has changed.\n        Screen.relativeBody.setSize(width, height)\n\n        // Create gui widgets from dls components.\n        widgetContainer = GuiRenderer.render(widgets).also {\n            it.parent = parent\n        }\n\n        // Set position back to 0 before placing children to respect minecraft's gui translation.\n        widgetContainer.relativeBody.resetPos()\n\n        // Initialize every widget and place it relative to its parent.\n        widgetContainer.apply {\n            initWidget()\n            placeChildren()\n        }\n\n        // Set size of the main container to the minimum necessary size to fit all children.\n        widgetContainer.relativeBody.setSize(\n            widgetContainer.minWidth,\n            widgetContainer.minHeight,\n        ).translate(\n            widgetContainer.margin.left,\n            widgetContainer.margin.top,\n        )\n\n        // initialize our relativeBody\n        relativeBody.resetPos()\n        // Set the root body of the gui based on the size of the first container\n        // and taking into account it's margin.\n        relativeBody.setSizeFromRectangle(\n            widgetContainer.relativeBody.copy().grow(\n                widgetContainer.margin.horizontal,\n                widgetContainer.margin.vertical,\n            ),\n        )\n\n        // Center gui with possible offsets\n        relativeBody.setPos(\n            newX = (Screen.xCenter - relativeBody.width / 2) + xOffset,\n            newY = (Screen.yCenter - relativeBody.height / 2) + yOffset,\n        )\n    }\n\n    fun getHovered(mouseX: Float, mouseY: Float): MouseHoverable? =\n        widgetContainer.getHovered(mouseX, mouseY)\n\n    fun updateHoveredState(mouseX: Float, mouseY: Float) {\n        hoveredWidget = getHovered(mouseX, mouseY)\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/font/BDF.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.font\n\ndata class BDF(override val glyphs: Map<Char, IGlyph>, override val defaultChar: Char, override val width: Int, override val height: Int, override val offsetX: Int, override var offsetY: Int) : IFont {}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/font/FontParser.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.font\n\nimport logisticspipes.LogisticsPipes\nimport net.minecraft.client.Minecraft\nimport net.minecraft.util.ResourceLocation\nimport java.io.IOException\nimport java.util.*\n\nobject FontParser {\n\n    fun read(resourceLocation: ResourceLocation): BDF? {\n        return try {\n            read(Minecraft.getMinecraft().resourceManager.getResource(resourceLocation).inputStream.bufferedReader().use { it.readLines() })\n        } catch (e: IOException) {\n            LogisticsPipes.log.error(\"Font ${resourceLocation.path} not found, and will not be rendered.\", e)\n            null\n        }\n    }\n\n    fun read(lines: List<String>): BDF {\n        val parser = LineParser()\n        lines.asSequence().filter { it.isNotBlank() }.withIndex().forEach { (index, line) -> parser.line(index, line) }\n        return BDF(\n            glyphs = parser.glyphs,\n            defaultChar = parser.defaultChar,\n            width = parser.gWidth,\n            height = parser.gHeight,\n            offsetX = parser.gOffsetX,\n            offsetY = parser.gOffsetY,\n        )\n    }\n\n    private class LineParser {\n        var state: State.IState = State.Font.Start\n\n        var chars = 0 // Used to know how many chars are supposed to be on the file\n        var gWidth = 0   //\n        var gHeight = 0  // Used to store the global bounding box of the font\n        var gOffsetX = 0 // This serves as fallback values in case some value is missing in an individual char\n        var gOffsetY = 0 //\n        var defaultChar: Char = '?'\n\n        lateinit var currentGlyph: Glyph // Used to keep define the current Glyph and later add to the Glyph map\n        var glyphs: Map<Char, IGlyph> = emptyMap() // Aforementioned Glyph map\n\n        var currentByte = 0 // Used to keep track of how many bits were read.\n\n\n        fun line(index: Int, line: String) = when (state) {\n            State.Font.Start -> handleFontStart(index, line)\n            State.Font.Definition -> handleFontDefinition(index, line)\n            State.Char.Pre -> handleCharPre(index, line)\n            State.Char.Definition -> handleCharDefinition(index, line)\n            State.Char.Bitmap -> handleCharBitmap(index, line)\n            State.Font.End -> throw FontParserSyntaxException(state, index, \"There must be nothing in the lines following 'ENDFONT'\")\n            else -> Unit\n        }\n\n        private fun handleCharBitmap(index: Int, line: String) {\n            val tokens = line.split(\" \")\n            when (val head = tokens.first()) {\n                \"ENDCHAR\" -> {\n                    state = State.Char.Pre\n                    if (currentByte != currentGlyph.height) throw throw FontParserSyntaxException(state, index, \"Current Glyph is missing some Bytes, last byte index is $currentByte, expected: ${currentGlyph.height};\")\n                    glyphs = glyphs + (currentGlyph.charPoint to currentGlyph)\n                }\n                else -> {\n                    val wordlen = head.length * 4 - 1\n                    val data = head.toInt(16)\n                    for (i in 0 until currentGlyph.width) {\n                        currentGlyph.bitmap[i + currentByte * currentGlyph.width] = data ushr wordlen - i and 1 != 0\n                    }\n                    currentByte++\n                }\n            }\n        }\n\n        private fun handleCharDefinition(index: Int, line: String) {\n            val tokens = line.split(\" \")\n            when (val head = tokens.first()) {\n                \"SWIDTH\" -> Unit\n\n                \"ENCODING\" -> currentGlyph.charPoint = tokens[1].toInt().toChar()\n\n                \"DWIDTH\" -> currentGlyph.apply {\n                    dWidthX = tokens[1].toInt()\n                    dWidthY = tokens[2].toInt()\n                }\n\n                \"BBX\" -> currentGlyph.apply {\n                    width = tokens[1].toInt()\n                    height = tokens[2].toInt()\n                    offsetX = tokens[3].toInt()\n                    offsetY = tokens[4].toInt()\n                }\n\n                \"BITMAP\" -> {\n                    state = State.Char.Bitmap\n                    currentByte = 0\n                }\n\n                else -> if(LogisticsPipes.isDEBUG()) LogisticsPipes.log.warn(\"[@$state][Ln$index] Declaration start not recognized: $head\")\n            }\n        }\n\n        private fun handleCharPre(index: Int, line: String) {\n            val tokens = line.split(\" \")\n            when (val head = tokens.first()) {\n                \"STARTCHAR\" -> {\n                    state = State.Char.Definition\n                    currentGlyph = Glyph(tokens[1]).apply {\n                        width = gWidth\n                        height = gHeight\n                        offsetX = gOffsetX\n                        offsetY = gOffsetY\n                    }\n                }\n\n                \"ENDFONT\" -> {\n                    if (chars != glyphs.size) println(\"[@$state][Ln$index] Expected a different amount of Glyphs, got ${glyphs.size}, expected: $chars\")\n                    state = State.Font.End\n                }\n\n                else -> println(\"[@$state][Ln$index] Declaration start not recognized: $head\")\n            }\n        }\n\n        private fun handleFontDefinition(index: Int, line: String) {\n            val tokens = line.split(\" \")\n            when (val head = tokens.first()) {\n                \"SIZE\", \"STARTPROPERTIES\", \"FONT_ASCENT\", \"FONT_DESCENT\", \"CAP_HEIGHT\",\n                \"COPYRIGHT\", \"FACE_NAME\", \"FONT\", \"FONT_VERSION\", \"FOUNDRY\", \"FAMILY_NAME\",\n                \"NOTICE\", \"POINT_SIZE\", \"RESOLUTION_X\", \"RESOLUTION_Y\", \"SLANT\",\n                \"WEIGHT_NAME\", \"X_HEIGHT\", \"ENDPROPERTIES\", \"COMMENT\" -> Unit\n\n                \"DEFAULT_CHAR\" -> defaultChar = tokens[1].toInt().toChar()\n\n                \"FONTBOUNDINGBOX\" -> {\n                    gWidth = tokens[1].toInt()\n                    gHeight = tokens[2].toInt()\n                    gOffsetX = tokens[3].toInt()\n                    gOffsetY = tokens[4].toInt()\n                }\n\n                \"CHARS\" -> {\n                    chars = tokens[1].toInt()\n                    state = State.Char.Pre\n                }\n\n                else -> println(\"[@$state][Ln$index] Declaration start not recognized: $head\")\n            }\n        }\n\n        fun handleFontStart(index: Int, line: String) {\n            val (token, version) = line.split(\" \")\n            if (token != \"STARTFONT\") throw FontParserSyntaxException(state, index, \"Expected 'STARTFONT', found: '$token';\")\n            if (version != \"2.1\") throw FontParserSyntaxException(state, index, \"Only supported version currently is '2.1' , found: '$version';\")\n            state = State.Font.Definition\n        }\n\n    }\n\n    private class Glyph(override val name: String) : IGlyph {\n        override var charPoint: Char = '\\u0000'\n        override var dWidthX: Int = 0\n        override var dWidthY: Int = 0\n        override var width: Int = 0\n        override var height: Int = 0\n        override var offsetX: Int = 0\n        override var offsetY: Int = 0\n        override val bitmap: BitSet = BitSet()\n    }\n\n    //public data class BoundingBox(val width: Int, val height: Int, val xOffset: Int, val yOffset: Int)\n\n    enum class State {\n        ;\n\n        interface IState\n\n        enum class Font : IState {\n            Start, //      (Starts @BOF, Ends @STARTFONT) Expects the start of the font with th version \"2.1\"\n            Definition, // (Starts @STARTFONT, Ends @CHARS) Defines the global properties\n            End; //        (Starts @ENDFONT, Ends @EOF) Anything after will throw an exception\n        }\n\n        enum class Char : IState {\n            Pre, //        (Starts @CHARS, Ends @STARTCHAR) // Is set before every STARTCHAR\n            Definition, // (Starts @STARTCHAR, Ends @BITMAP) // Is set while setting the char's properties\n            Bitmap, //     (Starts @BITMAP, Ends @ENDCHAR) // Is set while setting the bitmap\n        }\n    }\n\n    class FontParserSyntaxException(val state: State.IState, val line: Int, val s: String)\n        : RuntimeException(\"Syntax exception on line $line (state $state): $s\")\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/font/FontWrapper.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.font\n\nimport logisticspipes.LogisticsPipes\nimport net.minecraft.client.renderer.GlStateManager\nimport net.minecraft.client.renderer.texture.TextureUtil\nimport org.lwjgl.opengl.GL11\nimport java.nio.ByteBuffer\nimport java.util.*\nimport kotlin.math.max\n\nprivate val buffer = ByteBuffer.allocateDirect(10000000).asIntBuffer()\n\nclass FontWrapper(private val font: IFont) {\n    val textures: List<Int> get() = textureIndex.keys.toList()\n\n    private var glyphPosX: Map<Char, Int> = emptyMap()\n    private var glyphPosY: Map<Char, Int> = emptyMap()\n    private var textureIndex: Map<Int, CharRange> = emptyMap()\n\n    val fontWidth: Int get() = font.width\n    val fontHeight: Int get() = font.height\n    val fontXOffset: Int get() = font.offsetX\n    val fontYOffset: Int get() = font.offsetY\n    val fontLineOffset: Int get() = fontHeight + fontYOffset\n\n    val defaultChar = font.defaultChar\n\n    private val maxTexSize = 512\n\n    init {\n        allocateTextures()\n    }\n\n    private fun setTexture(bitmap: BitSet, texture: Int, x: Int, y: Int, width: Int, height: Int) {\n        buffer.clear()\n        for (i in 0 until width * height)\n            buffer.put(if (bitmap[i]) -1 else 0)\n        buffer.flip()\n        GlStateManager.bindTexture(texture)\n        GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, x, y, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer)\n    }\n\n    // Creates the necessary textures with all the glyphs in them\n    private fun allocateTextures(): Pair<Int, Int> {\n        // TODO change character-texture map to texture-IntRange relation.\n        // TODO allocate texture and write it on the same pass.\n\n        fun generateTexture(): Int{\n            val texId = GL11.glGenTextures()\n            GlStateManager.bindTexture(texId)\n            TextureUtil.allocateTexture(texId, maxTexSize, maxTexSize)\n            LogisticsPipes.log.warn(\"Created new texture: $texId\")\n            return texId\n        }\n\n        var currentWidth = 0\n        var currentHeight = 0\n        var currentRowMaxHeight = 0\n        var currentMaxHeight = 0\n        var currentMinOffset = 0\n        var currentTexId = 0\n        val firstChar = font.glyphs.keys.first()\n        var startingChar = firstChar\n\n        fun startNewRow(){\n            // Use gathered row data to keep track of highest character.\n            currentMaxHeight = max(currentMaxHeight, currentRowMaxHeight)\n            // Use gathered row data to safely start the next row with interfering with the previous ones.\n            currentHeight += currentRowMaxHeight.powerOf2()\n            // Reset row variables.\n            currentWidth = 0\n            currentRowMaxHeight = 0\n        }\n\n        fun addTextureRange(character: Char) {\n            textureIndex = textureIndex + (currentTexId to (startingChar..character))\n            LogisticsPipes.log.warn(\"Finished texture, covering characters ${startingChar.toInt()}..${character.toInt()}\")\n        }\n\n        fun startNewTexture(character: Char) {\n            if(character != firstChar){\n                // Store texture-character relation\n                addTextureRange(character)\n            }\n            startingChar = character\n            // Reset texture positional characters.\n            currentWidth = 0\n            currentHeight = 0\n            // Create a new texture and get it's id.\n            currentTexId = generateTexture()\n        }\n\n        fun allocateGlyph(character: Char, glyph: IGlyph){\n            if(currentWidth + glyph.width > maxTexSize)\n                error(\"Cannot write a texture of width=${glyph.width} at x=$currentWidth\")\n            if(currentHeight + glyph.height > maxTexSize)\n                error(\"Cannot write a texture of height=${glyph.height} at y=$currentHeight\")\n            // Store the location of the glyph\n            glyphPosX = glyphPosX + (character to currentWidth)\n            glyphPosY = glyphPosY + (character to currentHeight)\n            // Draw the glyph into the texture\n            setTexture(glyph.bitmap, currentTexId, currentWidth, currentHeight, glyph.width, glyph.height)\n            // After allocation\n            currentWidth += glyph.width.powerOf2()\n            currentRowMaxHeight = maxOf(currentRowMaxHeight, glyph.height)\n            currentMinOffset = minOf(currentMinOffset, glyph.offsetY)\n        }\n\n        fun start() {\n            startNewTexture(font.glyphs.keys.first())\n        }\n\n        fun finish(){\n            val lastChar = font.glyphs.keys.last()\n            if(startingChar != lastChar){\n                addTextureRange(lastChar)\n            }\n        }\n\n        start()\n        for ((character, glyph) in font.glyphs) {\n            if(currentWidth + glyph.width > maxTexSize) startNewRow()\n            if(currentHeight + glyph.height > maxTexSize) startNewTexture(character)\n            allocateGlyph(character, glyph)\n        }\n        finish()\n\n        return currentMaxHeight to currentMinOffset\n    }\n\n    // Getter for the texture indexes, returns -1 if null.\n    fun getTextureIndex(c: Char): Int = textureIndex.entries.find { entry -> entry.value.contains(c) }?.key ?: -1\n\n    // Getter for width, return -1 if char not found.\n    fun getFontTextureSize(): Int = maxTexSize\n\n    // Getter for the glyph's X coordinate\n    fun getGlyphX(c: Char): Int = glyphPosX[c] ?: -1\n\n    // Getter for the glyph's Y coordinate\n    fun getGlyphY(c: Char): Int = glyphPosY[c] ?: -1\n\n    // Getter for the Glyph object\n    fun getGlyph(c: Char): IGlyph? = font.glyphs[c] ?: font.glyphs[font.defaultChar]\n\n    // No idea how this works, found on StackOverflow :P This returns the closest greatest power of 2.\n    private fun Int.powerOf2(): Int {\n        var n = this - 1\n        n = n or n.ushr(1)\n        n = n or n.ushr(2)\n        n = n or n.ushr(4)\n        n = n or n.ushr(8)\n        n = n or n.ushr(16)\n        return if (n < 0) 1 else if (n >= Integer.MAX_VALUE) Integer.MAX_VALUE else n + 1\n    }\n}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/font/IFont.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.font\n\nimport java.util.*\n\ninterface IFont {\n    val glyphs: Map<Char, IGlyph>\n    val defaultChar: Char\n    val width: Int\n    val height: Int\n    val offsetX: Int\n    var offsetY: Int\n}\n\ninterface IGlyph {\n    val name: String\n    val charPoint: Char\n    val dWidthX: Int\n    val dWidthY: Int\n    val width: Int\n    val height: Int\n    val offsetX: Int\n    var offsetY: Int\n    val bitmap: BitSet\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/font/LPFontRenderer.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.font\n\nimport network.rs485.grow.Coroutines\nimport network.rs485.logisticspipes.gui.guidebook.pos\nimport network.rs485.logisticspipes.gui.guidebook.tex\nimport network.rs485.logisticspipes.util.alpha\nimport network.rs485.logisticspipes.util.blue\nimport network.rs485.logisticspipes.util.green\nimport network.rs485.logisticspipes.util.red\nimport network.rs485.markdown.*\nimport logisticspipes.LPConstants\nimport logisticspipes.LogisticsPipes\nimport org.lwjgl.opengl.GL11\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.renderer.GlStateManager\nimport net.minecraft.client.renderer.Tessellator\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats\nimport net.minecraft.util.ResourceLocation\nimport java.io.IOException\nimport java.util.concurrent.ConcurrentHashMap\nimport kotlin.math.ceil\nimport kotlin.math.tan\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.launch\n\nclass LPFontRenderer(private val fontName: String) {\n    companion object Factory {\n        private val fontRenderersOfThisWorld = ConcurrentHashMap<String, LPFontRenderer>()\n        private val preloadFonts = listOf(\"ter-u12n\")\n        fun get(fontName: String): LPFontRenderer = fontRenderersOfThisWorld.getOrPut(fontName) { LPFontRenderer(fontName) }\n\n        @ExperimentalCoroutinesApi\n        fun asyncPreload() {\n            Coroutines.ioScope.launch {\n                preloadFonts.map {\n                    async {\n                        get(it).apply { ::fontPlain.get() }\n                    }\n                }.forEach { deferred ->\n                    deferred.invokeOnCompletion {\n                        if (it != null) {\n                            LogisticsPipes.log.error(\"Error while preloading fonts:\\n${it.stackTraceToString()}\")\n                        } else {\n                            val fontRenderer = deferred.getCompleted()\n                            LogisticsPipes.log.info(\"Preloaded font files: ${fontRenderer.fontName}\")\n                            Minecraft.getMinecraft().addScheduledTask {\n                                fontRenderer::wrapperPlain.get()\n                                LogisticsPipes.log.info(\"Created font textures for: ${fontRenderer.fontName}\")\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    private val fontPlain: IFont by lazy {\n        val initialTime = System.currentTimeMillis()\n        val fontResourcePlain = ResourceLocation(LPConstants.LP_MOD_ID, \"fonts/$fontName.bdf\")\n        FontParser.read(fontResourcePlain).also {  LogisticsPipes.log.info(\"Elapsed time parsing font: ${System.currentTimeMillis() - initialTime}ms\") } ?: throw IOException(\"Failed to load ${fontResourcePlain.path}, this is not tolerated.\")\n    }\n\n    private val wrapperPlain: FontWrapper by lazy {\n        val initialTime = System.currentTimeMillis()\n        FontWrapper(fontPlain).also {  LogisticsPipes.log.info(\"Elapsed time wrapping font: ${System.currentTimeMillis() - initialTime}ms\") }\n    }\n\n    private val shadowColor = 0xEE3C3F41.toInt()\n    var zLevel: Float = 5f\n\n    private val tessellator\n        get() = Tessellator.getInstance()\n\n    private fun start() {\n        GlStateManager.enableTexture2D()\n        GlStateManager.enableAlpha()\n        GlStateManager.enableBlend()\n        tessellator.buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR)\n    }\n\n    private fun startUntextured() {\n        GlStateManager.enableAlpha()\n        GlStateManager.enableBlend()\n        GlStateManager.disableTexture2D()\n        tessellator.buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR)\n    }\n\n    private fun render() {\n        tessellator.draw()\n        GlStateManager.disableAlpha()\n        GlStateManager.enableTexture2D()\n    }\n\n    /**\n     * Adds the given char at the given spot with the set color to the buffer and returns the xOffset for the next character.\n     *\n     * @param char    Character to be drawn\n     * @param x       X coordinate to start drawing the character (left boundary)\n     * @param y       Y coordinate to draw the character. (top of the line)\n     * @param color   ARGB color for the character to be drawn.\n     * @param wrapper This is passed so you could draw with different fonts in quick succession if needed.\n     * @param italics This defines if the characters will have a front lean to them.\n     * @param scale   This defines the size of the character to be drawn.\n     * @return the width of the drawn character\n     */\n    private fun putChar(char: Char, x: Float, y: Float, color: Int, wrapper: FontWrapper, italics: Boolean, scale: Float): Float {\n        val c: Char\n        // Find current the character's uv coordinates\n        val texIndex = when {\n            wrapper.getTextureIndex(char) != -1 -> {\n                // Get the texture atlas in which this character is represented. In case it is not defined check the default char.\n                c = char\n                wrapper.getTextureIndex(c)\n            }\n            wrapper.getTextureIndex(wrapper.defaultChar) != -1 -> {\n                // Get the texture atlas in which the default character is represented. In case it is not defined return 0 and don't add anything to the buffer.\n                c = wrapper.defaultChar\n                wrapper.getTextureIndex(wrapper.defaultChar)\n            }\n            else -> return 0f\n        }\n        // Width of the drawn character texture\n        val width = wrapper.getFontTextureSize()\n        // Height of the drawn character texture\n        val height = wrapper.getFontTextureSize()\n        // X position of the drawn character\n        val textureX = wrapper.getGlyphX(c)\n        // Y position of the drawn character\n        val textureY = wrapper.getGlyphY(c)\n        // The actual character glyph containing the actual character size and offsets.\n        val glyph = wrapper.getGlyph(c)\n        // In case any of the above fails to be set return 0 without adding anything to the buffer.\n        if (width == -1 || height == -1 || textureX == -1 || textureY == -1 || glyph == null) return 0f\n        // Scaled character dimensions.\n        val sWidth = (glyph.width * scale)\n        val sHeight = (glyph.height * scale)\n        // Character draw coordinate calculation based on scale\n        val x0 = x - (glyph.offsetX * scale)\n        val y1 = y + ((wrapper.fontLineOffset - glyph.offsetY) * scale)\n        val x1 = x0 + sWidth\n        val y0 = y1 - sHeight\n        // Texture coordinates calculation (0.0 - 1.0 depending on the position relative to the size of the full texture)\n        val u0 = textureX / width.toFloat()\n        val v0 = textureY / height.toFloat()\n        val u1 = (textureX + glyph.width) / width.toFloat()\n        val v1 = (textureY + glyph.height) / height.toFloat()\n        // The offset distance requires a tan calculation because merely adding a fixed value independent of the character's height would lead to slightly different angles for each character.\n        val italicsOffset = if (italics) glyph.height * tan(0.2181662f) else 0f\n        // Set the Magnification filter to Nearest neighbour to have sharp looking characters. (For some reason this wasn't working when applied in the start() method\n        GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST)\n        GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST)\n        // Bind the texture atlas where the current character is to GL11\n        GlStateManager.bindTexture(texIndex)\n        // Add character quad to buffer\n        tessellator.buffer.pos(x0 + italicsOffset, y0, zLevel).tex(u0, v0).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        tessellator.buffer.pos(x0, y1, zLevel).tex(u0, v1).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        tessellator.buffer.pos(x1, y1, zLevel).tex(u1, v1).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        tessellator.buffer.pos(x1 + italicsOffset, y0, zLevel).tex(u1, v0).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        // Return the final width of the character, including the spacing for the next character, while being scaled or bypassing scaling in case the scale is set to 1.\n        return glyph.dWidthX * scale\n    }\n\n    /**\n     * Extension of the previous draw(char), that just implements functionality for bold characters, depending on the available wrappers\n     */\n    private fun putChar(char: Char, x: Float, y: Float, color: Int, italics: Boolean, bold: Boolean, scale: Float): Float {\n        return if (bold) {\n            putChar(char, x + scale, y, color, wrapperPlain, italics, scale)\n            putChar(char, x, y, color, wrapperPlain, italics, scale) + scale\n        } else {\n            putChar(char, x, y, color, wrapperPlain, italics, scale)\n        }\n    }\n\n\n    /**\n     * Extension of the previous draw(char), that just implements functionality for shadowed characters.\n     */\n    private fun putChar(c: Char, x: Float, y: Float, color: Int, italics: Boolean, bold: Boolean, shadow: Boolean, scale: Float): Float {\n        if (shadow) {\n            putChar(c, x + scale, y + scale, shadowColor, italics, bold, scale)\n        }\n        return putChar(c, x, y, color, italics, bold, scale)\n    }\n\n    /**\n     * Draws the given string with all the possible parameters applied to it.\n     */\n    fun drawString(string: String, x: Float, y: Float, color: Int, format: Set<TextFormat>, scale: Float): Int =\n            drawString(string = string, x = x, y = y, color = color, italic = format.italic(), bold = format.bold(), shadow = format.shadow(), underline = format.underline(), strikethrough = format.strikethrough(), scale = scale)\n\n    /**\n     * Draws the given string with all the possible parameters applied to it.\n     */\n    private fun drawString(string: String, x: Float, y: Float, color: Int, italic: Boolean, bold: Boolean, shadow: Boolean, underline: Boolean, strikethrough: Boolean, scale: Float): Int {\n        start()\n        var stringSize = string.fold(0f) { currentX, char -> currentX + putChar(char, x + currentX, y, color, italic, bold, shadow, scale) }\n        // Lines...\n        render()\n        if(underline || strikethrough) {\n            startUntextured()\n            putOverlayFormatting(\n                x = x,\n                y = y,\n                width = stringSize,\n                color = color,\n                italic = italic,\n                underline = underline,\n                strikethrough = strikethrough,\n                shadow = shadow,\n                scale = scale\n            )\n            render()\n        }\n        if (italic) stringSize += scale\n        return ceil(stringSize).toInt()\n    }\n\n    /**\n     * Adds the formatting lines to the buffer, for underline and strikethrough.\n     */\n    private fun putOverlayFormatting(x: Float, y: Float, width: Float, color: Int, italic: Boolean, underline: Boolean, strikethrough: Boolean, shadow: Boolean, scale: Float) {\n        if (underline) {\n            val underlineY = (wrapperPlain.fontHeight - 1) * scale\n            if (shadow) putHorizontalLine(x = x + scale, y = y + underlineY + scale, width = width, thickness = scale, color = shadowColor, italics = italic)\n            putHorizontalLine(x = x, y = y + underlineY, width = width, thickness = scale, color = color, italics = italic)\n        }\n        if (strikethrough) {\n            val strikethroughY = ((wrapperPlain.fontHeight) / 2f) * scale\n            if (shadow) putHorizontalLine(x = x + scale, y = y + strikethroughY + scale, width = width, thickness = scale, color = shadowColor, italics = italic)\n            putHorizontalLine(x = x, y = y + strikethroughY, width = width, thickness = scale, color = color, italics = italic)\n        }\n    }\n\n    fun drawSpace(x: Float, y: Float, width: Int, color: Int, italic: Boolean, underline: Boolean, strikethrough: Boolean, shadow: Boolean, scale: Float): Int {\n        if (width > 0 && (underline || strikethrough)) {\n            startUntextured()\n            putOverlayFormatting(x = x, y = y, width = width.toFloat(), color = color, italic = italic, underline = underline, strikethrough = strikethrough, shadow = shadow, scale = scale)\n            render()\n        }\n        return width\n    }\n\n    fun drawCenteredString(string: String, x: Float, y: Float, color: Int, tags: Set<TextFormat>, scale: Float): Int {\n        return drawString(string, x - (getStringWidth(string, tags, scale) / 2f), y, color, tags, scale)\n    }\n\n    // It's not being rounded because it's supposed to be floored.\n    fun getFontHeight(scale: Float = 1f): Int = (wrapperPlain.fontHeight * scale).toInt()\n\n    private fun getCharWidth(char: Char, wrapper: FontWrapper, scale: Float): Float {\n        val glyph = wrapper.getGlyph(char) ?: return 0f\n        return glyph.dWidthX * scale\n    }\n\n    private fun getCharWidth(char: Char, bold: Boolean, scale: Float): Float {\n        return if (bold) {\n            getCharWidth(char, wrapperPlain, scale) + 1\n        } else {\n            getCharWidth(char, wrapperPlain, scale)\n        }\n    }\n\n    fun getStringWidth(string: String, italics: Boolean, bold: Boolean, scale: Float): Int {\n        val italicsOffset = if (italics) scale else 0f\n        return (string.fold(0.0) { currentX, char -> currentX + getCharWidth(char, bold, scale) } + italicsOffset).toInt()\n    }\n\n    fun getStringWidth(string: String, tags: Set<TextFormat>, scale: Float): Int {\n        return getStringWidth(string, tags.italic(), tags.bold(), scale)\n    }\n\n    fun getStringWidth(string: String): Int = getStringWidth(string = string, italics = false, bold = false, scale = 1f)\n\n    private fun putHorizontalLine(x: Float, y: Float, width: Float, thickness: Float, color: Int, italics: Boolean) {\n        val italicsOffset = if (italics) thickness else 0f\n        tessellator.buffer.pos(x, y, 5f).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        tessellator.buffer.pos(x, y + thickness, 5f).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        tessellator.buffer.pos(x + width + italicsOffset, y + thickness, 5f).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n        tessellator.buffer.pos(x + width + italicsOffset, y, 5f).color(color.red(), color.green(), color.blue(), color.alpha()).endVertex()\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/BookmarkManagingButton.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport net.minecraft.client.Minecraft\nimport network.rs485.logisticspipes.gui.HorizontalAlignment\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.gui.VerticalAlignment\nimport network.rs485.logisticspipes.util.Rectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport java.util.*\n\nval additionTexture = Rectangle(192, 0, 16, 16)\nval subtractionTexture = additionTexture.translated(additionTexture.width, 0.0f)\n\n/*\n* This button's position is set based on the right and bottom constraints\n*/\nclass BookmarkManagingButton(x: Int, y: Int, onClickAction: (ButtonState) -> Boolean, val additionStateUpdater: (() -> ButtonState)): LPGuiButton(2, x - additionTexture.roundedWidth, y - additionTexture.roundedHeight, additionTexture.roundedWidth, additionTexture.roundedHeight) {\n    private var buttonState: ButtonState = ButtonState.ADD\n    var onClickActionStated: (ButtonState) -> Boolean = onClickAction\n\n    override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int, partialTicks: Float) {\n        if (visible) {\n            hovered = isHovered(mouseX, mouseY)\n            val yOffset = getHoverState(hovered) * additionTexture.roundedHeight\n            GuiDrawer.drawGuiTexturedRect(body, (if (buttonState == ButtonState.ADD) additionTexture else subtractionTexture).translated(0, yOffset), true, MinecraftColor.WHITE.colorCode)\n        }\n    }\n\n    override fun drawButtonForegroundLayer(mouseX: Int, mouseY: Int) {\n        if (hovered && visible) {\n            drawTooltip(\n                    x = body.roundedLeft + body.roundedHeight / 2,\n                    y = body.roundedTop - 6,\n                    horizontalAlign = HorizontalAlignment.CENTER,\n                    verticalAlign = VerticalAlignment.BOTTOM\n            )\n        }\n   }\n\n    fun setX(newX: Int){\n        body.setPos(newX.toFloat(), body.y0)\n    }\n\n    fun updateState() {\n        buttonState = additionStateUpdater()\n        visible = buttonState != ButtonState.DISABLED\n    }\n\n    override fun getTooltipText(): String = when(buttonState){\n        ButtonState.ADD, ButtonState.REMOVE -> TextUtil.translate(\"misc.guide_book.bookmark_button.${buttonState.toString().lowercase(Locale.getDefault())}\")\n        ButtonState.DISABLED -> \"\"\n    }\n\n    override fun getHoverState(mouseOver: Boolean): Int = if(buttonState == ButtonState.DISABLED) 2 else if (hovered) 1 else 0\n\n    override fun click(mouseButton: Int) = onClickActionStated(buttonState)\n\n    enum class ButtonState {\n        ADD,\n        REMOVE,\n        DISABLED\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/Drawable.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.audio.PositionedSoundRecord\nimport net.minecraft.client.audio.SoundHandler\nimport net.minecraft.init.SoundEvents\nimport net.minecraft.util.SoundEvent\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.gui.guidebook.GuideBookConstants.DRAW_BODY_WIREFRAME\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.Rectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\ninterface MouseHoverable {\n    /**\n     * Check if mouse is over the current object.\n     * @param mouseX X position of the mouse (absolute, screen)\n     * @param mouseY Y position of the mouse (absolute, screen)\n     */\n    fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean = false\n}\n\ninterface MouseInteractable : MouseHoverable {\n\n    /**\n     * A mouse click event should run this.\n     * @param mouseX X position of the mouse (absolute, screen)\n     * @param mouseY Y position of the mouse (absolute, screen)\n     * @param mouseButton button of the mouse that was pressed.\n     * @return true, if click was handled\n     */\n    fun mouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int): Boolean = false\n\n    /**\n     * Mouse scroll event, run this.\n     * @param mouseX X position of the mouse (absolute, screen)\n     * @param mouseY Y position of the mouse (absolute, screen)\n     * @param scrollAmount how much the scroll wheel has turned since the last event.\n     */\n    fun mouseScrolled(mouseX: Float, mouseY: Float, scrollAmount: Float): Boolean = false\n\n    /**\n     * A mouse release event should run this.\n     * @param mouseX X position of the mouse (absolute, screen)\n     * @param mouseY Y position of the mouse (absolute, screen)\n     * @param mouseButton button of the mouse that was pressed.\n     */\n    fun mouseReleased(mouseX: Float, mouseY: Float, mouseButton: Int): Boolean = false\n\n    /**\n     * Always call this method when mouse clicked is successful.\n     * @param soundHandler minecraft's sound handler\n     */\n    fun playPressedSound(soundHandler: SoundHandler, sound: SoundEvent = SoundEvents.UI_BUTTON_CLICK) {\n        soundHandler.playSound(PositionedSoundRecord.getMasterRecord(sound, 1.0f))\n    }\n\n}\n\ninterface Drawable {\n    companion object {\n        /**\n         * Assigns the parent of all children to this.\n         */\n        fun <T : Drawable> List<Drawable>.createParent(parentGetter: () -> T) =\n            parentGetter().also { parentDrawable -> this.forEach { it.parent = parentDrawable } }\n    }\n\n    val relativeBody: MutableRectangle\n\n    var parent: Drawable?\n\n    /** Relative x position. */\n    val x: Float get() = relativeBody.x0\n\n    /** Relative y position. */\n    val y: Float get() = relativeBody.y0\n\n    /** Drawable's width. */\n    val width: Int get() = relativeBody.roundedWidth\n\n    /** Drawable's height */\n    val height: Int get() = relativeBody.roundedHeight\n\n    /** Absolute left position. */\n    val left: Float get() = (parent?.left ?: 0.0f) + x\n\n    /** Absolute right position. */\n    val right: Float get() = left + width\n\n    /** Absolute top position. */\n    val top: Float get() = (parent?.top ?: 0.0f) + y\n\n    /** Absolute bottom position. */\n    val bottom: Float get() = top + height\n\n    /** Absolute drawable body. */\n    val absoluteBody: Rectangle\n        get() = Rectangle(left to top, right to bottom)\n\n    /**\n     * Assigns a new child's parent to this.\n     */\n    fun <T : Drawable> createChild(childGetter: () -> T) = childGetter().also { it.parent = this }\n\n    /**\n     * This is just like the normal draw functions for minecraft Gui classes but with the added current Y offset.\n     * @param mouseX        X position of the mouse (absolute, screen)\n     * @param mouseY        Y position of the mouse (absolute, screen)\n     * @param delta         Timing floating value\n     * @param visibleArea   used to avoid draw calls on non-visible children\n     */\n    fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        if (DRAW_BODY_WIREFRAME) {\n            val visibleAbsoluteBody = MutableRectangle.fromRectangle(visibleArea)\n                .translate(0, -5)\n                .grow(0, 10)\n                .overlap(absoluteBody)\n            GuiDrawer.drawOutlineRect(visibleAbsoluteBody, MinecraftColor.WHITE.colorCode)\n        }\n    }\n\n    /**\n     * This function is responsible for updating the Drawable's position by giving it the exact X and Y where it\n     * should start and returning the offset for the next element.\n     * @param x         the X position of the Drawable.\n     * @param y         the Y position of the Drawable.\n     * @return returns width and height of the drawable.\n     */\n    fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        return relativeBody.roundedWidth to relativeBody.roundedHeight\n    }\n\n    /**\n     * This function is responsible to check if the current Drawable is within the vertical constrains of the given area.\n     * @param visibleArea   Desired visible area to check\n     * @return true if within constraints false otherwise.\n     */\n    fun visible(visibleArea: IRectangle): Boolean {\n        return visibleArea.intersects(absoluteBody)\n    }\n}\n\nobject Screen : Drawable {\n    val screen: MutableRectangle\n        get() = MutableRectangle(\n            width = Minecraft.getMinecraft().currentScreen?.width ?: Minecraft.getMinecraft().displayWidth,\n            height = Minecraft.getMinecraft().currentScreen?.height ?: Minecraft.getMinecraft().displayHeight,\n        )\n\n    override val relativeBody: MutableRectangle\n        get() = screen\n\n    override var parent: Drawable? = null\n\n    val xCenter: Int\n        get() = relativeBody.roundedWidth / 2\n    val yCenter: Int\n        get() = relativeBody.roundedHeight / 2\n}\n\nval <T> Pair<T, T>.x: T\n    get() = first\n\nval <T> Pair<T, T>.y: T\n    get() = second\n\nfun Pair<Int, Int>.plus() = Pair(this.x + x, this.y + y)\n\nfun Pair<Int, Int>.minus() = Pair(this.x - x, this.y - y)\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableHeaderParagraph.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\n/**\n * Header token, stores all the tokens that are apart of the header.\n */\nclass DrawableHeaderParagraph(private val words: List<DrawableWord>) : DrawableParagraph() {\n    override val relativeBody: MutableRectangle = MutableRectangle()\n    override var parent: Drawable? = null\n\n    private val horizontalLine = createChild { DrawableHorizontalLine(1) }\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean =\n        words.find { it.isMouseHovering(mouseX, mouseY) }?.inBookMouseClicked(mouseX, mouseY, mouseButton, guideActionListener)\n            ?: false\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        drawChildren(mouseX, mouseY, delta, visibleArea)\n    }\n\n    override fun drawChildren(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        (this.words + horizontalLine).filter { it.visible(visibleArea) }.forEach { it.draw(mouseX, mouseY, delta, visibleArea) }\n    }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? =\n        (words + horizontalLine).firstOrNull { it.isMouseHovering(mouseX, mouseY) }\n\n    override fun setChildrenPos(): Int {\n        var currentY = splitAndInitialize(words, 0, 0, width, true)\n        currentY += horizontalLine.setPos(0, currentY).y\n        return currentY\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableHorizontalLine.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\n/**\n * This draws a line with a given thickness that will span the entire width of the page, minus padding.\n */\n\nprivate const val horizontalPadding: Int = 3\n\nclass DrawableHorizontalLine(private val thickness: Int, private val padding: Int = 3, val color: Int = MinecraftColor.WHITE.colorCode) : DrawableParagraph() {\n    override val relativeBody: MutableRectangle = MutableRectangle()\n    override var parent: Drawable? = null\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y + padding)\n        relativeBody.setSize(parent!!.width - 2 * horizontalPadding, padding + thickness)\n        return super.setPos(x, y)\n    }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? = null\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        GuiDrawer.drawLine(absoluteBody.topLeft, absoluteBody.topRight, color, thickness.toFloat())\n    }\n}    \n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableImageParagraph.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.utils.MinecraftColor\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.renderer.BufferBuilder\nimport net.minecraft.client.renderer.GlStateManager\nimport net.minecraft.client.renderer.Tessellator\nimport net.minecraft.client.renderer.texture.PngSizeInfo\nimport net.minecraft.client.renderer.vertex.DefaultVertexFormats\nimport net.minecraft.util.ResourceLocation\nimport java.io.IOException\nimport kotlin.math.min\n\nclass DrawableImageParagraph(private val alternativeText: List<DrawableWord>, val image: DrawableImage) : DrawableParagraph() {\n    override val relativeBody = MutableRectangle()\n    override var parent: Drawable? = null\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        // This has to be done in two steps because setChildrenPos() depends on the width already being set.\n        relativeBody.setSize(parent!!.width, 0)\n        relativeBody.setSize(relativeBody.roundedWidth, setChildrenPos())\n        return relativeBody.roundedWidth to relativeBody.roundedHeight\n    }\n\n    override fun setChildrenPos(): Int {\n        var currentY = 0\n        currentY += if (image.broken) {\n            splitAndInitialize(alternativeText, 5, currentY, width - 10, false)\n        } else {\n            image.setPos(0, currentY).y\n        }\n        return currentY\n    }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? = if (image.broken) {\n        alternativeText.firstOrNull { it.isMouseHovering(mouseX, mouseY) }\n    } else {\n        null\n    }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        if (image.broken) {\n            super.draw(mouseX, mouseY, delta, visibleArea)\n            for (drawableWord in alternativeText.filter { it.visible(visibleArea) }) {\n                drawableWord.draw(mouseX, mouseY, delta, visibleArea)\n                GuiDrawer.drawOutlineRect(absoluteBody, MinecraftColor.WHITE.colorCode)\n            }\n        } else {\n            image.draw(mouseX, mouseY, delta, visibleArea)\n        }\n    }\n}\n\nclass DrawableImage(private var imageResource: ResourceLocation) : Drawable {\n\n    override var relativeBody: MutableRectangle = MutableRectangle()\n    override var parent: Drawable? = null\n\n    private var imageSize: PngSizeInfo? = try {\n        val resource = Minecraft.getMinecraft().resourceManager.getResource(imageResource)\n        PngSizeInfo.makeFromResource(resource)\n    } catch (e: IOException) {\n        LogisticsPipes.log.error(\"File not found: ${imageResource.path}\")\n        null\n    }\n    val broken: Boolean get() = imageSize == null\n\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        if (imageSize != null) {\n            drawImage(absoluteBody, visibleArea, imageResource)\n        } else {\n            GuiDrawer.drawOutlineRect(absoluteBody, MinecraftColor.WHITE.colorCode)\n        }\n    }\n\n    private fun putTexturedImage(\n        bufferBuilder: BufferBuilder,\n        x0: Float,\n        y0: Float,\n        x1: Float,\n        y1: Float,\n        uw: Int,\n        vh: Int,\n        u0: Int,\n        v0: Int,\n        u1: Int,\n        v1: Int,\n    ) {\n        val atlasWidthScale = 1 / uw.toDouble()\n        val atlasHeightScale = 1 / vh.toDouble()\n        val u0S = u0 * atlasWidthScale\n        val v0S = v0 * atlasHeightScale\n        val u1S = u1 * atlasWidthScale\n        val v1S = v1 * atlasHeightScale\n        bufferBuilder.pos(x0, y1, 0f).tex(u0S, v1S).endVertex()\n        bufferBuilder.pos(x1, y1, 0f).tex(u1S, v1S).endVertex()\n        bufferBuilder.pos(x1, y0, 0f).tex(u1S, v0S).endVertex()\n        bufferBuilder.pos(x0, y0, 0f).tex(u0S, v0S).endVertex()\n    }\n\n    fun drawImage(imageBody: IRectangle, visibleArea: IRectangle, image: ResourceLocation) {\n        val visibleImageBody = imageBody.overlap(visibleArea)\n        val xOffset = min(imageBody.x0 - visibleArea.x0, 0f)\n        val yOffset = min(imageBody.y0 - visibleArea.y0, 0f)\n        val visibleImageTexture = MutableRectangle.fromRectangle(visibleImageBody).setPos(xOffset, -yOffset)\n        GlStateManager.pushMatrix()\n        Minecraft.getMinecraft().textureManager.bindTexture(image)\n        GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f)\n        val tessellator = Tessellator.getInstance()\n        val bufferBuilder = tessellator.buffer\n        bufferBuilder.begin(7, DefaultVertexFormats.POSITION_TEX)\n        putTexturedImage(\n            bufferBuilder = bufferBuilder,\n            x0 = visibleImageBody.x0,\n            y0 = visibleImageBody.y0,\n            x1 = visibleImageBody.x1,\n            y1 = visibleImageBody.y1,\n            uw = imageBody.roundedWidth,\n            vh = imageBody.roundedHeight,\n            u0 = visibleImageTexture.roundedLeft,\n            v0 = visibleImageTexture.roundedTop,\n            u1 = visibleImageTexture.roundedRight,\n            v1 = visibleImageTexture.roundedBottom,\n        )\n        tessellator.draw()\n        GlStateManager.popMatrix()\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        if (imageSize != null) {\n            // Checks width of image to scale down to a size that fits on the page\n            relativeBody.setSize(imageSize!!.pngWidth, imageSize!!.pngHeight)\n            if (imageSize!!.pngWidth > parent!!.width) {\n                val downScaleFactor = parent!!.width.toFloat() / width\n                relativeBody.scale(downScaleFactor)\n            }\n        } else {\n            relativeBody.setSize(20, 20)\n        }\n        return super.setPos(x, y)\n    }\n\n}\n\nfun BufferBuilder.pos(x: Float, y: Float, z: Float): BufferBuilder = pos(x.toDouble(), y.toDouble(), z.toDouble())\n\nfun BufferBuilder.tex(u: Float, v: Float): BufferBuilder = tex(u.toDouble(), v.toDouble())\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableMenuParagraph.kt",
    "content": "/*\n * Copyright (c) 2020-2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020-2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.LPItems\nimport logisticspipes.utils.MinecraftColor\nimport logisticspipes.utils.item.ItemStackRenderer\nimport net.minecraft.item.Item\nimport net.minecraft.util.ResourceLocation\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.gui.widget.Tooltipped\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport network.rs485.markdown.TextFormat\nimport java.util.*\n\nprivate const val listEntryHeight = 24\nprivate const val tileSize = 40\nprivate const val tileSpacing = 5\n\n/**\n * Menu token, stores the key and the type of menu in a page.\n */\nclass DrawableMenuParagraph<T>(private val menuTitle: List<DrawableWord>, private val menuGroups: List<DrawableMenuGroup<T>>) :\n    DrawableParagraph() where T : Drawable, T : GuideBookMouseInteractable {\n    override val relativeBody = MutableRectangle()\n    override var parent: Drawable? = null\n\n    private val horizontalLine = createChild { DrawableHorizontalLine(1) }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        drawChildren(mouseX, mouseY, delta, visibleArea)\n    }\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean =\n        menuGroups.firstOrNull { it.isMouseHovering(mouseX, mouseY) }?.inBookMouseClicked(mouseX, mouseY, mouseButton, guideActionListener)\n            ?: false\n\n    override fun setChildrenPos(): Int {\n        var currentY = 1\n        currentY += splitAndInitialize(menuTitle, 0, currentY, width, false)\n        currentY += horizontalLine.setPos(0, currentY).y\n        currentY += 5\n        for (group in menuGroups) currentY += group.setPos(0, currentY).y\n        return currentY\n    }\n\n    override fun drawChildren(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        (menuTitle + horizontalLine + menuGroups).filter { it.visible(visibleArea) }.forEach { it.draw(mouseX, mouseY, delta, visibleArea) }\n    }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? =\n        (menuTitle + horizontalLine + menuGroups).firstOrNull { it.isMouseHovering(mouseX, mouseY) }?.let {\n            if (it is DrawableParagraph) {\n                return it.getHovered(mouseX, mouseY)\n            } else {\n                it\n            }\n        }\n}\n\nclass DrawableMenuGroup<T>(private val groupTitle: List<DrawableWord>, private val groupTiles: List<T>) :\n    DrawableParagraph() where T : Drawable, T : GuideBookMouseInteractable {\n    override val relativeBody = MutableRectangle()\n    override var parent: Drawable? = null\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        drawChildren(mouseX, mouseY, delta, visibleArea)\n    }\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean =\n        groupTiles.firstOrNull { it.isMouseHovering(mouseX, mouseY) }?.inBookMouseClicked(mouseX, mouseY, mouseButton, guideActionListener)\n            ?: false\n\n    override fun setChildrenPos(): Int {\n        var currentY = 0\n        var currentX = tileSpacing\n        currentY += splitAndInitialize(groupTitle, currentX, currentY, width, false)\n        for (tile in groupTiles) {\n            if (currentX + tile.width + tileSpacing > width) {\n                currentX = tileSpacing\n                currentY += tile.height + tileSpacing\n            }\n            tile.setPos(currentX, currentY)\n            currentX += tile.width + tileSpacing\n            if (tile == groupTiles.last()) currentY += tile.height + tileSpacing\n        }\n        return currentY\n    }\n\n    override fun drawChildren(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        (groupTitle + groupTiles).filter { it.visible(visibleArea) }.forEach { it.draw(mouseX, mouseY, delta, visibleArea) }\n    }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? =\n        (groupTitle + groupTiles).firstOrNull { it.isMouseHovering(mouseX, mouseY) }\n}\n\nclass DrawableMenuTile(private val linkedPage: String, private val pageName: String, private val icon: String) : Drawable, GuideBookMouseInteractable, Tooltipped {\n    private val iconScale = 1.5f\n    private val iconBody = MutableRectangle()\n\n    override val relativeBody = MutableRectangle()\n    override var parent: Drawable? = null\n\n    companion object {\n        val itemStackRenderer by lazy {\n            ItemStackRenderer(0, 0, 0f, true, false)\n        }\n    }\n\n    init {\n        relativeBody.setSize(tileSize, tileSize)\n        iconBody.setSize((16 * iconScale).toInt(), (16 * iconScale).toInt())\n        iconBody.setPos((tileSize - iconBody.width) / 2, (tileSize - iconBody.height) / 2)\n    }\n\n    override fun getTooltipText(): List<String> = listOf(pageName)\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean = absoluteBody.contains(mouseX, mouseY)\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean =\n        guideActionListener?.onMenuButtonClick(linkedPage) != null\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        val hovered = isMouseHovering(mouseX, mouseY)\n        GuiDrawer.drawBorderedTile(\n            rect = absoluteBody,\n            hovered = hovered,\n            enabled = true,\n            light = true,\n            thickerBottomBorder = false\n        )\n        if (hovered) {\n            GuiDrawer.drawInteractionIndicator(mouseX, mouseY)\n        }\n        val itemRect = iconBody.translated(absoluteBody)\n        if (visibleArea.intersects(itemRect)) {\n            val item = Item.REGISTRY.getObject(ResourceLocation(icon)) ?: LPItems.brokenItem\n            itemStackRenderer.renderItemInGui(itemRect.left, itemRect.top, item, 0.0f, iconScale)\n        }\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        return super.setPos(x, y)\n    }\n}\n\nclass DrawableMenuListEntry(private val linkedPage: String, private val pageName: String, private val icon: String) : Drawable, GuideBookMouseInteractable {\n    private val iconScale = 1.0f\n    private val iconSize = (16 * iconScale).toInt()\n    private val itemRect = MutableRectangle()\n    private val itemOffset = (listEntryHeight - iconSize) / 2\n\n    override val relativeBody = MutableRectangle()\n    override var parent: Drawable? = null\n\n    companion object {\n        val itemStackRenderer by lazy {\n            ItemStackRenderer(0, 0, 0f, true, false)\n        }\n    }\n\n    init {\n        relativeBody.setSize(4 * itemOffset + iconSize + GuiDrawer.lpFontRenderer.getStringWidth(pageName), listEntryHeight)\n        itemRect.setSize(iconSize, iconSize)\n    }\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean = absoluteBody.contains(mouseX, mouseY)\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean =\n        guideActionListener?.onMenuButtonClick(linkedPage) != null\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        val hovered = visibleArea.contains(mouseX, mouseY) && isMouseHovering(mouseX, mouseY)\n        GuiDrawer.drawBorderedTile(\n            rect = absoluteBody,\n            hovered = hovered,\n            enabled = true,\n            light = true,\n            thickerBottomBorder = false\n        )\n        itemRect.setPos(left + itemOffset, top + itemOffset)\n        if (itemRect.intersects(visibleArea)) {\n            val textColor: Int = if (!hovered) MinecraftColor.WHITE.colorCode else 0xffffffa0.toInt()\n            val textVerticalOffset = (height - GuiDrawer.lpFontRenderer.getFontHeight(1.0f)) / 2\n            GuiDrawer.lpFontRenderer.drawString(\n                string = pageName,\n                x = itemRect.right + itemOffset,\n                y = top + textVerticalOffset,\n                color = textColor,\n                format = EnumSet.of(TextFormat.Shadow),\n                scale = 1.0f\n            )\n            val item = Item.REGISTRY.getObject(ResourceLocation(icon)) ?: LPItems.brokenItem\n            itemStackRenderer.renderItemInGui(itemRect.left, itemRect.top, item, 0.0f, iconScale)\n        }\n        if (hovered) {\n            GuiDrawer.drawInteractionIndicator(mouseX, mouseY)\n        }\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        itemRect.setPos(left + itemOffset, top + itemOffset)\n        return super.setPos(x, y)\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawablePage.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\nprivate const val PAGE_VERTICAL_PADDING = 5\n\nclass DrawablePage(private val drawableParagraphs: List<DrawableParagraph>) : DrawableParagraph() {\n    override val relativeBody: MutableRectangle = MutableRectangle()\n    override var parent: Drawable? = null\n\n    fun setWidth(width: Int) = relativeBody.setSize(width, relativeBody.roundedHeight)\n\n    fun updateScrollPosition(visibleArea: IRectangle, progress: Float) {\n        relativeBody.setPos(relativeBody.x0, visibleArea.y0 - ((height - visibleArea.height) * progress))\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        relativeBody.setSize(relativeBody.roundedWidth, setChildrenPos())\n        return relativeBody.roundedWidth to relativeBody.roundedHeight\n    }\n\n    override fun setChildrenPos(): Int {\n        var currentY = PAGE_VERTICAL_PADDING\n        for (paragraph in drawableParagraphs) {\n            currentY += paragraph.setPos(0, currentY).y + PAGE_VERTICAL_PADDING\n        }\n        return currentY\n    }\n\n    override fun preRender(mouseX: Float, mouseY: Float, visibleArea: IRectangle) =\n        getVisibleParagraphs(visibleArea).forEach {\n            it.preRender(mouseX, mouseY, visibleArea)\n        }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) =\n        drawChildren(mouseX, mouseY, delta, visibleArea)\n\n    override fun drawChildren(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) =\n        getVisibleParagraphs(visibleArea).forEach { it.draw(mouseX, mouseY, delta, visibleArea) }\n\n    fun getVisibleParagraphs(visibleArea: IRectangle) =\n        drawableParagraphs.filter { it.visible(visibleArea) }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? =\n        drawableParagraphs.firstOrNull { it.isMouseHovering(mouseX, mouseY) }?.getHovered(mouseX, mouseY)\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawablePageFactory.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.gui.guidebook.Drawable.Companion.createParent\nimport network.rs485.logisticspipes.guidebook.BookContents\nimport network.rs485.logisticspipes.guidebook.PageInfoProvider\nimport network.rs485.logisticspipes.guidebook.toLocation\nimport network.rs485.markdown.*\nimport kotlin.math.min\n\nprivate typealias DrawableWordMap<T> = (List<DrawableWord>) -> T\nprivate typealias DrawableMenuEntryFactory<T> = (linkedPage: String, pageName: String, icon: String) -> T\n\nobject DrawablePageFactory {\n    /**\n     * Calculates the scale from level 1 (2.0), reducing 0.2 for each level with a minimum of 1.0.\n     */\n    private fun getScaleFromLevel(headerLevel: Int): Float = min(1.0f, 2.0f - ((headerLevel - 1) / 5.0f))\n\n    fun createDrawablePage(page: PageInfoProvider): DrawablePage =\n            createDrawableParagraphs(page).let { it.createParent { DrawablePage(it) } }\n\n    private fun getLinkGroup(linkGroups: MutableMap<Link, LinkGroup>, state: InlineDrawableState) = state.link?.let { link ->\n        linkGroups.getOrPut(link) { LinkGroup(link) }\n    }\n\n    private fun LinkGroup?.createChild(constructor: (linkGroup: LinkGroup?) -> DrawableWord): DrawableWord =\n            constructor(this).also { this?.addChild(it) }\n\n    private fun <T : DrawableParagraph> createDrawableParagraph(paragraphConstructor: DrawableWordMap<T>, elements: List<InlineElement>, scale: Float) =\n            defaultDrawableState.copy().let { state ->\n                val linkGroups = mutableMapOf<Link, LinkGroup>()\n                elements.mapNotNull { element ->\n                    element.changeDrawableState(state)\n                    when (element) {\n                        is Word -> getLinkGroup(linkGroups, state).createChild { DrawableWord(element.str, scale, state, it) }\n                        is Space -> getLinkGroup(linkGroups, state).createChild { DrawableSpace(scale, state, it) }\n                        Break -> DrawableBreak\n                        else -> null\n                    }\n                }\n            }.let { drawableWords ->\n                drawableWords.createParent { paragraphConstructor(drawableWords) }\n            }\n\n    private fun createDrawableParagraphs(page: PageInfoProvider): List<DrawableParagraph> =\n            page.paragraphs.map { paragraph ->\n                when (paragraph) {\n                    is RegularParagraph -> createDrawableParagraph(\n                            paragraphConstructor = ::DrawableRegularParagraph,\n                            elements = paragraph.elements,\n                            scale = 1.0f,\n                    )\n                    is HeaderParagraph -> createDrawableParagraph(\n                            paragraphConstructor = ::DrawableHeaderParagraph,\n                            elements = paragraph.elements,\n                            scale = getScaleFromLevel(paragraph.headerLevel),\n                    )\n                    is HorizontalLineParagraph -> DrawableHorizontalLine(2)\n                    is MenuParagraph -> {\n                        if (page.metadata.menu.containsKey(paragraph.link)) {\n                            createDrawableParagraph(\n                                    paragraphConstructor = { drawableMenuTitle ->\n                                        val factory = when (paragraph.type) {\n                                            MenuParagraphType.LIST -> ::DrawableMenuListEntry\n                                            MenuParagraphType.TILE -> ::DrawableMenuTile\n                                        }\n                                        createDrawableMenuParagraph(page, page.metadata.menu[paragraph.link]!!, drawableMenuTitle, factory)\n                                    },\n                                    elements = MarkdownParser.splitAndFormatWords(paragraph.description),\n                                    scale = getScaleFromLevel(3),\n                            )\n                        } else {\n                            createDrawableParagraph(\n                                    paragraphConstructor = ::DrawableRegularParagraph,\n                                    elements = MarkdownParser.splitSpacesAndWords(\"Menu `${paragraph.link}` not found\"),\n                                    scale = 1.0f,\n                            )\n                        }\n                    }\n                    is ImageParagraph -> createDrawableParagraph(\n                            paragraphConstructor = { drawableAlternativeText ->\n                                val imageResource = page.resolveResource(paragraph.imagePath)\n                                DrawableImageParagraph(drawableAlternativeText, DrawableImage(imageResource)).also { drawableImageParagraph ->\n                                    drawableImageParagraph.image.parent = drawableImageParagraph\n                                }\n                            },\n                            elements = MarkdownParser.splitAndFormatWords(paragraph.alternative),\n                            scale = 1.0f,\n                    )\n                }\n            }\n\n    private fun resolvePaths(page: PageInfoProvider, groupEntries: List<String>) =\n            groupEntries.map { loc -> page.resolveLocation(loc).toLocation(true) }\n\n    private fun <T> createDrawableMenuParagraph(\n            page: PageInfoProvider,\n            menuStructure: Map<String, List<String>>,\n            drawableMenuTitle: List<DrawableWord>,\n            drawableMenuEntryConstructor: DrawableMenuEntryFactory<T>,\n    ) where T : Drawable, T : GuideBookMouseInteractable = menuStructure.map { (groupTitle: String, groupEntries: List<String>) ->\n        createDrawableParagraph(\n                paragraphConstructor = { drawableGroupTitle ->\n                    createDrawableMenu(resolvePaths(page, groupEntries), drawableGroupTitle, drawableMenuEntryConstructor)\n                },\n                elements = MarkdownParser.splitAndFormatWords(groupTitle),\n                scale = getScaleFromLevel(6),\n        )\n    }.let { drawableMenuGroups ->\n        drawableMenuGroups.createParent { DrawableMenuParagraph(drawableMenuTitle, drawableMenuGroups) }\n    }\n\n    private fun <T> createDrawableMenu(\n            menuGroupEntries: List<String>,\n            drawableGroupTitle: List<DrawableWord>,\n            drawableMenuEntryConstructor: DrawableMenuEntryFactory<T>,\n    ) where T : Drawable, T : GuideBookMouseInteractable = menuGroupEntries\n            .map { path ->\n                BookContents.get(path).metadata.let { metadata ->\n                    drawableMenuEntryConstructor(path, metadata.title, metadata.icon)\n                }\n            }.let { drawableMenuTiles ->\n                drawableMenuTiles.createParent { DrawableMenuGroup(drawableGroupTitle, drawableMenuTiles) }\n            }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableParagraph.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.util.IRectangle\n\nabstract class DrawableParagraph : Drawable, GuideBookMouseInteractable {\n    private val preRenderCallbacks = mutableSetOf<(mouseX: Float, mouseY: Float, visibleArea: IRectangle) -> Unit>()\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        relativeBody.setSize(parent!!.width, 0)\n        relativeBody.setSize(relativeBody.roundedWidth, setChildrenPos())\n        return super.setPos(x, y)\n    }\n\n    /**\n     * This function is supposed to update the children's position by starting\n     * Y and X placement at 0 and iterating through the children while calculating their placement.\n     * This function is also responsible for updating the Paragraphs height as it directly\n     * depends on the placement of it's children.\n     * @return the height of all the Paragraph's children combined.\n     */\n    open fun setChildrenPos(): Int {\n        return relativeBody.roundedHeight\n    }\n\n    /**\n     * This function is responsible check if the mouse is over the object\n     * @param mouseX        X position of the mouse (absolute, screen)\n     * @param mouseY        Y position of the mouse (absolute, screen)\n     */\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean =\n        absoluteBody.contains(mouseX, mouseY)\n\n    open fun drawChildren(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {}\n\n    /**\n     * Registers a preRender callback to call on preRender.\n     */\n    fun registerPreRenderCallback(callable: (mouseX: Float, mouseY: Float, visibleArea: IRectangle) -> Unit) {\n        preRenderCallbacks.add(callable)\n    }\n\n    open fun preRender(mouseX: Float, mouseY: Float, visibleArea: IRectangle) =\n        preRenderCallbacks.forEach { function ->\n            function.invoke(mouseX, mouseY, visibleArea)\n        }\n\n    abstract fun getHovered(mouseX: Float, mouseY: Float): Drawable?\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableRegularParagraph.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\n/**\n * Stores groups of ITokenText tokens to more easily translate Tokens to Drawable elements\n */\nclass DrawableRegularParagraph(private val words: List<DrawableWord>) : DrawableParagraph() {\n    override val relativeBody: MutableRectangle = MutableRectangle()\n    override var parent: Drawable? = null\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        relativeBody.setSize(parent!!.width, setChildrenPos())\n        return super.setPos(x, y)\n    }\n\n    override fun setChildrenPos(): Int {\n        return splitAndInitialize(words, 0, 0, width, true)\n    }\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean =\n        words.find { it.isMouseHovering(mouseX, mouseY) }?.inBookMouseClicked(mouseX, mouseY, mouseButton, guideActionListener)\n            ?: false\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        drawChildren(mouseX, mouseY, delta, visibleArea)\n    }\n\n    override fun drawChildren(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        val lines = words.groupBy { it.top }.values\n        // Split by lines\n        for (line in lines) {\n            // Check if first (representative of the whole line) is visible, aka contained within the visible area.\n            if (line.first().visible(visibleArea)) {\n                for (drawable in line) {\n                    drawable.draw(mouseX, mouseY, delta, visibleArea)\n                }\n            }\n        }\n    }\n\n    override fun getHovered(mouseX: Float, mouseY: Float): Drawable? =\n        words.firstOrNull {\n            it.isMouseHovering(mouseX, mouseY)\n        }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/DrawableWord.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport network.rs485.markdown.*\nimport kotlin.math.floor\n\n/**\n * Normal Token that stores the text and the formatting tags of said text.\n */\nopen class DrawableWord(\n    private val str: String,\n    private val scale: Float,\n    state: InlineDrawableState,\n    protected val linkInteractable: LinkInteractable?,\n) : Drawable, GuideBookMouseInteractable {\n\n    final override val relativeBody: MutableRectangle = MutableRectangle()\n    override var parent: Drawable? = null\n        set(value) {\n            field = value\n            (value as? DrawableParagraph)?.run(::setupParent)\n        }\n    val format: Set<TextFormat> = state.format\n    val color: Int = state.color\n\n    init {\n        relativeBody.setSize(\n            newWidth = GuiDrawer.lpFontRenderer.getStringWidth(str, format.italic(), format.bold(), scale),\n            newHeight = GuiDrawer.lpFontRenderer.getFontHeight(scale),\n        )\n    }\n\n    private fun setupParent(drawableParagraph: DrawableParagraph) {\n        if (linkInteractable != null) drawableParagraph.registerPreRenderCallback(linkInteractable::updateState)\n    }\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?) =\n        linkInteractable?.inBookMouseClicked(mouseX, mouseY, mouseButton, guideActionListener) ?: super.mouseClicked(mouseX, mouseY, mouseButton)\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean =\n        absoluteBody.contains(mouseX, mouseY)\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        val hovering = linkInteractable?.isMouseHovering(mouseX, mouseY) ?: false\n        val updatedColor = linkInteractable?.updateColor(color) ?: color\n        val updatedFormat = linkInteractable?.updateFormat(format) ?: format\n        if (hovering) {\n            GuiDrawer.drawInteractionIndicator(mouseX, mouseY)\n        }\n        GuiDrawer.lpFontRenderer.drawString(string = str, x = left, y = top, color = updatedColor, format = updatedFormat, scale = scale)\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        relativeBody.setPos(x, y)\n        return super.setPos(x, y)\n    }\n\n    override fun toString(): String {\n        return \"\\\"$str\\\"\"\n    }\n}\n\n/**\n * Space object responsible for drawing the necessary formatting in between words.\n */\nclass DrawableSpace(\n    private val scale: Float,\n    state: InlineDrawableState,\n    linkInteractable: LinkInteractable?,\n) : DrawableWord(\" \", scale, state, linkInteractable) {\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        if (width > 0) {\n            linkInteractable?.isMouseHovering(mouseX, mouseY)\n            val updatedColor = linkInteractable?.updateColor(color) ?: color\n            val updatedFormat = linkInteractable?.updateFormat(format) ?: format\n            GuiDrawer.lpFontRenderer.drawSpace(\n                x = left,\n                y = top,\n                width = width,\n                color = updatedColor,\n                italic = updatedFormat.italic(),\n                underline = updatedFormat.underline(),\n                strikethrough = updatedFormat.strikethrough(),\n                shadow = updatedFormat.shadow(),\n                scale = scale,\n            )\n        }\n    }\n\n    fun setWidth(newWidth: Int) {\n        relativeBody.setSize(newWidth, relativeBody.roundedHeight)\n    }\n\n    fun resetWidth() {\n        setWidth(newWidth = GuiDrawer.lpFontRenderer.getStringWidth(\" \", format.italic(), format.bold(), scale))\n    }\n\n    override fun toString(): String {\n        return \"Space of size $width with formatting: $format.\"\n    }\n}\n\nobject DrawableBreak : DrawableWord(\"\", 1.0f, defaultDrawableState, null)\n\ninternal fun splitAndInitialize(drawables: List<DrawableWord>, x: Int, y: Int, maxWidth: Int, justify: Boolean): Int {\n    var currentHeight = 0\n    val splitLines = splitLines(drawables, maxWidth)\n\n    fun isLastLine(line: List<DrawableWord>) = line == splitLines.last()\n    fun hasBreak(line: List<DrawableWord>) = line.contains(DrawableBreak)\n\n    for (line in splitLines) {\n        currentHeight += if (!justify || isLastLine(line) || hasBreak(line)) {\n            initializeLine(line, x, y + currentHeight)\n        } else {\n            initializeJustifiedLine(line, x, y + currentHeight, maxWidth)\n        }\n    }\n    return currentHeight\n}\n\nprivate fun initializeJustifiedLine(line: List<DrawableWord>, x: Int, y: Int, maxWidth: Int): Int {\n    val spacesExceptIfLast = line.filterIsInstance<DrawableSpace>().filterNot { it == line.last() }\n    val spaceIfLast: DrawableSpace? = line.find { it is DrawableSpace && it == line.last() } as DrawableSpace?\n    val totalSpaceWidth = maxWidth - line.filterNot { it is DrawableSpace }.fold(0) { currentWidth, word -> currentWidth + word.width }\n    val spaceWidthBase = floor(totalSpaceWidth.toFloat() / spacesExceptIfLast.size).toInt()\n    var remainder = if (spacesExceptIfLast.isNotEmpty()) totalSpaceWidth % spacesExceptIfLast.size else 0\n    spacesExceptIfLast.forEach { space ->\n        val currentSpaceWidth = if (remainder > 0) {\n            remainder--\n            spaceWidthBase + 1\n        } else {\n            spaceWidthBase\n        }\n        space.setWidth(currentSpaceWidth)\n    }\n    spaceIfLast?.setWidth(0)\n    return initializeLine(line, x, y)\n}\n\nprivate fun initializeLine(line: List<DrawableWord>, x: Int, y: Int): Int {\n    if (line.isEmpty()) return 0\n    line.fold(x) { currentX, word ->\n        word.setPos(currentX, y)\n        currentX + word.width\n    }\n    return line.maxOf { word -> word.height }\n}\n\nprivate fun splitLines(originalWords: List<DrawableWord>, maxWidth: Int): List<List<DrawableWord>> {\n    val line = mutableListOf<DrawableWord>()\n    val lines = mutableListOf<List<DrawableWord>>()\n    var currentWidth = 0\n\n    fun breakLine() {\n        currentWidth = 0\n        lines.add(line.toMutableList())\n        line.clear()\n    }\n\n    fun addWordToLine(word: DrawableWord) {\n        currentWidth += word.width\n        line.add(word)\n    }\n\n    for (word in originalWords) {\n        if (word is DrawableSpace) word.resetWidth()\n        if (currentWidth + word.width > maxWidth && word !is DrawableSpace) {\n            breakLine()\n        }\n        addWordToLine(word)\n        if (word is DrawableBreak || word == originalWords.last()) breakLine()\n    }\n\n    return lines\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/GuiGuideBook.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.LPItems\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.modplugins.jei.JEIPluginLoader\nimport logisticspipes.utils.Color\nimport logisticspipes.utils.MinecraftColor\nimport logisticspipes.utils.gui.SimpleGraphics\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.gui.GuiButton\nimport net.minecraft.client.gui.GuiConfirmOpenLink\nimport net.minecraft.client.gui.GuiScreen\nimport net.minecraft.client.renderer.GlStateManager\nimport net.minecraft.item.ItemStack\nimport network.rs485.logisticspipes.gui.HorizontalAlignment\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.gui.VerticalAlignment\nimport network.rs485.logisticspipes.gui.widget.Tooltipped\nimport network.rs485.logisticspipes.guidebook.BookContents\nimport network.rs485.logisticspipes.guidebook.BookContents.MAIN_MENU_FILE\nimport network.rs485.logisticspipes.guidebook.DebugPage\nimport network.rs485.logisticspipes.guidebook.ItemGuideBook\nimport network.rs485.logisticspipes.util.cycleMinecraftColorId\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport network.rs485.markdown.TextFormat\nimport org.lwjgl.input.Mouse\nimport org.lwjgl.opengl.GL11\nimport java.net.URI\nimport java.net.URISyntaxException\nimport java.util.*\nimport kotlin.math.floor\nimport kotlin.math.max\nimport kotlin.math.min\nimport kotlin.math.roundToInt\n\n\nobject GuideBookConstants {\n    // Z Levels\n    const val Z_TOOLTIP = 500.0f // Tooltip z\n\n    // Debug constant\n    const val DRAW_BODY_WIREFRAME = false\n}\n\nclass GuiGuideBook(private val state: ItemGuideBook.GuideBookState) : GuiScreen() {\n\n    /*\n    TODO after first deployment:\n    - Page history with back and forwards functionality.\n    - Crafting recipes?\n    - Use translatable names or block/item identifiers as text?\n    - DrawableListParagraph\n    - Add configurability to images\n    - Create tooltip object and render it independently of the Drawable it's attached to\n    - Create a variety of tooltips with configurable style and information.\n    - Improve font renderer to allow for more fonts.\n    - Add config screen for the book to change font/font size.\n    - Add option to enable or disable text justification.\n     */\n\n    // Gui Frame Constants\n    private val guiBorderThickness = 16\n    private val guiShadowThickness = 6\n    private val guiSeparatorThickness = 6\n\n    // Slider\n    private val guiSliderWidth = 12\n\n    // Tabs\n    private val guiTabWidth = 24\n    private val maxTabs = 100\n\n    // Gui constrains\n    private val innerGui = MutableRectangle()\n    private val outerGui = MutableRectangle()\n    private val sliderSeparator = MutableRectangle()\n    private val visibleArea = MutableRectangle()\n\n    // Drawing vars\n    private var guiSliderX = 0\n    private var guiSliderY0 = 0\n    private var guiSliderY1 = 0\n\n    // Buttons\n    private lateinit var slider: SliderButton\n    private lateinit var home: HomeButton\n\n    private lateinit var addOrRemoveTabButton: BookmarkManagingButton\n\n    // initialize tabs from the stack NBT\n    private val tabButtons = state.bookmarks.map(::createGuiTabButton).toMutableList()\n    private var freeColor: Int = state.bookmarks.maxOfOrNull { it.color ?: 0 } ?: 0\n\n    // initialize cached pages with initial open page\n    private val cachedPages = state.bookmarks.plus(state.currentPage).associateBy { it.page }.toMutableMap()\n\n    private val actionListener = ActionListener()\n\n    private var currentProgress: Float = state.currentPage.progress\n\n    inner class ActionListener {\n        fun onMenuButtonClick(newPage: String) = changePage(newPage)\n        fun onPageLinkClick(newPage: String) = changePage(newPage)\n        fun onWebLinkClick(webLink: String) {\n            try {\n                this@GuiGuideBook.clickedLinkURI = URI(webLink)\n                mc.displayGuiScreen(GuiConfirmOpenLink(this@GuiGuideBook, webLink, 31102009, false))\n            } catch (error: URISyntaxException) {\n                LogisticsPipes.log.warn(\"Could not parse link $webLink in GuiGuideBook\", error)\n            }\n        }\n\n        fun onItemLinkClick(stack: ItemStack) {\n            JEIPluginLoader.showRecipe(stack)\n        }\n    }\n\n    init {\n        if (LogisticsPipes.isDEBUG()) {\n            val debugSavedPage = cachedPages.getOrPut(DebugPage.FILE) { Page(PageData(DebugPage.FILE)) }\n            debugSavedPage.color = 0\n            tabButtons.add(createGuiTabButton(debugSavedPage))\n        }\n    }\n\n    private fun changePage(path: String) {\n        val newPage = cachedPages.getOrPut(path) { Page(PageData(path)) }\n        state.currentPage = newPage\n        currentProgress = state.currentPage.progress\n        newPage.setDrawablesPosition(visibleArea)\n        updateButtonVisibility()\n    }\n\n    // (Re)calculates gui element sizes and positions, this is run on gui init\n    private fun calculateGuiConstraints() {\n        val marginRatio = 1.0 / 8.0\n        val sizeRatio = 6.0 / 8.0\n        outerGui.setPos(floor(marginRatio * width).toInt(), floor(marginRatio * height).toInt())\n            .setSize((sizeRatio * width).toInt(), (sizeRatio * height).toInt())\n        innerGui.setPos(outerGui.x0 + guiBorderThickness, outerGui.y0 + guiBorderThickness)\n            .setSize(outerGui.roundedWidth - 2 * guiBorderThickness, outerGui.roundedHeight - 2 * guiBorderThickness)\n        sliderSeparator.setPos(innerGui.x1 - guiSliderWidth - guiSeparatorThickness - guiShadowThickness, innerGui.y0 - 1)\n            .setSize(2 * guiShadowThickness + guiSeparatorThickness, innerGui.roundedHeight + 2)\n        guiSliderX = innerGui.roundedRight - guiSliderWidth\n        guiSliderY0 = innerGui.roundedTop\n        guiSliderY1 = innerGui.roundedBottom\n        visibleArea.setPos(innerGui.x0 + guiShadowThickness, innerGui.y0)\n            .setSize(innerGui.roundedWidth - sliderSeparator.roundedWidth - guiSliderWidth, innerGui.roundedHeight)\n        state.currentPage.setDrawablesPosition(visibleArea)\n        updateButtonVisibility()\n    }\n\n    // Checks each button for visibility and updates tab positions.\n    private fun updateButtonVisibility() {\n        if (this::home.isInitialized) home.visible = state.currentPage.page != MAIN_MENU_FILE\n        if (this::slider.isInitialized) {\n            slider.updateSlider(state.currentPage.getExtraHeight(visibleArea), state.currentPage.progress)\n        }\n        var xOffset = 0\n        for (button: TabButton in tabButtons) {\n            button.setPos(outerGui.roundedRight - 2 - 2 * guiTabWidth - xOffset, outerGui.roundedTop)\n            xOffset += guiTabWidth\n        }\n        if (this::addOrRemoveTabButton.isInitialized) {\n            addOrRemoveTabButton.updateState()\n            addOrRemoveTabButton.setX(outerGui.roundedRight - 20 - guiTabWidth - xOffset)\n        }\n    }\n\n    private fun isTabAbsent(page: Page): Boolean = state.bookmarks.none { it.pageEquals(page) }\n\n    override fun initGui() {\n        calculateGuiConstraints()\n        slider = addButton(\n            SliderButton(\n                x = innerGui.roundedRight - guiSliderWidth,\n                y = innerGui.roundedTop,\n                railHeight = innerGui.roundedHeight,\n                width = guiSliderWidth,\n                progress = state.currentPage.progress,\n                setProgressCallback = { progress -> state.currentPage.progress = progress }\n            )\n        )\n        home = addButton(\n            HomeButton(\n                x = outerGui.roundedRight,\n                y = outerGui.roundedTop\n            ) { mouseButton ->\n                if (mouseButton == 0) {\n                    changePage(MAIN_MENU_FILE)\n                }\n                return@HomeButton true\n            }\n        )\n        addOrRemoveTabButton = addButton(\n            BookmarkManagingButton(\n                x = outerGui.roundedRight - 18 - guiTabWidth + 4,\n                y = outerGui.roundedTop - 2,\n                onClickAction = { buttonState ->\n                    when (buttonState) {\n                        BookmarkManagingButton.ButtonState.ADD -> addBookmark().let { true }\n                        BookmarkManagingButton.ButtonState.REMOVE -> removeBookmark(state.currentPage)\n                        BookmarkManagingButton.ButtonState.DISABLED -> false\n                    }\n                },\n                additionStateUpdater = {\n                    when {\n                        state.currentPage.isBookmarkable() && isTabAbsent(state.currentPage) -> BookmarkManagingButton.ButtonState.ADD\n                        !isTabAbsent(state.currentPage) -> BookmarkManagingButton.ButtonState.REMOVE\n                        else -> BookmarkManagingButton.ButtonState.DISABLED\n                    }\n                }\n            )\n        )\n        updateButtonVisibility()\n    }\n\n    override fun onGuiClosed() {\n        LPItems.itemGuideBook.saveState(state)\n        if (LogisticsPipes.isDEBUG()) {\n            BookContents.clear()\n        }\n        super.onGuiClosed()\n    }\n\n    override fun onResize(mcIn: Minecraft, w: Int, h: Int) {\n        state.currentPage.progress = 0.0f\n        super.onResize(mcIn, w, h)\n    }\n\n    override fun drawScreen(mouseX: Int, mouseY: Int, partialTicks: Float) {\n        drawDefaultBackground()\n        GlStateManager.enableDepth()\n        GlStateManager.depthFunc(GL11.GL_ALWAYS)\n        SimpleGraphics.drawGradientRect(0, 0, width, height, Color.BLANK, Color.BLANK, 450.0)\n\n        GuiDrawer.drawGuideBookBackground(outerGui)\n\n        GlStateManager.depthFunc(GL11.GL_LEQUAL)\n        state.currentPage.run {\n            updateScrollPosition(visibleArea, currentProgress)\n            draw(visibleArea, mouseX.toFloat(), mouseY.toFloat(), partialTicks)\n        }\n        GlStateManager.depthFunc(GL11.GL_ALWAYS)\n        tabButtons.forEach { it.drawButton(mc, mouseX, mouseY, partialTicks) }\n        GuiDrawer.drawGuideBookFrame(outerGui, sliderSeparator)\n        buttonList.forEach { it.drawButton(mc, mouseX, mouseY, partialTicks) }\n\n        (buttonList + tabButtons).reversed().forEach { it.drawButtonForegroundLayer(mouseX, mouseY) }\n        GlStateManager.depthFunc(GL11.GL_LEQUAL)\n\n        if (visibleArea.contains(mouseX, mouseY)) {\n            val hovered = state.currentPage.getHovered(mouseX.toFloat(), mouseY.toFloat())\n            hovered?.also {\n                if (it is Tooltipped) {\n                    GuiDrawer.drawTextTooltip(\n                        text = it.getTooltipText(),\n                        x = mouseX,\n                        y = min(mouseY - 5f, visibleArea.bottom).roundToInt(),\n                        z = GuideBookConstants.Z_TOOLTIP,\n                        horizontalAlign = HorizontalAlignment.CENTER,\n                        verticalAlign = VerticalAlignment.BOTTOM,\n                    )\n                }\n            }\n        }\n        drawTitle()\n    }\n\n    override fun doesGuiPauseGame() = false\n\n    override fun mouseClicked(mouseX: Int, mouseY: Int, mouseButton: Int) {\n        val allButtons = (buttonList + tabButtons).sortedBy { it.zLevel }.filter { it.visible && it.enabled }\n        for (button in allButtons) {\n            if (button.mousePressed(mc, mouseX, mouseY)) {\n                selectedButton = button\n                when (mouseButton) {\n                    0 -> {\n                        actionPerformed(button)\n                        return\n                    }\n\n                    1 -> {\n                        rightClick(button)\n                        return\n                    }\n                }\n            }\n        }\n        if (visibleArea.contains(mouseX, mouseY)) {\n            state.currentPage.mouseClicked(mouseX.toFloat(), mouseY.toFloat(), mouseButton, visibleArea, actionListener)\n        }\n    }\n\n    override fun updateScreen() {\n        if (currentProgress == state.currentPage.progress) {\n            return\n        }\n        val progressDiff = currentProgress - state.currentPage.progress\n        val speedModifier = 0.5f\n        currentProgress = when {\n            progressDiff < 0.0025f && progressDiff > -0.0025f -> {\n                state.currentPage.progress\n            }\n\n            progressDiff < 0.0025f -> {\n                min(currentProgress - (progressDiff * speedModifier), state.currentPage.progress)\n            }\n\n            progressDiff > -0.0025f -> {\n                max(currentProgress - (progressDiff * speedModifier), state.currentPage.progress)\n            }\n\n            else -> currentProgress\n        }\n    }\n\n    override fun handleMouseInput() {\n        super.handleMouseInput()\n        if (state.currentPage.getExtraHeight(visibleArea) > 0) {\n            val mouseDWheel = Mouse.getDWheel() / -120\n            if (mouseDWheel != 0) {\n                slider.changeProgress(mouseDWheel * GuiDrawer.lpFontRenderer.getFontHeight(1.0f))\n            }\n        }\n    }\n\n    override fun actionPerformed(button: GuiButton) {\n        when (button) {\n            home -> if (home.click(0)) {\n                button.playPressSound(mc.soundHandler)\n            }\n\n            addOrRemoveTabButton -> if (addOrRemoveTabButton.click(0)) {\n                button.playPressSound(mc.soundHandler)\n            }\n\n            is TabButton -> if (button.onLeftClick()) {\n                button.playPressSound(mc.soundHandler)\n            }\n        }\n        updateButtonVisibility()\n    }\n\n    private fun rightClick(button: GuiButton) {\n        when (button) {\n            is TabButton -> {\n                if (button.onRightClick(shiftClick = isShiftKeyDown(), ctrlClick = isCtrlKeyDown())) {\n                    button.playPressSound(mc.soundHandler)\n                }\n            }\n        }\n        updateButtonVisibility()\n    }\n\n    private fun addBookmark() = state.currentPage.takeIf { isTabAbsent(it) && tabButtons.size < maxTabs }\n        ?.also { state.bookmarks.add(it); tabButtons.add(createGuiTabButton(it)) }\n\n    private fun createGuiTabButton(tabPage: Page): TabButton =\n        TabButton(tabPage, outerGui.roundedRight - 2 - 2 * guiTabWidth, outerGui.roundedTop, object : TabButtonReturn {\n            override fun onLeftClick(): Boolean {\n                if (!isPageActive()) {\n                    changePage(tabPage.page)\n                    return true\n                }\n                return false\n            }\n\n            override fun onRightClick(shiftClick: Boolean, ctrlClick: Boolean): Boolean {\n                if (!isPageActive()) return false\n                if (ctrlClick && shiftClick) {\n                    removeBookmark(tabPage)\n                } else {\n                    tabPage.cycleColor(inverted = shiftClick)\n                }\n                return true\n            }\n\n            override fun getColor(): Int =\n                tabPage.color ?: cycleMinecraftColorId(freeColor).also { freeColor = it; tabPage.color = it }\n\n            override fun isPageActive(): Boolean = tabPage.pageEquals(state.currentPage)\n        })\n\n    private fun removeBookmark(page: Page): Boolean {\n        val removedFromState = state.bookmarks.removeIf { it.pageEquals(page) }\n        val removedFromButtons = tabButtons.removeIf { it.tabPage.pageEquals(page) }\n        return removedFromState || removedFromButtons\n    }\n\n    private fun drawTitle() {\n        GuiDrawer.lpFontRenderer.drawCenteredString(\n            state.currentPage.title,\n            floor(width / 2.0f),\n            outerGui.y0 + (innerGui.y0 - outerGui.y0 - GuiDrawer.lpFontRenderer.getFontHeight()) / 2.0f,\n            MinecraftColor.WHITE.colorCode,\n            EnumSet.of(TextFormat.Shadow),\n            1.0f\n        )\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/HomeButton.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.renderer.GlStateManager\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.util.Rectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\nprivate val homeButtonTexture = Rectangle(16, 64, 24, 32)\nprivate val homeIconTexture = Rectangle(128, 0, 16, 16)\n\n/*\n* Position on the button is set based on its rightmost and where it needs to connect at the bottom.\n*/\nclass HomeButton(x: Int, y: Int, onClickAction: (Int) -> Boolean) : LPGuiButton(1, x - 24, y - 24, homeButtonTexture.roundedWidth, homeButtonTexture.roundedHeight) {\n    private val homeIconBody: MutableRectangle\n    override val bodyTrigger = Rectangle(1, 1, 22, 22)\n\n    init {\n        this.setOnClickAction(onClickAction)\n        val offset = (body.width - homeIconTexture.width) / 2\n        homeIconBody = MutableRectangle(offset, offset, homeIconTexture.width, homeIconTexture.height)\n    }\n\n    override fun setPos(newX: Int, newY: Int) {\n        body.setPos(newX - 24, newY + 8)\n    }\n\n    override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int, partialTicks: Float) {\n        hovered = isHovered(mouseX, mouseY)\n        if (visible) {\n            GlStateManager.enableAlpha()\n            GlStateManager.enableBlend()\n            GuiDrawer.drawGuiTexturedRect(body, homeButtonTexture, false, MinecraftColor.WHITE.colorCode)\n            val hoverStateOffset = getHoverState(hovered) * homeIconTexture.roundedHeight\n            GuiDrawer.drawGuiTexturedRect(homeIconBody.translated(body), homeIconTexture.translated(0, hoverStateOffset), false, MinecraftColor.WHITE.colorCode)\n        }\n    }\n\n    override fun getTooltipText(): String {\n        return TextUtil.translate(\"misc.guide_book.home_button\")\n    }\n\n    override fun drawButtonForegroundLayer(mouseX: Int, mouseY: Int) {\n        if (hovered && visible) {\n            drawTooltip(\n                    x = body.roundedRight,\n                    y = body.roundedTop,\n                    horizontalAlign = HorizontalAlignment.RIGHT,\n                    verticalAlign = VerticalAlignment.BOTTOM\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/LPGuiButton.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.gui.GuiButton\nimport network.rs485.logisticspipes.gui.HorizontalAlignment\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.gui.VerticalAlignment\nimport network.rs485.logisticspipes.util.Rectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\nopen class LPGuiButton(id: Int, x: Int, y: Int, width: Int, height: Int) : GuiButton(id, 24, 24, \"\") {\n    val body = MutableRectangle(x, y, width, height)\n\n    // Position relative to body.\n    open val bodyTrigger: Rectangle = Rectangle(width = width, height = height)\n    private var onClickAction: ((Int) -> Boolean)? = null\n\n    override fun mousePressed(mc: Minecraft, mouseX: Int, mouseY: Int): Boolean = isHovered(mouseX, mouseY)\n\n    override fun isMouseOver(): Boolean = hovered\n\n    override fun getButtonWidth(): Int = body.roundedWidth\n\n    override fun setWidth(width: Int) {\n        body.setSize(newWidth = width, body.roundedHeight)\n    }\n\n    override fun getHoverState(mouseOver: Boolean): Int = if (!enabled) 2 else if (hovered) 1 else 0\n\n    internal fun isHovered(mouseX: Int, mouseY: Int): Boolean =\n        enabled && visible && bodyTrigger.translated(body.x0, body.y0).contains(mouseX, mouseY)\n\n    open fun setPos(newX: Int, newY: Int) {\n        body.setPos(newX, newY)\n    }\n\n    open fun setOnClickAction(newOnClickAction: (Int) -> Boolean): LPGuiButton {\n        onClickAction = newOnClickAction\n        return this\n    }\n\n    open fun click(mouseButton: Int): Boolean = onClickAction?.invoke(mouseButton) ?: false\n\n    open fun getTooltipText(): String = \"\"\n\n    open fun drawTooltip(x: Int, y: Int, horizontalAlign: HorizontalAlignment, verticalAlign: VerticalAlignment) {\n        GuiDrawer.drawTextTooltip(listOf(getTooltipText()), x, y, GuideBookConstants.Z_TOOLTIP, horizontalAlign, verticalAlign)\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/LinkGroup.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.markdown.*\n\ninterface LinkInteractable : GuideBookMouseInteractable {\n    /**\n     * Returns an updated color depending on any mouse interaction.\n     */\n    fun updateColor(baseColor: Int): Int\n\n    /**\n     * Returns an updated format depending on any mouse interaction.\n     */\n    fun updateFormat(baseFormat: Set<TextFormat>): Set<TextFormat>\n\n    /**\n     * Update mouse state for any state changes.\n     */\n    fun updateState(mouseX: Float, mouseY: Float, visibleArea: IRectangle)\n\n}\n\ninterface GuideBookMouseInteractable : MouseInteractable {\n    /**\n     * A mouse click event should run this and the implementation checks if\n     * any actions on guideActionListener should be run.\n     * @param mouseX position of the mouse (absolute, screen)\n     * @param mouseY position of the mouse (absolute, screen)\n     * @param mouseButton button of the mouse that was pressed.\n     * @param guideActionListener actions to run from outside this scope? (ben knows it best)\n     * @return true, if action was taken.\n     */\n    fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean = false\n}\n\nclass LinkGroup(private val link: Link) : LinkInteractable {\n    private val orderedChildren: MutableList<DrawableWord> = mutableListOf()\n    var hovered: Boolean = false\n        internal set\n\n    fun addChild(linkWord: DrawableWord) = orderedChildren.add(linkWord)\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean =\n            orderedChildren.any {\n                it.isMouseHovering(mouseX, mouseY)\n            }\n\n    override fun updateState(mouseX: Float, mouseY: Float, visibleArea: IRectangle) =\n            isMouseHovering(mouseX, mouseY).let { hovered = it }\n\n    override fun inBookMouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int, guideActionListener: GuiGuideBook.ActionListener?): Boolean {\n        if (guideActionListener != null) {\n            when (link) {\n                is PageLink -> guideActionListener.onPageLinkClick(link.page)\n                is WebLink -> guideActionListener.onWebLinkClick(link.url)\n                is ItemLink -> {\n                    guideActionListener.onItemLinkClick(link.stack)\n                    /* TODO Display item tooltip on hover */\n                }\n            }\n            return true\n        }\n        return false\n    }\n\n    override fun updateColor(baseColor: Int): Int = MinecraftColor.LIGHT_BLUE.colorCode\n\n    override fun updateFormat(baseFormat: Set<TextFormat>): Set<TextFormat> =\n            (if (hovered) baseFormat::minusElement else baseFormat::plusElement).invoke(TextFormat.Underline)\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/Page.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport net.minecraft.nbt.NBTTagCompound\nimport network.rs485.logisticspipes.guidebook.BookContents\nimport network.rs485.logisticspipes.util.*\n\n\ninterface IPageData : LPSerializable {\n    var page: String\n    var color: Int?\n    var progress: Float\n\n    fun fromTag(tag: NBTTagCompound) {\n        page = tag.getString(\"page\")\n        color = if (tag.hasKey(\"color\")) tag.getInteger(\"color\") else null\n        progress = tag.getFloat(\"progress\")\n    }\n\n    fun toTag(): NBTTagCompound {\n        val nbt = NBTTagCompound()\n        nbt.setString(\"page\", page)\n        color?.also {\n            nbt.setInteger(\"color\", it)\n        }\n        nbt.setFloat(\"progress\", progress)\n        return nbt\n    }\n\n    /**\n     * Takes in an LPDataOutput buffer and turns a SavedPage object into bytes and puts them inside the buffer.\n     * @param output data to send\n     */\n    override fun write(output: LPDataOutput) = output.writeNBTTagCompound(toTag())\n\n    /**\n     * Takes in an LPDataInput buffer and turns the buffered bytes object into a SavedPage object.\n     * @param input the received data\n     * @return SavedPage object created from the buffered data\n     */\n    override fun read(input: LPDataInput) {\n        input.readNBTTagCompound()?.apply(::fromTag)\n    }\n}\n\n\nclass PageData : IPageData {\n\n    override var page: String = \"\"\n    override var color: Int? = null\n    override var progress: Float = 0.0F\n\n    constructor(input: LPDataInput) {\n        read(input)\n    }\n\n    constructor(tag: NBTTagCompound) {\n        fromTag(tag)\n    }\n\n    constructor(page: String) {\n        this.page = page\n    }\n\n}\n\n\nclass Page(data: PageData) : IPageData by data {\n\n    private val infoProvider = BookContents.get(page)\n    private val drawable = BookContents.getDrawablePage(page)\n\n    val title: String\n        get() = infoProvider.metadata.title\n\n    fun updateScrollPosition(visibleArea: IRectangle, currentProgress: Float) =\n        drawable.updateScrollPosition(visibleArea, currentProgress)\n\n    fun getExtraHeight(visibleArea: IRectangle): Int =\n        if (visibleArea.roundedHeight < drawable.height) drawable.height - visibleArea.roundedHeight else 0\n\n    fun mouseClicked(\n        mouseX: Float,\n        mouseY: Float,\n        mouseButton: Int,\n        visibleArea: IRectangle,\n        guideActionListener: GuiGuideBook.ActionListener,\n    ) {\n        drawable.getVisibleParagraphs(visibleArea)\n            .firstOrNull { it.absoluteBody.contains(mouseX, mouseY) }\n            ?.inBookMouseClicked(mouseX, mouseY, mouseButton, guideActionListener)\n    }\n\n    fun setDrawablesPosition(area: IRectangle) {\n        drawable.setWidth(area.roundedWidth)\n        drawable.setPos(area.roundedX, area.roundedY)\n    }\n\n    fun isBookmarkable() = infoProvider.bookmarkable\n\n    fun pageEquals(other: Page): Boolean = this.page == other.page\n\n    fun cycleColor(inverted: Boolean = false) =\n        cycleMinecraftColorId((color ?: 0), inverted).also { color = it }\n\n    fun draw(visibleArea: IRectangle, mouseX: Float, mouseY: Float, partialTicks: Float) {\n        drawable.preRender(mouseX, mouseY, visibleArea)\n        drawable.draw(mouseX, mouseY, partialTicks, visibleArea)\n    }\n\n    fun getHovered(mouseX: Float, mouseY: Float) = drawable.getHovered(mouseX, mouseY)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/SliderButton.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport net.minecraft.client.Minecraft\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.util.Rectangle\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport kotlin.math.roundToInt\n\nprivate const val minimumHeight = 16\nprivate val texture = Rectangle(96, 0, 12, 16)\n\nclass SliderButton(x: Int, y: Int, width: Int, railHeight: Int, private var progress: Float, val setProgressCallback: (progress: Float) -> Unit) : LPGuiButton(0, x, y, width, railHeight) {\n    private val sliderButton: MutableRectangle = MutableRectangle()\n    private val movementDistance: Int get() = body.roundedHeight - sliderButton.roundedHeight\n    private var dragging: Boolean = false\n    private var initialMouseYOffset: Int = 0\n    private var hoveredBar: Boolean = false\n\n    override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int, partialTicks: Float) {\n        if (!visible) return\n        hoveredBar = sliderButton.translated(body).contains(mouseX, mouseY)\n        hovered = body.contains(mouseX, mouseY)\n        GuiDrawer.drawSliderButton(\n            body = sliderButton.translated(body),\n            texture = texture.translated(0, getHoverState(hoveredBar) * texture.roundedHeight),\n        )\n        mouseDragged(mc, mouseX, mouseY)\n    }\n\n    override fun getHoverState(mouseOver: Boolean): Int = if (dragging) 3 else if (!enabled) 2 else if (hoveredBar) 1 else 0\n\n    override fun mouseReleased(mouseX: Int, mouseY: Int) {\n        if (dragging) {\n            dragging = false\n            setProgressI((mouseY - body.roundedY) - initialMouseYOffset)\n            initialMouseYOffset = 0\n            setProgressCallback(progress)\n        }\n        super.mouseReleased(mouseX, mouseY)\n    }\n\n    override fun mouseDragged(mc: Minecraft, mouseX: Int, mouseY: Int) {\n        if (dragging) {\n            setProgressI((mouseY - body.roundedY) - initialMouseYOffset)\n            setProgressCallback(progress)\n        }\n    }\n\n    override fun mousePressed(mc: Minecraft, mouseX: Int, mouseY: Int): Boolean {\n        if (visible && enabled) {\n            if (hoveredBar) {\n                dragging = true\n                initialMouseYOffset = mouseY - sliderButton.translated(body).y0.toInt()\n                return true\n            } else if(hovered) {\n                setProgressI(mouseY - body.roundedTop - (sliderButton.roundedHeight / 2))\n                setProgressCallback(progress)\n            }\n        }\n        return false\n    }\n\n    private fun updateButtonY() {\n        val y: Int = (movementDistance * progress).toInt()\n        sliderButton.setPos(sliderButton.roundedX, y)\n    }\n\n    fun updateSlider(extraHeight: Int, newProgress: Float): SliderButton {\n        if (extraHeight > 0) {\n            enabled = true\n            sliderButton.setPos(0, calculateProgressI())\n            val possibleHeight: Int = body.roundedHeight - extraHeight\n            sliderButton.setSize(\n                newWidth = body.roundedWidth,\n                newHeight = (if ((possibleHeight % 2) == 0) possibleHeight - 1 else possibleHeight).coerceIn(minimumHeight..body.roundedHeight)\n            )\n            progress = newProgress\n            updateButtonY()\n        } else {\n            enabled = false\n            sliderButton.setPos(0, 0)\n            sliderButton.setSize(body.roundedWidth, newHeight = minimumHeight)\n            progress = 0.0f\n            updateButtonY()\n        }\n        return this\n    }\n\n    // Set button y level as well as update progress value.\n    private fun setProgressI(progressI: Int) {\n        sliderButton.setPos(sliderButton.roundedX, progressI.coerceIn(0, movementDistance))\n        progress = calculateProgressF()\n    }\n\n    fun changeProgress(amount: Int) {\n        sliderButton.setPos(sliderButton.x0, (sliderButton.y0 + amount).coerceIn(0.0F, movementDistance.toFloat()))\n        progress = calculateProgressF()\n        setProgressCallback(progress)\n    }\n\n    // Calculates y level from given progress\n    private fun calculateProgressI(): Int = (movementDistance * progress).roundToInt()\n\n    // Calculates progress from given y level\n    private fun calculateProgressF(): Float = sliderButton.y0 / movementDistance\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/guidebook/TabButton.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport net.minecraft.client.Minecraft\nimport network.rs485.logisticspipes.gui.HorizontalAlignment\nimport network.rs485.logisticspipes.gui.GuiDrawer\nimport network.rs485.logisticspipes.gui.VerticalAlignment\nimport network.rs485.logisticspipes.util.Rectangle\n\ninterface TabButtonReturn {\n    fun onLeftClick(): Boolean\n    fun onRightClick(shiftClick: Boolean, ctrlClick: Boolean): Boolean\n    fun getColor(): Int\n    fun isPageActive(): Boolean\n}\n\nprivate val buttonTextureArea = Rectangle(40, 64, 24, 32)\nprivate val circleAreaTexture = Rectangle(32, 96, 16, 16)\n\nclass TabButton(\n    internal val tabPage: Page,\n    x: Int,\n    y: Int,\n    private val whisky: TabButtonReturn,\n) : LPGuiButton(99, x, y - 24, 24, 32) {\n\n    override val bodyTrigger = Rectangle(1, 1, 22, 22)\n    private val circleArea = Rectangle(4, 4, 16, 16)\n    val isActive: Boolean\n        get() = whisky.isPageActive()\n    val isInactive: Boolean\n        get() = !isActive\n\n\n    fun onLeftClick() = whisky.onLeftClick()\n\n    fun onRightClick(shiftClick: Boolean, ctrlClick: Boolean) = whisky.onRightClick(shiftClick, ctrlClick)\n\n    override fun drawButton(mc: Minecraft, mouseX: Int, mouseY: Int, partialTicks: Float) {\n        hovered = isHovered(mouseX, mouseY)\n        if (!visible) return\n        if (isInactive) {\n            val yOffset = if (whisky.isPageActive()) 0 else 3\n            val color: Int = (MinecraftColor.values()[whisky.getColor()].colorCode and 0x00FFFFFF) or 0xFF000000.toInt()\n            GuiDrawer.drawGuiTexturedRect(\n                rect = body.translated(0, yOffset),\n                text = buttonTextureArea,\n                blend = true,\n                color = if (whisky.isPageActive()) 0xFFFFFFFF.toInt() else color\n            )\n        }\n    }\n\n    override fun getTooltipText(): String {\n        return tabPage.title\n    }\n\n    override fun drawButtonForegroundLayer(mouseX: Int, mouseY: Int) {\n        if (isActive) {\n            val color: Int = (MinecraftColor.values()[whisky.getColor()].colorCode and 0x00FFFFFF) or 0xFF000000.toInt()\n            GuiDrawer.drawGuiTexturedRect(\n                rect = body,\n                text = buttonTextureArea,\n                blend = true,\n                color = -1\n            )\n            GuiDrawer.drawGuiTexturedRect(\n                rect = circleArea.translated(body),\n                text = circleAreaTexture,\n                blend = true,\n                color = color\n            )\n        }\n        if (hovered && visible) {\n            drawTooltip(\n                x = body.roundedRight,\n                y = body.roundedTop,\n                horizontalAlign = HorizontalAlignment.RIGHT,\n                verticalAlign = VerticalAlignment.BOTTOM\n            )\n        }\n    }\n\n    override fun setPos(newX: Int, newY: Int) {\n        body.setPos(newX, newY - 24)\n    }\n\n    override fun mousePressed(mc: Minecraft, mouseX: Int, mouseY: Int): Boolean =\n        bodyTrigger\n            .translated(body)\n            .translated(0, if (whisky.isPageActive()) -3 else 0)\n            .contains(mouseX, mouseY)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/module/ItemSinkGui.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.module\n\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.gui.widget.FuzzySelectionWidget\nimport network.rs485.logisticspipes.inventory.container.ItemSinkContainer\nimport network.rs485.logisticspipes.property.BooleanProperty\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty\nimport network.rs485.logisticspipes.property.layer.PropertyLayer\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport logisticspipes.modules.ModuleItemSink\nimport logisticspipes.network.PacketHandler\nimport logisticspipes.network.packets.module.ItemSinkImportPacket\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.utils.Color\nimport logisticspipes.utils.item.ItemIdentifier\nimport mezz.jei.api.gui.IGhostIngredientHandler\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\nimport java.awt.Rectangle\nimport java.util.concurrent.atomic.AtomicReference\n\nclass ItemSinkWidgetScreen(private val guiReference: AtomicReference<ItemSinkGui>) : WidgetScreen() {\n    override fun constructWidgetContainer() = widgetContainer {\n        val gui = guiReference.get() ?: return@widgetContainer\n        margin = Margin.DEFAULT\n        staticLabel {\n            text = gui.itemSinkModule.filterInventory.name\n            textAlignment = HorizontalAlignment.CENTER\n            textColor = Color.TEXT_DARK.value\n        }\n        customSlots {\n            slots = gui.itemSinkContainer.filterSlots\n            columns = 9\n            rows = 1\n        }\n        horizontal {\n            margin = Margin(top = 3, bottom = 3)\n            optionalComponent {\n                predicate = { gui.inHand }\n                inactiveComponents {\n                    button {\n                        text = TextUtil.translate(\"${gui.prefix}import\")\n                        action = {\n                            MainProxy.sendPacketToServer(\n                                PacketHandler.getPacket(ItemSinkImportPacket::class.java).setModulePos(gui.itemSinkModule),\n                            )\n                        }\n                        enabled = true // TODO disable button if there is no attached inventory!\n                    }\n                }\n            }\n            staticLabel {\n                text = \"${TextUtil.translate(\"${gui.prefix}Defaultroute\")}:\"\n                textColor = Color.TEXT_DARK.value\n                textAlignment = HorizontalAlignment.RIGHT\n                verticalAlignment = VerticalAlignment.CENTER\n                horizontalSize = Size.MIN\n            }\n            propertyButton<Boolean, BooleanProperty> {\n                property = gui.itemSinkModule.defaultRoute\n                propertyLayer = gui.propertyLayer\n                propertyToText = { isDefaultRoute ->\n                    if (isDefaultRoute) {\n                        TextUtil.translate(\"${gui.prefix}Yes\")\n                    } else {\n                        TextUtil.translate(\"${gui.prefix}No\")\n                    }\n                }\n                text = propertyToText(gui.defaultRouteOverlay.get())\n                action = { gui.defaultRouteOverlay.write { it.toggle() } }\n            }\n        }\n        playerSlots {\n            slots = gui.itemSinkContainer.playerSlots\n        }\n    }\n\n}\n\nclass ItemSinkGui private constructor(\n    internal val itemSinkModule: ModuleItemSink,\n    internal val itemSinkContainer: ItemSinkContainer,\n    internal val propertyLayer: PropertyLayer,\n    internal val inHand: Boolean,\n    guiReference: AtomicReference<ItemSinkGui> = AtomicReference(),\n) : BaseGuiContainer(itemSinkContainer, widgetScreen = ItemSinkWidgetScreen(guiReference)) {\n\n    companion object {\n        @JvmStatic\n        fun create(\n            playerInventory: IInventory,\n            itemSinkModule: ModuleItemSink,\n            lockedStack: ItemStack,\n            isFuzzy: Boolean,\n            inHand: Boolean,\n        ): ItemSinkGui {\n            val propertyLayer = PropertyLayer(itemSinkModule.properties)\n            val filterInventoryOverlay = propertyLayer.overlay(itemSinkModule.filterInventory)\n            return ItemSinkGui(\n                itemSinkModule = itemSinkModule,\n                itemSinkContainer = ItemSinkContainer(\n                    playerInventory = playerInventory,\n                    filterInventoryOverlay = filterInventoryOverlay,\n                    itemSinkModule = itemSinkModule,\n                    propertyLayer = propertyLayer,\n                    isFuzzy = isFuzzy,\n                    moduleInHand = lockedStack,\n                ),\n                propertyLayer = propertyLayer,\n                inHand = inHand,\n            )\n        }\n    }\n\n    internal val prefix: String = \"gui.itemsink.\"\n\n    internal val defaultRouteOverlay = propertyLayer.overlay(itemSinkModule.defaultRoute)\n    private val filterInventoryOverlay = propertyLayer.overlay(itemSinkModule.filterInventory)\n\n    override val fuzzySelector = FuzzySelectionWidget(this, itemSinkContainer.fuzzyFlagOverlay)\n\n    init {\n        guiReference.set(this)\n    }\n\n    fun importFromInventory(importedItems: List<ItemIdentifier>) {\n        if (importedItems.isEmpty()) return\n        filterInventoryOverlay.write { filterInventory: ItemIdentifierInventoryProperty ->\n            for (i in filterInventory.indices) {\n                if (i < importedItems.size) {\n                    filterInventory.setInventorySlotContents(i, importedItems[i].makeStack(1))\n                } else {\n                    filterInventory.setInventorySlotContents(i, ItemStack.EMPTY)\n                }\n            }\n        }\n    }\n\n    override fun onGuiClosed() {\n        super.onGuiClosed()\n        propertyLayer.unregister()\n        if (mc.player != null && propertyLayer.properties.isNotEmpty()) {\n            // send update to server, when there are changed properties\n            MainProxy.sendPacketToServer(\n                ModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(itemSinkModule),\n            )\n        }\n    }\n\n    override fun <I : Any?> getFilterSlots(): MutableList<IGhostIngredientHandler.Target<I>> {\n        return itemSinkContainer.filterSlots.map { slot ->\n            object : IGhostIngredientHandler.Target<I> {\n                override fun accept(ingredient: I) {\n                    if (ingredient is ItemStack) {\n                        slot.putStack(ingredient)\n                    }\n                }\n\n                override fun getArea(): Rectangle = Rectangle(guiLeft + slot.xPos, guiTop + slot.yPos, 17, 17)\n            }\n        }.toMutableList()\n    }\n\n    override fun getExtraGuiAreas(): List<IRectangle> {\n        return if (fuzzySelector.active) {\n            listOf(fuzzySelector.relativeBody)\n        } else {\n            emptyList()\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/module/ProviderGui.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.module\n\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.inventory.ProviderMode\nimport network.rs485.logisticspipes.inventory.container.ProviderContainer\nimport network.rs485.logisticspipes.property.BooleanProperty\nimport network.rs485.logisticspipes.property.EnumProperty\nimport network.rs485.logisticspipes.property.layer.PropertyLayer\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport logisticspipes.modules.ModuleProvider\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.utils.Color\nimport mezz.jei.api.gui.IGhostIngredientHandler\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\nimport java.awt.Rectangle\nimport java.util.concurrent.atomic.AtomicReference\n\n\nclass ProviderWidgetScreen(private val guiReference: AtomicReference<ProviderGui>) : WidgetScreen() {\n    override fun constructWidgetContainer(): ComponentContainer = widgetContainer {\n        val gui = guiReference.get() ?: return@widgetContainer\n        margin = Margin.DEFAULT\n        staticLabel {\n            text = gui.providerModule.filterInventory.name\n            textAlignment = HorizontalAlignment.CENTER\n            textColor = Color.TEXT_DARK.value\n            extendable = true\n            backgroundColor = Color.BACKGROUND_LIGHT.value\n            horizontalSize = Size.GROW\n        }\n        horizontal {\n            gap = 6\n            button {\n                text = TextUtil.translate(\"${gui.prefix}Switch\")\n                action = { gui.providerMode.write { it.next() } }\n                verticalAlignment = VerticalAlignment.CENTER\n            }\n            customSlots {\n                slots = gui.providerContainer.filterSlots\n                columns = 3\n                rows = 3\n                verticalAlignment = VerticalAlignment.CENTER\n            }\n            propertyButton<Boolean, BooleanProperty> {\n                property = gui.providerModule.isExclusionFilter\n                propertyLayer = gui.propertyLayer\n                propertyToText = { isExclude ->\n                    if (isExclude) {\n                        TextUtil.translate(\"${gui.prefix}Exclude\")\n                    } else {\n                        TextUtil.translate(\"${gui.prefix}Include\")\n                    }\n                }\n                text = propertyToText(gui.isExclusionFilter.get())\n                action = { gui.isExclusionFilter.write { it.toggle() } }\n                verticalAlignment = VerticalAlignment.CENTER\n            }\n        }\n        staticLabel {\n            text = TextUtil.translate(\"${gui.prefix}ExcessInventory\")\n            textAlignment = HorizontalAlignment.LEFT\n            textColor = Color.TEXT_DARK.value\n        }\n        label<ProviderMode, EnumProperty<ProviderMode>> {\n            property = gui.providerModule.providerMode\n            propertyLayer = gui.propertyLayer\n            textAlignment = HorizontalAlignment.LEFT\n            propertyToText = { providerMode ->\n                TextUtil.translate(providerMode.modeTranslationKey)\n            }\n            textColor = Color.TEXT_DARK.value\n            text = propertyToText(gui.providerMode.get())\n        }\n        playerSlots {\n            slots = gui.providerContainer.playerSlots\n        }\n    }\n}\n\n// TODO create different buttons.\nclass ProviderGui private constructor(\n    internal val providerModule: ModuleProvider,\n    internal val providerContainer: ProviderContainer,\n    internal val propertyLayer: PropertyLayer,\n    guiReference: AtomicReference<ProviderGui> = AtomicReference(),\n) : BaseGuiContainer(providerContainer, widgetScreen = ProviderWidgetScreen(guiReference)) {\n\n    companion object {\n        @JvmStatic\n        fun create(playerInventory: IInventory, providerModule: ModuleProvider, lockedStack: ItemStack): ProviderGui {\n            val propertyLayer = PropertyLayer(providerModule.propertyList)\n            val filterInventoryOverlay = propertyLayer.overlay(providerModule.filterInventory)\n            return ProviderGui(\n                providerModule = providerModule,\n                providerContainer = ProviderContainer(\n                    providerModule = providerModule,\n                    playerInventoryIn = playerInventory,\n                    filterInventoryOverlay = filterInventoryOverlay,\n                    moduleInHand = lockedStack,\n                ),\n                propertyLayer = propertyLayer,\n            )\n        }\n    }\n\n    internal val prefix: String = \"gui.providerpipe.\"\n\n    internal val providerMode = propertyLayer.overlay(providerModule.providerMode)\n    internal val isExclusionFilter = propertyLayer.overlay(providerModule.isExclusionFilter)\n\n    init {\n        guiReference.set(this)\n    }\n\n    override fun drawFocalgroundLayer(mouseX: Float, mouseY: Float, partialTicks: Float) {\n        for (guiButton in buttonList) {\n            guiButton.drawButton(mc, mouseX.toInt(), mouseY.toInt(), partialTicks)\n        }\n    }\n\n    override fun <I> getFilterSlots(): MutableList<IGhostIngredientHandler.Target<I>> {\n        // TODO create method to turn list of filter slots into list of Target<I>\n        return providerContainer.filterSlots.map { slot ->\n            object : IGhostIngredientHandler.Target<I> {\n                override fun accept(ingredient: I) {\n                    if (ingredient is ItemStack) {\n                        slot.putStack(ingredient)\n                    }\n                }\n\n                override fun getArea(): Rectangle = Rectangle(guiLeft + slot.xPos, guiTop + slot.yPos, 17, 17)\n            }\n        }.toMutableList()\n    }\n\n    override fun getExtraGuiAreas(): List<IRectangle> = emptyList()\n\n    override fun onGuiClosed() {\n        super.onGuiClosed()\n        propertyLayer.unregister()\n        if (mc.player != null && propertyLayer.properties.isNotEmpty()) {\n            // send update to server, when there are changed properties\n            MainProxy.sendPacketToServer(\n                ModulePropertiesUpdate.fromPropertyHolder(propertyLayer).setModulePos(providerModule),\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/FuzzySelectionWidget.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.guidebook.MouseInteractable\nimport network.rs485.logisticspipes.property.BitSetProperty\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay\nimport network.rs485.logisticspipes.util.FuzzyFlag\nimport network.rs485.logisticspipes.util.FuzzyUtil\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport logisticspipes.utils.Color\nimport net.minecraft.client.Minecraft\nimport java.util.*\n\nclass FuzzySelectionWidget(\n    parent: Drawable,\n    private val fuzzyFlagOverlay: PropertyOverlay<BitSet, BitSetProperty>,\n) : LPGuiWidget(\n    parent = parent,\n    xPosition = HorizontalAlignment.LEFT,\n    yPosition = VerticalAlignment.TOP,\n    xSize = Size.FIXED,\n    ySize = Size.FIXED,\n    margin = Margin.NONE,\n), MouseInteractable {\n\n    private val flagPrefix: String = \"enum.logisticspipes.fuzzy_flags.\"\n    private val border = 5\n\n    var active: Boolean = false\n\n    var currentSlot: FuzzyItemSlot? = null\n        set(newSlot) {\n            field = newSlot?.also {\n                setSize(calculateWidth(newSlot.usedFlags), calculateHeight(newSlot.usedFlags))\n            }\n        }\n\n    override val minWidth: Int\n        get() = calculateWidth(currentSlot?.usedFlags ?: emptySet())\n    override val minHeight: Int\n        get() = calculateHeight(currentSlot?.usedFlags ?: emptySet())\n    override val maxWidth: Int = minWidth\n    override val maxHeight: Int = minHeight\n\n    override fun initWidget() {\n\n    }\n\n    private fun calculateWidth(flags: Set<FuzzyFlag>): Int = flags.maxOfOrNull {\n        Minecraft.getMinecraft().fontRenderer.getStringWidth(\n            TextUtil.translate(\"$flagPrefix${it.name.lowercase()}\") + border * 2,\n        )\n    } ?: 0\n\n    private fun calculateHeight(flags: Set<FuzzyFlag>): Int = flags.size * 10 + border * 2\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        if (active) {\n            if ((isMouseHovering(\n                    mouseX,\n                    mouseY,\n                ) || (Minecraft.getMinecraft().currentScreen as BaseGuiContainer).hoveredSlot == currentSlot) && currentSlot != null\n            ) {\n                currentSlot?.let { slot ->\n                    GuiDrawer.drawGuiBackground(relativeBody)\n                    var yOffset = border\n                    val flags = slot.flagGetter.invoke()\n                    slot.usedFlags.forEach { flag: FuzzyFlag ->\n                        val color = if (FuzzyUtil.get(flags, flag)) {\n                            GuiDrawer.getFuzzyColor(flag)\n                        } else {\n                            Color.TEXT_DARK.value\n                        }\n                        // TODO maybe draw string with shadow when hovered\n                        GuiDrawer.mcFontRenderer.drawString(\n                            TextUtil.translate(flagPrefix + flag.name.lowercase()),\n                            relativeBody.roundedX + border,\n                            relativeBody.roundedY + yOffset,\n                            color,\n                        )\n                        yOffset += 10\n                    }\n                }\n            }\n        }\n    }\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean {\n        return relativeBody.copy().grow(2).translate(-1, -1).contains(mouseX, mouseY)\n    }\n\n    override fun mouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int): Boolean {\n        currentSlot?.let { currentSlot ->\n            getHoveredFlag(mouseX, mouseY)?.let { clickedFlag ->\n                fuzzyFlagOverlay.write { p ->\n                    p.flip(currentSlot.slotIndex * 4 + clickedFlag.bit)\n                }\n                return true\n            }\n        }\n        return false\n    }\n\n    private fun getHoveredFlag(mouseX: Float, mouseY: Float): FuzzyFlag? = currentSlot?.usedFlags?.firstOrNull {\n        relativeBody.copy().translate(border, border + 10 * it.ordinal).setSize(relativeBody.roundedWidth, 10)\n            .contains(mouseX, mouseY)\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/GhostSlots.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport network.rs485.logisticspipes.property.IBitSet\nimport network.rs485.logisticspipes.util.FuzzyFlag\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.inventory.Slot\nimport java.util.*\n\ninterface Fuzzy\ninterface Unmodifiable\ninterface Item\ninterface Fluid\n\nsealed class GhostSlot(\n    inventoryIn: IInventory,\n    index: Int,\n    xPosition: Int,\n    yPosition: Int,\n) : Slot(inventoryIn, index, xPosition, yPosition) {\n    override fun getSlotStackLimit(): Int {\n        return 0\n    }\n\n    override fun canTakeStack(playerIn: EntityPlayer): Boolean {\n        return false\n    }\n}\n\nclass GhostItemSlot(\n    inventoryIn: IInventory,\n    index: Int,\n    xPosition: Int,\n    yPosition: Int,\n) : GhostSlot(\n    inventoryIn = inventoryIn,\n    index = index,\n    xPosition = xPosition,\n    yPosition = yPosition,\n), Item\n\nopen class FuzzyItemSlot(\n    inventoryIn: IInventory,\n    index: Int,\n    xPosition: Int,\n    yPosition: Int,\n    val usedFlags: EnumSet<FuzzyFlag>,\n    val flagGetter: () -> IBitSet,\n) : GhostSlot(\n    inventoryIn = inventoryIn,\n    index = index,\n    xPosition = xPosition,\n    yPosition = yPosition,\n), Fuzzy, Item\n\nclass UnmodifiableItemSlot(\n    slot: Slot,\n) : GhostSlot(\n    inventoryIn = slot.inventory,\n    index = slot.slotIndex,\n    xPosition = slot.xPos,\n    yPosition = slot.yPos,\n), Unmodifiable, Item\n\nclass FuzzyUnmodifiableItemSlot(\n    fuzzySlot: FuzzyItemSlot,\n) : FuzzyItemSlot(\n    inventoryIn = fuzzySlot.inventory,\n    index = fuzzySlot.slotIndex,\n    xPosition = fuzzySlot.xPos,\n    yPosition = fuzzySlot.yPos,\n    usedFlags = fuzzySlot.usedFlags,\n    flagGetter = fuzzySlot.flagGetter,\n), Unmodifiable\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/LPGuiButton.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.guidebook.MouseInteractable\nimport network.rs485.logisticspipes.util.IRectangle\n\nabstract class LPGuiButton(\n    parent: Drawable,\n    xPosition: HorizontalAlignment,\n    yPosition: VerticalAlignment,\n    xSize: Size,\n    ySize: Size,\n    margin: Margin,\n    val onClickAction: ((Int) -> Boolean),\n) : LPGuiWidget(\n    parent = parent,\n    xPosition = xPosition,\n    yPosition = yPosition,\n    xSize = xSize,\n    ySize = ySize,\n    margin = margin,\n), MouseInteractable {\n\n    var visible: Boolean = true\n    var enabled: Boolean = true\n\n    val helper = GuiDrawer\n\n    final override val minWidth: Int = 20\n    override val minHeight: Int = 20\n\n    override val maxHeight: Int = 20\n    override val maxWidth: Int = 100\n\n    override fun initWidget() {\n        setSize(minWidth, minHeight)\n    }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        if (visible) {\n            helper.drawBorderedTile(\n                rect = absoluteBody,\n                hovered = isMouseHovering(mouseX, mouseY),\n                enabled = enabled,\n                light = false,\n                thickerBottomBorder = true,\n            )\n        }\n    }\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean = absoluteBody.contains(mouseX, mouseY)\n\n    override fun mouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int): Boolean =\n        onClickAction.invoke(mouseButton)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/LPGuiWidget.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.guidebook.MouseHoverable\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\ninterface Tooltipped : MouseHoverable {\n    fun getTooltipText(): List<String>\n}\n\nabstract class LPGuiWidget(\n    parent: Drawable,\n    val xPosition: HorizontalAlignment,\n    val yPosition: VerticalAlignment,\n    val xSize: Size,\n    val ySize: Size,\n    var margin: Margin,\n) : Drawable {\n    override var parent: Drawable? = parent\n\n    final override val relativeBody: MutableRectangle = MutableRectangle()\n\n    abstract val minWidth: Int\n    abstract val minHeight: Int\n\n    abstract val maxWidth: Int\n    abstract val maxHeight: Int\n\n    abstract fun initWidget()\n\n    open fun setSize(newWidth: Int = relativeBody.roundedWidth, newHeight: Int = relativeBody.roundedHeight) {\n        relativeBody.setSize(newWidth, newHeight)\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/Label.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.gui.Gui\nimport net.minecraft.client.renderer.GlStateManager\nimport network.rs485.logisticspipes.util.TextUtil\nimport network.rs485.logisticspipes.util.math.MutableRectangle\nimport network.rs485.logisticspipes.util.opaque\n\nopen class Label(fullText: String, internal val x: Int, internal val y: Int, internal val maxLength: Int, internal val textColor: Int, internal val backgroundColor: Int) : Gui() {\n\n    open val overflows: Boolean get() = fullRect.width > maxLength\n\n    internal val fontRenderer = Minecraft.getMinecraft().fontRenderer\n\n    internal val fullRect = MutableRectangle().setPos(x, y)\n    internal val trimmedRect = MutableRectangle().setPos(x, y)\n\n    internal var fullText: String = \"\"\n    internal var trimmedText: String = \"\"\n    internal var hovered = false\n\n    init {\n        setText(fullText)\n    }\n\n    open fun draw(mouseX: Int, mouseY: Int) {\n        hovered = hovered(mouseX, mouseY)\n        GlStateManager.pushMatrix()\n        GlStateManager.translate(fullRect.x0, fullRect.y0, 0.0f)\n        if (overflows && hovered) {\n            drawGradientRect(0, -1, fullRect.roundedWidth, fullRect.roundedHeight + 1, backgroundColor, backgroundColor)\n            // Outlines\n            LogisticsBaseGuiScreen.drawHorizontalGradientRect(fullRect.roundedWidth, -2, fullRect.roundedWidth + 1, fullRect.roundedHeight + 1, 0, textColor.opaque(), textColor.opaque())\n            LogisticsBaseGuiScreen.drawHorizontalGradientRect(0, -2, fullRect.roundedWidth, -1, 0, 0x0, textColor.opaque())\n            LogisticsBaseGuiScreen.drawHorizontalGradientRect(0, fullRect.roundedHeight, fullRect.roundedWidth, fullRect.roundedHeight + 1, 0, 0x0, textColor.opaque())\n            fullText\n        } else {\n            trimmedText\n        }.also {\n            fontRenderer.drawString(it, 0, 0, textColor)\n        }\n        GlStateManager.translate(-fullRect.x0, -fullRect.y0, 0.0f)\n        GlStateManager.popMatrix()\n    }\n\n    open fun setText(newFullText: String) {\n        fullText = newFullText\n        fullRect.setSize(fontRenderer.getStringWidth(fullText), fontRenderer.FONT_HEIGHT)\n\n        trimmedText = TextUtil.getTrimmedString(fullText, maxLength, fontRenderer)\n        trimmedRect.setSize(fontRenderer.getStringWidth(trimmedText), fontRenderer.FONT_HEIGHT)\n\n        val offset = (maxLength - trimmedRect.roundedWidth) / 2\n        fullRect.setPos(x + offset, y)\n        trimmedRect.setPos(x + offset, y)\n    }\n\n    fun isTextEqual(text: String): Boolean = fullText === text\n\n    internal fun hovered(mouseX: Int, mouseY: Int): Boolean = (if (hovered) fullRect else trimmedRect).contains(mouseX, mouseY)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/LabelWidget.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport network.rs485.logisticspipes.gui.*\nimport net.minecraft.client.renderer.GlStateManager\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.gui.guidebook.MouseHoverable\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport network.rs485.logisticspipes.util.math.MutableRectangle\n\nclass LabelWidget(\n    parent: Drawable,\n    width: Int,\n    xPosition: HorizontalAlignment,\n    yPosition: VerticalAlignment,\n    xSize: Size,\n    margin: Margin,\n    private var text: String,\n    private val textColor: Int,\n    private val textAlignment: HorizontalAlignment,\n    private var extendable: Boolean,\n    private var backgroundColor: Int,\n) : LPGuiWidget(\n    parent = parent,\n    xPosition = xPosition,\n    yPosition = yPosition,\n    xSize = xSize,\n    ySize = Size.FIXED,\n    margin = margin,\n), MouseHoverable, Tooltipped {\n\n    private var overflowing: Boolean = false\n\n    override val minWidth: Int = when (xSize) {\n        Size.FIXED -> {\n            width\n        }\n\n        Size.MIN -> {\n            text.width() + 2\n        }\n\n        Size.GROW -> {\n            30\n        }\n    }\n\n    override val minHeight: Int = GuiDrawer.mcFontRenderer.FONT_HEIGHT + 1\n\n    override val maxWidth: Int = parent.height\n    override val maxHeight: Int = parent.height\n\n    private var trimmedText = trimText(text)\n    private val fullBody = MutableRectangle()\n\n    override fun initWidget() {\n        setSize(minWidth, minHeight)\n        updateConstraints()\n    }\n\n    fun updateText(newText: String) {\n        text = newText\n        updateConstraints()\n    }\n\n    private fun updateConstraints() {\n        trimmedText = trimText(text)\n        fullBody.setPosFromRectangle(absoluteBody).translate(translateY = -2).grow(1)\n        fullBody.setSize(text.width(), minHeight)\n        overflowing = text != trimmedText\n    }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        val hovering = isMouseHovering(mouseX, mouseY)\n        GlStateManager.pushMatrix()\n        GlStateManager.enableDepth()\n        if (hovering && overflowing && extendable) {\n            GuiDrawer.drawRect(fullBody.translated(absoluteBody), backgroundColor)\n        }\n        val (effectiveAlignment, effectiveText) = if (overflowing) {\n            HorizontalAlignment.LEFT to if (hovering && extendable) text else trimmedText\n        } else {\n            textAlignment to text\n        }\n        GuiDrawer.mcFontRenderer.drawString(\n            effectiveText,\n            when (effectiveAlignment) {\n                HorizontalAlignment.LEFT -> absoluteBody.roundedLeft\n                HorizontalAlignment.CENTER -> absoluteBody.roundedLeft + (width - effectiveText.width()) / 2\n                HorizontalAlignment.RIGHT -> absoluteBody.roundedRight - effectiveText.width()\n            },\n            absoluteBody.roundedY,\n            textColor\n        )\n        GlStateManager.disableDepth()\n        GlStateManager.popMatrix()\n    }\n\n    private fun trimText(text: String): String {\n        return TextUtil.getTrimmedString(text, width, GuiDrawer.mcFontRenderer)\n    }\n\n    override fun setSize(newWidth: Int, newHeight: Int) {\n        relativeBody.setSize(newWidth, newHeight)\n        updateConstraints()\n    }\n\n    override fun getTooltipText(): List<String> = if (overflowing && !extendable) {\n        listOf(text)\n    } else {\n        emptyList()\n    }\n\n    override fun isMouseHovering(mouseX: Float, mouseY: Float): Boolean = absoluteBody.contains(mouseX, mouseY)\n\n    private fun String.width() = GuiDrawer.mcFontRenderer.getStringWidth(this)\n\n    override fun toString(): String {\n        return \"LabelWidget: $text, $absoluteBody\"\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/LockedSlot.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.inventory.Slot\nimport net.minecraft.item.ItemStack\n\nclass LockedSlot(inventoryIn: IInventory, index: Int, xPosition: Int, yPosition: Int) : Slot(inventoryIn, index, xPosition, yPosition) {\n    override fun canTakeStack(playerIn: EntityPlayer): Boolean = false\n    override fun isItemValid(stack: ItemStack): Boolean = false\n}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/PlayerInventorySlotGroup.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport net.minecraft.inventory.Slot\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\n\nclass PlayerInventorySlotGroup(\n    parent: Drawable,\n    xPosition: HorizontalAlignment,\n    yPosition: VerticalAlignment,\n    margin: Margin,\n    val slots: List<Slot>\n) : LPGuiWidget(\n    parent = parent,\n    xPosition = xPosition,\n    yPosition = yPosition,\n    xSize = Size.FIXED,\n    ySize = Size.FIXED,\n    margin = margin,\n) {\n    override val minWidth: Int = 9 * 18\n    override val minHeight: Int = 4 * 18 + 4\n\n    override val maxWidth: Int = minWidth\n    override val maxHeight: Int = minHeight\n\n    override fun initWidget() {\n        assert(slots.size == 4 * 9)\n        setSize(minWidth, minHeight)\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        super.setPos(x, y)\n        val startX = absoluteBody.roundedX + 1\n        val startY = absoluteBody.roundedY + 1\n        val slotSize = 18\n        var index = 0\n        for (row in 0 until 3) {\n            for (column in 0 until 9) {\n                slots[index].apply {\n                    xPos = startX + column * slotSize\n                    yPos = startY + row * slotSize\n                }\n                index++\n            }\n        }\n\n        // Add the hotbar inventory slots\n        for (column in 0 until 9) {\n            slots[index].apply {\n                xPos = startX + column * slotSize\n                yPos = startY + 3 * slotSize + 4\n            }\n            index++\n        }\n        return width to height\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/SlotGroup.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport net.minecraft.inventory.Slot\nimport network.rs485.logisticspipes.gui.*\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\n\nclass SlotGroup(\n    parent: Drawable,\n    xPosition: HorizontalAlignment,\n    yPosition: VerticalAlignment,\n    margin: Margin,\n    val slots: List<Slot>,\n    val columns: Int,\n    val rows: Int\n) : LPGuiWidget(\n    parent = parent,\n    xPosition = xPosition,\n    yPosition = yPosition,\n    xSize = Size.FIXED,\n    ySize = Size.FIXED,\n    margin = margin,\n) {\n    override val minWidth: Int = columns * 18\n    override val minHeight: Int = rows * 18\n    override val maxWidth: Int = minWidth\n    override val maxHeight: Int = minHeight\n\n    override fun initWidget() {\n        assert(slots.size == columns * rows)\n        setSize(minWidth, minHeight)\n    }\n\n    override fun setPos(x: Int, y: Int): Pair<Int, Int> {\n        super.setPos(x, y)\n        val startX = absoluteBody.roundedX + 1\n        val startY = absoluteBody.roundedY + 1\n        val slotSize = 18\n        for (row in 0 until rows) {\n            for (column in 0 until columns) {\n                slots[column + row * rows].apply {\n                    xPos = startX + column * slotSize\n                    yPos = startY + row * slotSize\n                }\n            }\n        }\n        return width to height\n    }\n}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/TextButton.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport logisticspipes.utils.Color\nimport net.minecraft.client.renderer.GlStateManager\nimport network.rs485.logisticspipes.gui.HorizontalAlignment\nimport network.rs485.logisticspipes.gui.Margin\nimport network.rs485.logisticspipes.gui.Size\nimport network.rs485.logisticspipes.gui.VerticalAlignment\nimport network.rs485.logisticspipes.gui.guidebook.Drawable\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.TextUtil\nimport kotlin.math.roundToInt\n\nopen class TextButton(\n    parent: Drawable,\n    xPosition: HorizontalAlignment,\n    yPosition: VerticalAlignment,\n    xSize: Size,\n    ySize: Size,\n    margin: Margin,\n    text: String,\n    enabled: Boolean,\n    onClickAction: (Int) -> Boolean\n) : LPGuiButton(\n    parent = parent,\n    xPosition = xPosition,\n    yPosition = yPosition,\n    xSize = xSize,\n    ySize = ySize,\n    margin = margin,\n    onClickAction = onClickAction\n), Tooltipped {\n\n    override val minHeight: Int = 20\n\n    init {\n        this.enabled = enabled\n    }\n\n    var text: String = text\n        set(value) {\n            field = value\n            trimmedText = trimText(value)\n        }\n    private var trimmedText: String = trimText(text)\n    val yOffset: Int = ((relativeBody.roundedHeight - helper.mcFontRenderer.FONT_HEIGHT) / 2) + 1\n    private val centerX: Float\n        get() = relativeBody.width / 2\n\n    override fun setSize(newWidth: Int, newHeight: Int) {\n        super.setSize(newWidth, newHeight)\n        text = text\n    }\n\n    private fun trimText(text: String): String {\n        return TextUtil.getTrimmedString(text, relativeBody.roundedWidth - 4, helper.mcFontRenderer)\n    }\n\n    override fun draw(mouseX: Float, mouseY: Float, delta: Float, visibleArea: IRectangle) {\n        super.draw(mouseX, mouseY, delta, visibleArea)\n        val color = if (!enabled) {\n            Color.TEXT_DISABLED\n        } else if (isMouseHovering(mouseX, mouseY)) {\n            Color.TEXT_HOVERED\n        } else {\n            Color.TEXT_WHITE\n        }\n        val yOffset: Int = ((relativeBody.roundedHeight - helper.mcFontRenderer.FONT_HEIGHT) / 2) + 1\n        GlStateManager.enableBlend()\n        GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA)\n        helper.drawCenteredString(trimmedText, (absoluteBody.left + centerX).roundToInt(), absoluteBody.roundedY + yOffset, color.value, true)\n        GlStateManager.disableBlend()\n    }\n\n    override fun mouseClicked(mouseX: Float, mouseY: Float, mouseButton: Int): Boolean = if (enabled) {\n        onClickAction.invoke(mouseButton)\n    } else {\n        false\n    }\n\n    override fun getTooltipText(): List<String> = if (trimmedText != text) listOf(text) else emptyList()\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/gui/widget/VerticalLabel.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.gui.widget\n\nimport network.rs485.logisticspipes.util.TextUtil\nimport network.rs485.logisticspipes.util.opaque\nimport logisticspipes.utils.gui.LogisticsBaseGuiScreen\nimport net.minecraft.client.renderer.GlStateManager\n\nclass VerticalLabel(fullText: String, x: Int, y: Int, maxLength: Int, textColor: Int, backgroundColor: Int) : Label(fullText, x, y, maxLength, textColor, backgroundColor) {\n\n    override val overflows: Boolean get() = fullRect.height > maxLength\n\n    override fun draw(mouseX: Int, mouseY: Int) {\n        hovered = hovered(mouseX, mouseY)\n        GlStateManager.pushMatrix()\n        GlStateManager.translate(fullRect.x1.toDouble(), fullRect.y0.toDouble(), 500.0)\n        GlStateManager.rotate(90f, 0f, 0f, 1f)\n        if (overflows && hovered) {\n            drawGradientRect(0, -1, fullRect.roundedHeight, fullRect.roundedWidth + 1, backgroundColor, backgroundColor)\n            // Outlines\n            LogisticsBaseGuiScreen.drawHorizontalGradientRect(fullRect.roundedHeight, -2, fullRect.roundedHeight + 1, fullRect.roundedWidth + 1, 0, 0x0, textColor.opaque())\n            LogisticsBaseGuiScreen.drawHorizontalGradientRect(0, -2, fullRect.roundedHeight, -1, 0, 0x0, textColor.opaque())\n            LogisticsBaseGuiScreen.drawHorizontalGradientRect(0, fullRect.roundedWidth, fullRect.roundedHeight, fullRect.roundedWidth + 1, 0, 0x0, textColor.opaque())\n            fullText\n        } else {\n            trimmedText\n        }.also {\n            fontRenderer.drawString(it, 0, 0, textColor)\n        }\n        GlStateManager.popMatrix()\n    }\n\n    override fun setText(newFullText: String) {\n        fullText = newFullText\n        fullRect.setSize(fontRenderer.FONT_HEIGHT, fontRenderer.getStringWidth(fullText))\n\n        trimmedText = TextUtil.getTrimmedString(fullText, maxLength, fontRenderer)\n        trimmedRect.setSize(fontRenderer.FONT_HEIGHT, fontRenderer.getStringWidth(trimmedText))\n\n        val offset = (maxLength - trimmedRect.roundedHeight) / 2\n        fullRect.setPos(x, y + offset)\n        trimmedRect.setPos(x, y + offset)\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/guidebook/BookContents.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.guidebook\n\nimport com.charleskorn.kaml.Yaml\nimport com.charleskorn.kaml.YamlException\nimport kotlinx.serialization.Serializable\nimport logisticspipes.LPConstants\nimport logisticspipes.LogisticsPipes\nimport net.minecraft.client.Minecraft\nimport net.minecraft.item.Item\nimport net.minecraft.util.ResourceLocation\nimport network.rs485.logisticspipes.gui.guidebook.DrawablePage\nimport network.rs485.logisticspipes.gui.guidebook.DrawablePageFactory\nimport network.rs485.logisticspipes.util.TextUtil\nimport network.rs485.markdown.HeaderParagraph\nimport network.rs485.markdown.ImageParagraph\nimport network.rs485.markdown.MarkdownParser\nimport network.rs485.markdown.Paragraph\nimport org.apache.commons.io.FilenameUtils\nimport java.io.IOException\nimport java.nio.file.Path\nimport java.nio.file.Paths\nimport java.text.MessageFormat\n\n\nval MISSING_META = YamlPageMetadata(\"[404] the metadata was not found :P\", icon = \"logisticspipes:pipe_transport_basic\")\n\nobject BookContents {\n\n    const val MAIN_MENU_FILE = \"/main_menu.md\"\n\n    internal val specialImages = mapOf(\n        \"guide_book_404\" to \"textures/gui/guide_book_404.png\"\n    )\n\n    private val specialPages = mapOf<String, PageInfoProvider>(\n        DebugPage.FILE to DebugPage\n    )\n\n    private val cachedLoadedPages = hashMapOf<String, PageInfoProvider>()\n    private val cachedDrawablePages = hashMapOf<String, DrawablePage>()\n\n    fun get(markdownFile: String): PageInfoProvider {\n        assert(markdownFile.isNotEmpty()) { \"Cannot read an empty file\" }\n        return specialPages.getOrDefault(markdownFile, cachedLoadedPages.getOrPut(markdownFile) {\n            loadPage(markdownFile, Minecraft.getMinecraft().languageManager.currentLanguage.languageCode)\n        })\n    }\n\n    fun getDrawablePage(page: String): DrawablePage = cachedDrawablePages.getOrPut(page) {\n        DrawablePageFactory.createDrawablePage(get(page))\n    }\n\n    fun clear() {\n        cachedLoadedPages.clear()\n        cachedDrawablePages.clear()\n    }\n}\n\nprivate val metadataRegex = \"^\\\\s*<!---\\\\s*\\\\n(.*?)\\\\n\\\\s*--->\\\\s*(.*)$\".toRegex(RegexOption.DOT_MATCHES_ALL)\n\nfun loadPage(path: String, lang: String): PageInfoProvider {\n    val resolvedLocation = resolveAbsoluteLocation(resolvedLocation = Paths.get(path), language = lang).toLocation(false)\n    return try {\n        val bookFile = Minecraft.getMinecraft().resourceManager.getResource(ResourceLocation(LPConstants.LP_MOD_ID, resolvedLocation))\n        LoadedPage(\n            fileLocation = path,\n            language = lang,\n            unformattedText = bookFile.inputStream.bufferedReader().readLines().joinToString(\"\\n\"),\n        )\n    } catch (error: IOException) {\n        if (lang != \"en_us\") {\n            // Didn't find current file, checking for english version.\n            if (LogisticsPipes.isDEBUG()) LogisticsPipes.log.error(\"Language $lang for the current file ($resolvedLocation) was not found. Defaulting to en_us.\")\n            loadPage(path, \"en_us\")\n        } else {\n            // English not found, this may be normal. Maybe the previous language file pointed to a non-existent file.\n            val translatedError = MessageFormat.format(TextUtil.translate(\"misc.guide_book.missing_page\"), resolvedLocation)\n            object : PageInfoProvider {\n                override val bookmarkable: Boolean = false\n                override val language: String = lang\n                override val fileLocation: String = \"\"\n                override val metadata: YamlPageMetadata = YamlPageMetadata(\n                    title = TextUtil.translate(\"misc.guide_book.missing_page_title\"),\n                    icon = \"logisticspipes:broken_item\",\n                    menu = emptyMap()\n                )\n                override val paragraphs: List<Paragraph> = listOf(\n                    ImageParagraph(\n                        alternative = \"Not found image not found?\",\n                        imagePath = \"guide_book_404\"\n                    ),\n                    HeaderParagraph(\n                        elements = MarkdownParser.splitSpacesAndWords(translatedError),\n                        headerLevel = 1\n                    ),\n                )\n            }\n        }\n    }\n}\n\nprivate fun parseMetadata(metadataString: String, markdownFile: String): YamlPageMetadata {\n    return if (metadataString.isNotEmpty()) {\n        // Takes the metadata string and parses the YAML information\n        try {\n            Yaml.default.decodeFromString(YamlPageMetadata.serializer(), metadataString)\n        } catch (e: YamlException) {\n            LogisticsPipes.log.error(\"The following Yaml in $markdownFile is malformed! \\n$metadataString\", e)\n            MISSING_META\n        }\n    } else MISSING_META\n}\n\n/**\n * @param title title of the page\n * @param icon the icon\n * @param menu menus of the page: Map of id to (category to entries)\n */\n@Serializable\ndata class YamlPageMetadata(\n    val title: String,\n    val icon: String = \"logisticspipes:item_card\",\n    val menu: Map<String, Map<String, List<String>>> = emptyMap()\n)\n\nclass LoadedPage(override val fileLocation: String, override val language: String, unformattedText: String) : PageInfoProvider {\n    private val metadataString: String\n    private val markdownString: String\n\n    init {\n        // Splits the input string into the metadata and the markdown parts of the page.\n        val result =\n            metadataRegex.matchEntire(unformattedText) ?: throw RuntimeException(\"Could not load page, regex failed in $fileLocation:\\n$unformattedText\")\n        metadataString = result.groups[1]?.value?.trim() ?: \"\"\n        markdownString = result.groups[2]?.value?.trim() ?: \"\"\n    }\n\n    override val metadata: YamlPageMetadata by lazy {\n        parseMetadata(metadataString, fileLocation).also {\n            if (LogisticsPipes.isDEBUG()) {\n                try {\n                    it.icon.split(\":\").apply {\n                        val item = Item.REGISTRY.getObject(\n                            ResourceLocation(\n                                this@apply[0],\n                                this@apply[1],\n                            )\n                        )\n                        if (item == null) LogisticsPipes.log.error(\"Item does not exist! ${it.icon}\")\n                    }\n                } catch (e: Exception) {\n                    LogisticsPipes.log.warn(\"Problem while checking if \\\\\\\"${it.icon}\\\\\\\" exists.\")\n                }\n            }\n        }\n    }\n\n    override val paragraphs: List<Paragraph> by lazy {\n        MarkdownParser.parseParagraphs(markdownString)\n    }\n\n    override val bookmarkable: Boolean = fileLocation != BookContents.MAIN_MENU_FILE\n}\n\nfun Path.toLocation(absolute: Boolean = isAbsolute) = (if (absolute) \"/\" else \"\").plus(\n    toString()\n        .let { it.substring(FilenameUtils.getPrefixLength(it)) }\n        .let { FilenameUtils.separatorsToUnix(it) }\n)\n\nfun resolveAbsoluteLocation(resolvedLocation: Path, language: String): Path =\n    Paths.get(\"book/$language\").let { base ->\n        resolvedLocation.normalize()\n            .filter { path -> !path.startsWith(\"..\") }\n            .fold(base, Path::resolve)\n    }\n\ninterface PageInfoProvider {\n    fun resolveLocation(location: String): Path = Paths.get(fileLocation).resolveSibling(location).normalize()\n    fun resolveResource(location: String): ResourceLocation =\n        location.lastIndexOf(':').let { idx ->\n            val resourceDomain = when (idx) {\n                -1 -> LPConstants.LP_MOD_ID\n                else -> location.substring(0 until idx)\n            }\n            var resourcePath: String = ((idx + 1)..location.lastIndex).let { if (it.isEmpty()) \"\" else location.substring(it) }\n            resourcePath = BookContents.specialImages.getOrDefault(\n                key = resourcePath,\n                defaultValue = resolveAbsoluteLocation(resolveLocation(resourcePath), language).toLocation(false)\n            )\n            ResourceLocation(resourceDomain, resourcePath)\n        }\n\n    val language: String\n    val fileLocation: String\n    val metadata: YamlPageMetadata\n    val paragraphs: List<Paragraph>\n    val bookmarkable: Boolean\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/guidebook/DebugPage.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.guidebook\n\nimport logisticspipes.utils.MinecraftColor\nimport network.rs485.markdown.*\nimport java.util.*\nimport kotlin.random.Random\n\nobject DebugPage : PageInfoProvider {\n    private fun randomColor(): Int = MinecraftColor.values()[Random.nextInt(MinecraftColor.values().size)].colorCode\n\n    const val FILE = \"/debug/debug_page.md\"\n\n    override val bookmarkable: Boolean = false\n    override val fileLocation = FILE\n    override val language = \"en_us\"\n    override val metadata = YamlPageMetadata(\n        title = \"Debug Page\",\n        icon = \"logisticspipes:item_card\",\n        menu = mapOf(\n            \"listed\" to mapOf(\n                \"Guides:\" to listOf(\n                    \"/guides/quickstart_guide.md\",\n                    \"/guides/start_guide.md\",\n                    \"/guides/intermediate_guide.md\",\n                    \"/guides/advanced_guide.md\",\n                    \"/guides/in_depth.md\",\n                    \"/guides/not_found.md\",\n                )\n            )\n        )\n    )\n    override val paragraphs: List<Paragraph> = listOf(\n        MenuParagraph(\n            description = \"A listed menu.\",\n            link = \"listed\",\n            type = MenuParagraphType.LIST,\n        ),\n        MenuParagraph(\n            description = \"A menu.\",\n            link = \"listed\",\n            type = MenuParagraphType.TILE,\n        ),\n        ImageParagraph(\n            alternative = \"This image failed loading\",\n            imagePath = \"/guides/test_image.png\",\n        ),\n        HeaderParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Shadow))),\n                MarkdownParser.splitSpacesAndWords(\n                    \"Nulla faucibus cursus bibendum.\"\n                ).map {\n                    if (it is Word) listOf(ColorFormatting(randomColor()), it) else listOf(it)\n                }.flatten(),\n            ).flatten(), headerLevel = 4\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.of(TextFormat.Bold, TextFormat.Shadow))),\n                listOf(LinkFormatting(PageLink(\"/cantfindme.md\")), Word(\"Hello\"), Space, Word(\"World\"), LinkFormatting(null), Break),\n                listOf(ColorFormatting(randomColor())),\n                MarkdownParser.splitSpacesAndWords(\n                    \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vel sapien nisl.\"\n                ),\n            ).flatten()\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(ColorFormatting(randomColor())),\n                listOf(TextFormatting(EnumSet.of(TextFormat.Bold, TextFormat.Italic))),\n                MarkdownParser.splitWhitespaceCharactersAndWords(\n                    \"Phasellus ut ipsum quis metus rutrum tempus eget in lacus. Nam at sollicitudin massa. Curabitur fringilla nisl ut quam lacinia, vel laoreet leo placerat. Aliquam erat volutpat. Nulla faucibus cursus bibendum.  \\n\" +\n                            \"Etiam porttitor sed nulla vitae vehicula. Mauris nec dolor ipsum. In eget leo malesuada, faucibus turpis a, convallis neque.\"\n                ),\n            ).flatten()\n        ),\n        HeaderParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.of(TextFormat.Strikethrough))),\n                MarkdownParser.splitSpacesAndWords(\n                    \"Nulla faucibus cursus bibendum.\"\n                ).map {\n                    if (it is Word) listOf(ColorFormatting(randomColor()), it) else listOf(it)\n                }.flatten(),\n            ).flatten(), headerLevel = 4\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.noneOf(TextFormat::class.java))),\n                listOf(ColorFormatting(randomColor())),\n                MarkdownParser.splitSpacesAndWords(\n                    \"Cras sit amet nisi velit. Etiam vitae elit quis ipsum rhoncus facilisis et ac ante.\"\n                ),\n            ).flatten(),\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.noneOf(TextFormat::class.java))),\n                listOf(ColorFormatting(randomColor())),\n                MarkdownParser.splitSpacesAndWords(\n                    \"Лорем ипсум долор сит амет, видит лаборес ест еи, мунере цомпрехенсам вим ех. \" +\n                            \"Делецтус сенсибус антиопам те сед, но мел яуидам денияуе делицатиссими, ин мелиоре \" +\n                            \"хонестатис иус. Дицта елецтрам волуптатибус но сед, вертерем праесент реферрентур \" +\n                            \"яуи еу, ад нам алияуид оффендит вулпутате. Не мел саепе еффициантур.\"\n                ),\n            ).flatten(),\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.noneOf(TextFormat::class.java))),\n                listOf(ColorFormatting(randomColor())),\n                MarkdownParser.splitSpacesAndWords(\n                    \"就ら展総ま内長ミルロム水万くし競顔北参ラテキ物36由らいおね割心社イ距公ワヱトネ労固服推野ぱお。\" +\n                            \"合ナ体2業みさイぴ米案にゆろ花内ラシカケ千自どでレま走9式オユヲ完味るょけ事養べ必選ケ最感湖わ\" +\n                            \"スろ啓際コト属健めぞ山歩マ白太苦体丘ぜ。活示よへッえ上誤歳むひぱフ報塚コタイ進左じなふ録氷隠は暮\" +\n                            \"的お音安まる自質編メシハ掲79文ユヌ演言フドろぐ事岡ホヤ小行済テサフ主挙助検引ぞー。\"\n                ),\n            ).flatten(),\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.of(TextFormat.Underline, TextFormat.Shadow))),\n                listOf(ColorFormatting(randomColor())),\n                MarkdownParser.splitSpacesAndWords(\n                    \"並城容打性様権続料左速水戸離。績相質三活活気堀防塩関遅。\" +\n                            \"版受指遠本意日念日録来能筆確文秋医含関山。法嗅瑞催東原小能調見還房。\" +\n                            \"繊軽夫開江質聖米棋河意立給研。模更辞級催京百陽審稿治年。\" +\n                            \"交呼語天値葉定表暮紙進当。掲治覧確見年造直経和挑禁在果。\" +\n                            \"介図後禁情洗崎平古伝援参天史飛権米。丈大勲社判福性書持者社方覧掲助浅。\"\n                ),\n            ).flatten(),\n        ),\n        RegularParagraph(\n            listOf(\n                listOf(TextFormatting(EnumSet.of(TextFormat.Underline, TextFormat.Italic))),\n                listOf(ColorFormatting(randomColor())),\n                MarkdownParser.splitWhitespaceCharactersAndWords(\n                    \"Phasellus ut ipsum quis metus rutrum tempus eget in lacus. Nam at sollicitudin massa.\\n\" +\n                            \"Curabitur fringilla nisl ut quam lacinia, vel laoreet leo placerat. Aliquam erat volutpat. Nulla faucibus cursus bibendum.\\n\" +\n                            \"Etiam porttitor sed nulla vitae vehicula. Mauris nec dolor ipsum. In eget leo malesuada, faucibus turpis a, convallis neque.\"\n                ),\n            ).flatten(),\n        ),\n    )\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/guidebook/ItemGuideBook.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.guidebook\n\nimport logisticspipes.items.LogisticsItem\nimport logisticspipes.network.PacketHandler\nimport logisticspipes.network.guis.OpenGuideBook\nimport logisticspipes.proxy.MainProxy\nimport net.minecraft.client.Minecraft\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.EntityEquipmentSlot\nimport net.minecraft.item.ItemStack\nimport net.minecraft.nbt.NBTTagCompound\nimport net.minecraft.nbt.NBTTagList\nimport net.minecraft.util.ActionResult\nimport net.minecraft.util.EnumActionResult\nimport net.minecraft.util.EnumHand\nimport net.minecraft.world.World\nimport network.rs485.logisticspipes.gui.guidebook.GuiGuideBook\nimport network.rs485.logisticspipes.gui.guidebook.IPageData\nimport network.rs485.logisticspipes.gui.guidebook.PageData\nimport network.rs485.logisticspipes.gui.guidebook.Page\nimport network.rs485.logisticspipes.network.packets.SetCurrentPagePacket\n\nclass ItemGuideBook : LogisticsItem() {\n\n    companion object {\n        /**\n         * Loads the current page and the tabs from the stack's NBT. Returns Pair(currentPage, Tabs)\n         */\n        private fun loadDataFromNBT(stack: ItemStack): Pair<PageData, List<PageData>> {\n            var currentPage: PageData? = null\n            var tabPages: List<PageData>? = null\n            if (stack.hasTagCompound()) {\n                val nbt = stack.tagCompound!!\n                if (nbt.hasKey(\"version\")) {\n                    when (nbt.getByte(\"version\")) {\n                        1.toByte() -> {\n                            currentPage = PageData(nbt.getCompoundTag(\"page\"))\n                            // type 10 = NBTTagCompound, see net.minecraft.nbt.NBTBase.createNewByType\n                            val tagList = nbt.getTagList(\"bookmarks\", 10)\n                            tabPages = tagList.mapNotNull { tag -> PageData(tag as NBTTagCompound) }\n                        }\n                    }\n                }\n            }\n            currentPage = currentPage ?: PageData(BookContents.MAIN_MENU_FILE)\n            tabPages = tabPages ?: emptyList()\n            return currentPage to tabPages\n        }\n\n        @JvmStatic\n        fun openGuideBook(hand: EnumHand, stack: ItemStack) {\n            val mc = Minecraft.getMinecraft()\n            val equipmentSlot = if (hand == EnumHand.MAIN_HAND) EntityEquipmentSlot.MAINHAND else EntityEquipmentSlot.OFFHAND\n            // add scheduled task to switch from network thread to main thread with OpenGL context\n            mc.addScheduledTask {\n                val state = loadDataFromNBT(stack).let {\n                    GuideBookState(equipmentSlot, Page(it.first), it.second.map(::Page))\n                }\n                mc.displayGuiScreen(GuiGuideBook(state))\n            }\n        }\n    }\n\n    init {\n        maxStackSize = 1\n    }\n\n    class GuideBookState(val equipmentSlot: EntityEquipmentSlot, var currentPage: Page, bookmarks: List<Page>) {\n        val bookmarks = bookmarks.toMutableList()\n    }\n\n    fun updateNBT(tag: NBTTagCompound, page: IPageData, tabs: List<IPageData>) = tag.apply {\n        setByte(\"version\", 1)\n        setTag(\"page\", page.toTag())\n        setTag(\"bookmarks\", NBTTagList().apply {\n            tabs.map(IPageData::toTag).forEach(::appendTag)\n        })\n    }\n\n    override fun onItemRightClick(world: World, player: EntityPlayer, hand: EnumHand): ActionResult<ItemStack> {\n        val stack = player.getHeldItem(hand)\n        if (stack.item is ItemGuideBook && MainProxy.isServer(world)) {\n            MainProxy.sendPacketToPlayer(\n                PacketHandler.getPacket(OpenGuideBook::class.java).setHand(hand).setStack(stack),\n                player,\n            )\n            return ActionResult(EnumActionResult.SUCCESS, stack)\n        }\n        return ActionResult(EnumActionResult.PASS, stack)\n    }\n\n    fun saveState(state: GuideBookState) {\n        val stack = Minecraft.getMinecraft().player.getItemStackFromSlot(state.equipmentSlot)\n        val compound = if (stack.hasTagCompound()) stack.tagCompound!! else NBTTagCompound()\n        // update NBT for the client\n        stack.tagCompound = updateNBT(compound, state.currentPage, state.bookmarks)\n\n        // … and for the server\n        MainProxy.sendPacketToServer(\n            PacketHandler.getPacket(SetCurrentPagePacket::class.java)\n                .setEquipmentSlot(state.equipmentSlot)\n                .setCurrentPage(state.currentPage)\n                .setBookmarks(state.bookmarks)\n        )\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/FuzzySlotAccess.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.inventory\n\nimport network.rs485.logisticspipes.property.BitSetProperty\nimport network.rs485.logisticspipes.property.IBitSet\n\nclass FuzzySlotAccess(\n    private val slotAccess: SlotAccess, private val fuzzyFlags: BitSetProperty\n) : SlotAccess {\n\n    private fun bitsForSlot(idx: Int): IBitSet =\n        (idx * 4).let { fuzzyFlags.get(it, it + 3) }\n\n    override fun mergeSlots(intoSlot: Int, fromSlot: Int) {\n        slotAccess.mergeSlots(intoSlot, fromSlot)\n        bitsForSlot(intoSlot).replaceWith(bitsForSlot(fromSlot))\n        bitsForSlot(fromSlot).clear()\n    }\n\n    override fun canMerge(intoSlot: Int, fromSlot: Int): Boolean =\n        slotAccess.canMerge(intoSlot, fromSlot)\n                && (isSlotEmpty(intoSlot) || bitsForSlot(intoSlot) == bitsForSlot(fromSlot))\n\n    override fun isSlotEmpty(idx: Int): Boolean = slotAccess.isSlotEmpty(idx)\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/IItemIdentifierInventory.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\npackage network.rs485.logisticspipes.inventory\n\nimport logisticspipes.interfaces.IClientInformationProvider\nimport logisticspipes.proxy.computers.interfaces.ILPCCTypeHolder\nimport logisticspipes.utils.ISimpleInventoryEventHandler\nimport logisticspipes.utils.item.ItemIdentifier\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport logisticspipes.utils.tuples.Pair\nimport net.minecraft.inventory.IInventory\n\ninterface IItemIdentifierInventory : IInventory, ILPCCTypeHolder, IClientInformationProvider {\n    val itemsAndCount: Map<ItemIdentifier, Int>\n    val slotAccess: SlotAccess\n    fun getIDStackInSlot(i: Int): ItemIdentifierStack?\n    fun setInventorySlotContents(i: Int, itemstack: ItemIdentifierStack?)\n    fun containsItem(item: ItemIdentifier?): Boolean\n    fun handleItemIdentifierList(_allItems: Collection<ItemIdentifierStack>)\n    fun addListener(listener: ISimpleInventoryEventHandler)\n    fun removeListener(listener: ISimpleInventoryEventHandler)\n    fun containsUndamagedItem(item: ItemIdentifier): Boolean\n    fun containsExcludeNBTItem(item: ItemIdentifier): Boolean\n    fun containsUndamagedExcludeNBTItem(item: ItemIdentifier): Boolean\n    fun itemCount(item: ItemIdentifier): Int\n    fun contents(): Iterable<Pair<ItemIdentifierStack, Int>>\n    fun recheckStackLimit()\n    fun clearInventorySlotContents(i: Int)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/ProviderMode.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.inventory\n\n@Suppress(\"unused\") // these are saved/restored by values() index\nenum class ProviderMode(\n    translationName: String,\n    val hideOnePerStack: Boolean,\n    val hideOnePerType: Boolean,\n    val cropStart: Int,\n    val cropEnd: Int,\n) {\n    DEFAULT(\"Normal\", false, false, 0, 0),\n    LEAVE_FIRST(\"LeaveFirst\", false, false, 1, 0),\n    LEAVE_LAST(\"LeaveLast\", false, false, 0, 1),\n    LEAVE_FIRST_AND_LAST(\"LeaveFirstAndLast\", false, false, 1, 1),\n    LEAVE_ONE_PER_STACK(\"Leave1PerStack\", true, false, 0, 0),\n    LEAVE_ONE_PER_TYPE(\"Leave1PerType\", false, true, 0, 0);\n\n    val modeTranslationKey = \"misc.extractionmode.$translationName\"\n\n    companion object {\n        @JvmStatic\n        fun modeFromIntSafe(id: Int): ProviderMode = values().getOrNull(id) ?: DEFAULT\n\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/SlotAccess.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.inventory\n\ninterface SlotAccess {\n\n    fun compactFirst(size: Int) {\n        for (firstSlot in 0 until size) {\n            for (secondSlot in firstSlot + 1 until size) {\n                if (!isSlotEmpty(secondSlot) && (isSlotEmpty(firstSlot) || canMerge(firstSlot, secondSlot))) {\n                    mergeSlots(firstSlot, secondSlot)\n                }\n            }\n        }\n    }\n\n    fun mergeSlots(intoSlot: Int, fromSlot: Int)\n\n    fun canMerge(intoSlot: Int, fromSlot: Int): Boolean\n\n    fun isSlotEmpty(idx: Int): Boolean\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/container/ItemSinkContainer.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.inventory.container\n\nimport network.rs485.logisticspipes.gui.widget.GhostSlot\nimport network.rs485.logisticspipes.property.InventoryProperty\nimport network.rs485.logisticspipes.property.layer.PropertyLayer\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay\nimport network.rs485.logisticspipes.property.layer.PropertyOverlayInventoryAdapter\nimport network.rs485.logisticspipes.util.FuzzyFlag\nimport logisticspipes.modules.ModuleItemSink\nimport logisticspipes.utils.item.ItemIdentifierInventory\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\nimport java.util.*\n\nclass ItemSinkContainer(\n    playerInventory: IInventory,\n    filterInventoryOverlay: PropertyOverlay<ItemIdentifierInventory, out InventoryProperty<ItemIdentifierInventory>>,\n    itemSinkModule: ModuleItemSink,\n    propertyLayer: PropertyLayer, // FIXME: property layer should not be passed into the container, it is a client GUI thing\n    val isFuzzy: Boolean,\n    val moduleInHand: ItemStack,\n) : LPBaseContainer<ModuleItemSink>(itemSinkModule) {\n\n    private val flags = EnumSet.of(FuzzyFlag.IGNORE_NBT, FuzzyFlag.IGNORE_DAMAGE)\n\n    val fuzzyFlagOverlay = propertyLayer.overlay(itemSinkModule.fuzzyFlags)\n\n    val playerSlots = addPlayerSlotsToContainer(\n        playerInventoryIn = playerInventory,\n        startX = 0,\n        startY = 0,\n        lockedStack = moduleInHand,\n    )\n\n    val filterSlots = addDummySlotsToContainer(\n        overlayInventory = PropertyOverlayInventoryAdapter(filterInventoryOverlay),\n        baseProperty = module.filterInventory,\n        startX = 0,\n        startY = 0,\n    )\n\n    override fun addDummySlotsToContainer(\n        overlayInventory: IInventory,\n        baseProperty: InventoryProperty<*>?,\n        startX: Int,\n        startY: Int\n    ): List<GhostSlot> {\n        val filterSlots = mutableListOf<GhostSlot>()\n\n        for (column in 0 until 9) {\n            filterSlots.add(\n                if (isFuzzy) {\n                    addFuzzyItemSlotToContainer(\n                        dummyInventoryIn = overlayInventory,\n                        baseProperty = baseProperty,\n                        slotId = column,\n                        posX = startX + column * slotSize,\n                        posY = startY,\n                        usedFlags = flags,\n                    ) {\n                        fuzzyFlagOverlay.read { p ->\n                            p.get(column * 4, column * 4 + 3)\n                        }\n                    }\n                } else {\n                    addGhostItemSlotToContainer(\n                        dummyInventoryIn = overlayInventory,\n                        baseProperty = baseProperty,\n                        slotId = column,\n                        posX = startX + column * slotSize,\n                        posY = startY,\n                    )\n                },\n            )\n        }\n\n        return filterSlots\n    }\n\n    override fun canInteractWith(playerIn: EntityPlayer): Boolean = true\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/container/LPBaseContainer.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.inventory.container\n\nimport network.rs485.logisticspipes.gui.widget.*\nimport network.rs485.logisticspipes.property.IBitSet\nimport network.rs485.logisticspipes.property.InventoryProperty\nimport network.rs485.logisticspipes.util.FuzzyFlag\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.modules.LogisticsModule\nimport logisticspipes.utils.gui.ModuleSlot\nimport net.minecraftforge.fml.relauncher.Side\nimport net.minecraftforge.fml.relauncher.SideOnly\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.*\nimport net.minecraft.item.ItemStack\nimport java.util.*\nimport kotlin.math.min\n\nabstract class LPBaseContainer<out M : LogisticsModule>(val module: M) : Container() {\n\n    val slotSize = 18\n\n    private val playerHotbarSlots = mutableListOf<Slot>()\n    private val playerBackpackSlots = mutableListOf<Slot>()\n    private val directSlotPropertyMap = mutableMapOf<Slot, InventoryProperty<*>>()\n\n    /**\n     * Add container-specific's DummySlots to the Container's slot list.\n     * This should be implemented in a per-container basis.\n     * @param overlayInventory  dummy inventory from which the slots will be grabbed.\n     * @param startX            starting leftmost position.\n     * @param startY            starting bottommost position.\n     * @return the list of added lots.\n     */\n    abstract fun addDummySlotsToContainer(\n        overlayInventory: IInventory,\n        baseProperty: InventoryProperty<*>? = null,\n        startX: Int,\n        startY: Int\n    ): List<GhostSlot>\n\n    /**\n     * Add DummySlot to the Container's slot list.\n     * @param dummyInventoryIn slot's inventory.\n     * @param slotId id to be given to the slot\n     */\n    fun addGhostItemSlotToContainer(\n        dummyInventoryIn: IInventory,\n        baseProperty: InventoryProperty<*>?,\n        slotId: Int,\n        posX: Int,\n        posY: Int\n    ): GhostItemSlot {\n        val slot = GhostItemSlot(\n            inventoryIn = dummyInventoryIn,\n            index = slotId,\n            xPosition = posX,\n            yPosition = posY,\n        )\n        addSlotToContainer(slot)\n        baseProperty?.let { directSlotPropertyMap[slot] = it }\n        return slot\n    }\n\n\n    fun addFuzzyItemSlotToContainer(\n        dummyInventoryIn: IInventory,\n        baseProperty: InventoryProperty<*>?,\n        slotId: Int,\n        posX: Int,\n        posY: Int,\n        usedFlags: EnumSet<FuzzyFlag>,\n        flagGetter: () -> IBitSet,\n    ): FuzzyItemSlot {\n        val slot = FuzzyItemSlot(\n            inventoryIn = dummyInventoryIn,\n            index = slotId,\n            xPosition = posX,\n            yPosition = posY,\n            usedFlags = usedFlags,\n            flagGetter = flagGetter,\n        )\n        addSlotToContainer(slot)\n        baseProperty?.let { directSlotPropertyMap[slot] = it }\n        return slot\n    }\n\n\n    override fun slotClick(slotId: Int, dragType: Int, clickTypeIn: ClickType, player: EntityPlayer): ItemStack {\n\n        // slotId -999 is a special case for when the ItemStack is being drag-split between slots.\n        if (slotId < 0) {\n            return super.slotClick(slotId, dragType, clickTypeIn, player)\n        }\n\n        val slot = inventorySlots[slotId] ?: return ItemStack.EMPTY\n\n        if (slot is LockedSlot) return ItemStack.EMPTY\n\n        if (slot !is GhostSlot) {\n            // In case slot is not a subtype of GhostSlot vanilla behaviour will be applied.\n            return super.slotClick(slotId, dragType, clickTypeIn, player)\n        }\n\n        // The slot will always be a subtype of GhostSlot from this point onwards.\n        val grabbedItemStack = player.inventory.itemStack\n        handleGhostSlotClick(slot, grabbedItemStack, dragType, clickTypeIn, player)\n        return ItemStack.EMPTY\n\n    }\n\n    /**\n     * Transfers items back and forth from the player's backpack and hotbar.\n     * Override and return this to add extra functionality.\n     * @param player player accessing the container\n     * @param index of the slot in the inventorySlots list.\n     * @return empty ItemStack to stop the weird loop that vanilla runs using this.\n     */\n    override fun transferStackInSlot(player: EntityPlayer, index: Int): ItemStack {\n        val slot = inventorySlots[index] ?: return ItemStack.EMPTY\n        if (!slot.hasStack || slot is GhostSlot || slot is ModuleSlot) return ItemStack.EMPTY\n        when {\n            playerHotbarSlots.contains(slot) -> handleShiftClickFromSlotToList(slot, playerBackpackSlots, player)\n            playerBackpackSlots.contains(slot) -> handleShiftClickFromSlotToList(slot, playerHotbarSlots, player)\n            else -> LogisticsPipes.log.warn(\"Something is wrong, this slot is not apart of the player's inventory and wasn't dealt with properly before.\")\n        }\n        return ItemStack.EMPTY\n    }\n\n    /**\n     * Runs the code to check and add any item that would normally be added by running [transferStackInSlot].\n     * This is useful to bring client-side shift-clicking functionality to property-based GUIs.\n     * @return true, if a ghost slot did take the item and false if the transfer should be handled elsewhere.\n     */\n    open fun tryTransferSlotToGhostSlot(slotIdx: Int): Boolean = false\n\n    /**\n     * Attempts to transfer the stack to one or more slots in the list.\n     * @param from slot sending stack\n     * @param toList slots possibly receiving stack\n     * @param player player interacting with the container\n     * @return true when the shifted stack was fully utilized, false otherwise\n     */\n    open fun handleShiftClickFromSlotToList(from: Slot, toList: List<Slot>, player: EntityPlayer): Boolean {\n        if (!from.hasStack) return true\n        val slots = toList.partition { it.hasStack }\n        // Iterate through all non-empty slots and then through all empty slots until the initial slot is depleted or it fails.\n        slots.first.takeIf { it.isNotEmpty() }\n            ?.forEach { to -> if (handleShiftClickFromSlotToSlot(from, to, player)) return true }\n        slots.second.takeIf { it.isNotEmpty() }\n            ?.forEach { to -> if (handleShiftClickFromSlotToSlot(from, to, player)) return true }\n        return false\n    }\n\n    /**\n     * Attempts to shift a stack from one stack from the other.\n     * @param from slot sending stack\n     * @param to slot receiving stack\n     * @param player player interacting with the container\n     * @return true when from is empty false when no action taken\n     */\n    open fun handleShiftClickFromSlotToSlot(from: Slot, to: Slot, player: EntityPlayer): Boolean {\n        if (!from.hasStack) return true\n        if (to is GhostSlot || to is ModuleSlot) return false\n        if (to.hasStack && from.stack.isItemEqual(to.stack)) {\n            // Calculate how many items can be added to stack until it is full, can be limited by the ItemStack(Item) or the Slot.\n            val freeAmount = min(to.slotStackLimit, to.stack.maxStackSize) - to.stack.count\n            if (freeAmount > 0) {\n                // Reduce original from stack and do the same on the slot to sync.\n                var shiftedStack = from.decrStackSize(freeAmount)\n                shiftedStack = from.onTake(player, shiftedStack)\n                if (!shiftedStack.isEmpty && !to.stack.isEmpty) {\n                    // Increase count on the receiving stack and also slot to sync.\n                    to.stack.grow(shiftedStack.count)\n                    to.putStack(to.stack)\n                    return !from.hasStack\n                }\n            }\n        } else if (!to.hasStack) {\n            // Calculate how much can be added to empty slot\n            val maxAmount = min(from.stack.count, to.slotStackLimit)\n            if (maxAmount > 0) {\n                val shiftedStack = from.decrStackSize(maxAmount)\n                to.putStack(shiftedStack)\n                if (from.stack.isEmpty) from.putStack(ItemStack.EMPTY)\n            }\n            return !from.hasStack\n        }\n        return false\n    }\n\n    /**\n     * Add player 9 + 27 slots to the Container's slot list. This method currently places\n     * the slots in a grid so they work on old guis.\n     * @param playerInventoryIn player's inventory from which the slots will be grabbed.\n     * @param startX starting leftmost position.\n     * @param startY starting topmost position.\n     * @return  return all the slots in the player's inventory.\n     */\n    open fun addPlayerSlotsToContainer(\n        playerInventoryIn: IInventory,\n        startX: Int,\n        startY: Int,\n        lockedStack: ItemStack,\n    ): List<Slot> {\n\n        // Minecraft expects the 27 backpack slots to be index in 0-26 on the container list, and the hotbar\n        // corresponds to 27-35.\n\n        // Add the top 27 inventory slots\n        for (row in 0..2) {\n            for (column in 0..8) {\n                playerBackpackSlots.add(\n                    addSlotToContainer(\n                        Slot(\n                            playerInventoryIn,\n                            column + row * 9 + 9,\n                            startX + column * slotSize,\n                            startY + row * slotSize,\n                        ),\n                    ),\n                )\n            }\n        }\n\n        // Add the hotbar inventory slots\n        for (index in 0..8) {\n            if (!lockedStack.isEmpty && playerInventoryIn.getStackInSlot(index) == lockedStack) {\n                playerHotbarSlots.add(\n                    addSlotToContainer(\n                        LockedSlot(\n                            playerInventoryIn,\n                            index,\n                            startX + index * slotSize,\n                            startY + 3 * slotSize + 4,\n                        ),\n                    ),\n                )\n            } else {\n                playerHotbarSlots.add(\n                    addSlotToContainer(\n                        Slot(\n                            playerInventoryIn,\n                            index,\n                            startX + index * slotSize,\n                            startY + 3 * slotSize + 4,\n                        ),\n                    ),\n                )\n            }\n        }\n\n        return playerBackpackSlots + playerHotbarSlots\n    }\n\n    // Handle click on GhostSlot\n    private fun handleGhostSlotClick(\n        slot: GhostSlot,\n        grabbedItemStack: ItemStack,\n        dragType: Int,\n        clickTypeIn: ClickType,\n        player: EntityPlayer,\n    ) = when (slot) {\n        is Item -> handleGhostItemSlotClick(slot, grabbedItemStack, dragType, clickTypeIn, player)\n        else -> {\n            TODO(\"When did I add fluid slots?\")\n        }\n    }\n\n    /**\n     * Decide what to do based on the input received\n     * @param slot Clicked slot\n     * @param grabbedItemStack ItemStack grabbed by the mouse, EMPTY if none.\n     * @param dragType stage of multi slot dragging\n     * @param clickTypeIn type of action being performed @see ClickType\n     * @param player interacting with the container\n     */\n    open fun handleGhostItemSlotClick(\n        slot: GhostSlot,\n        grabbedItemStack: ItemStack,\n        dragType: Int,\n        clickTypeIn: ClickType,\n        player: EntityPlayer,\n    ) {\n        LogisticsPipes.log.info(\"DragType $dragType, ClickType: $clickTypeIn\")\n        // Copy the grabbedStack and insert it into the GhostItemSlot\n        if (slot !is Unmodifiable) {\n            applyItemStackToGhostItemSlot(grabbedItemStack, slot)\n        }\n    }\n\n    /**\n     * Copies given ItemStack and gives it to the given GhostItemSlot\n     * @param itemStack ItemStack to be copied\n     * @param slot target GhostItemSlot\n     */\n    open fun applyItemStackToGhostItemSlot(itemStack: ItemStack, slot: GhostSlot) {\n        val copiedItemStack = itemStack.copy()\n        slot.putStack(copiedItemStack)\n    }\n\n    override fun putStackInSlot(slotID: Int, stack: ItemStack) {\n        // external change, access underlying property directly\n        val slot = inventorySlots.getOrNull(slotID)\n        slot?.let { directSlotPropertyMap[slot] }?.also { property ->\n            property.setInventorySlotContents(slot.slotIndex, stack)\n        } ?: super.putStackInSlot(slotID, stack)\n    }\n\n    @SideOnly(Side.CLIENT)\n    override fun setAll(slotStacks: MutableList<ItemStack>) {\n        for (slotIdx in slotStacks.indices) {\n            putStackInSlot(slotIdx, slotStacks[slotIdx])\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/inventory/container/ProviderContainer.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.inventory.container\n\nimport network.rs485.logisticspipes.gui.widget.GhostItemSlot\nimport network.rs485.logisticspipes.gui.widget.GhostSlot\nimport network.rs485.logisticspipes.property.InventoryProperty\nimport network.rs485.logisticspipes.property.layer.PropertyOverlay\nimport network.rs485.logisticspipes.property.layer.PropertyOverlayInventoryAdapter\nimport logisticspipes.modules.ModuleProvider\nimport logisticspipes.utils.item.ItemIdentifierInventory\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\n\nclass ProviderContainer(\n    providerModule: ModuleProvider,\n    playerInventoryIn: IInventory,\n    filterInventoryOverlay: PropertyOverlay<ItemIdentifierInventory, out InventoryProperty<ItemIdentifierInventory>>,\n    moduleInHand: ItemStack,\n) : LPBaseContainer<ModuleProvider>(providerModule) {\n\n    val playerSlots = addPlayerSlotsToContainer(playerInventoryIn, 0, 0, moduleInHand)\n\n    val filterSlots = addDummySlotsToContainer(\n        overlayInventory = PropertyOverlayInventoryAdapter(filterInventoryOverlay),\n        baseProperty = module.filterInventory,\n        startX = 0,\n        startY = 0,\n    )\n\n    // Add 3x3 grid of dummy slots.\n    override fun addDummySlotsToContainer(\n        overlayInventory: IInventory,\n        baseProperty: InventoryProperty<*>?,\n        startX: Int,\n        startY: Int\n    ): List<GhostSlot> {\n        val filterSlots = mutableListOf<GhostSlot>()\n\n        for (row in 0..2) {\n            for (column in 0..2) {\n                filterSlots.add(\n                    addGhostItemSlotToContainer(\n                        dummyInventoryIn = overlayInventory,\n                        baseProperty = baseProperty,\n                        slotId = column + row * 3,\n                        posX = startX + column * slotSize,\n                        posY = startY + row * slotSize,\n                    ),\n                )\n            }\n        }\n\n        return filterSlots\n    }\n\n    override fun tryTransferSlotToGhostSlot(slotIdx: Int): Boolean {\n        val playerInvSlot = inventorySlots.getOrNull(slotIdx)?.takeIf { playerSlots.contains(it) } ?: return false\n        var firstFreeSlotId = Int.MAX_VALUE\n        for (filterSlot in filterSlots.withIndex()) {\n            if (filterSlot.value.hasStack) {\n                if (filterSlot.value.stack.isItemEqual(playerInvSlot.stack)) {\n                    // item already in filter slots\n                    return false\n                }\n            } else {\n                firstFreeSlotId = minOf(firstFreeSlotId, filterSlot.index)\n            }\n        }\n\n        return firstFreeSlotId.takeIf { it in filterSlots.indices }\n            ?.let { filterSlots[it] as? GhostItemSlot }\n            ?.let { firstFreeSlot ->\n                applyItemStackToGhostItemSlot(playerInvSlot.stack, firstFreeSlot)\n                true\n            }\n            ?: false\n    }\n\n    override fun canInteractWith(playerIn: EntityPlayer): Boolean = true\n\n    override fun applyItemStackToGhostItemSlot(itemStack: ItemStack, slot: GhostSlot) {\n        val copiedStack = itemStack.copy().apply { count = 1 }\n        slot.putStack(copiedStack)\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/logistics/LogisticsManager.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.logistics\n\nimport logisticspipes.modules.LogisticsModule\nimport logisticspipes.pipefxhandlers.Particles\nimport logisticspipes.proxy.SimpleServiceLocator\nimport logisticspipes.routing.AsyncRouting\nimport logisticspipes.routing.ExitRoute\nimport logisticspipes.routing.PipeRoutingConnectionType\nimport logisticspipes.routing.ServerRouter\nimport logisticspipes.utils.SinkReply\nimport logisticspipes.utils.item.ItemIdentifier\nimport net.minecraft.item.ItemStack\nimport java.util.*\nimport java.util.stream.Stream\n\nobject LogisticsManager {\n    fun allDestinations(stack: ItemStack, itemid: ItemIdentifier, canBeDefault: Boolean, sourceRouter: ServerRouter, filter: () -> Boolean): Sequence<Pair<Int, SinkReply>> {\n        val jamList = LinkedList<Int>()\n        return generateSequence {\n            return@generateSequence if (filter()) getDestination(stack, itemid, canBeDefault, sourceRouter, jamList)?.also { jamList.add(it.first) } else null\n        }\n    }\n\n    fun getDestination(stack: ItemStack, itemid: ItemIdentifier, canBeDefault: Boolean, sourceRouter: ServerRouter, routersToExclude: List<Int>): Pair<Int, SinkReply>? {\n        val destinationStream = ServerRouter.getRoutersInterestedIn(itemid).stream()\n                .mapToObj(SimpleServiceLocator.routerManager::getServerRouter)\n                .flatMap {\n                    it?.let { router ->\n                        AsyncRouting.getDistance(sourceRouter, router)?.let { routes ->\n                            routes.stream().filter { exitRoute -> exitRoute.containsFlag(PipeRoutingConnectionType.canRouteTo) }\n                        }\n                    } ?: Stream.empty()\n                }\n        return getBestReply(stack, itemid, sourceRouter, destinationStream, routersToExclude, canBeDefault)\n    }\n\n    private fun getBestReply(stack: ItemStack, itemid: ItemIdentifier, sourceRouter: ServerRouter, destinationStream: Stream<ExitRoute>, routersToExclude: List<Int>, canBeDefault: Boolean): Pair<Int, SinkReply>? {\n        var resultRouterId: Int? = null\n        var result: SinkReply? = null\n        destinationStream.filter {\n            it.destination.id != sourceRouter.id &&\n                    !routersToExclude.contains(it.destination.simpleID) &&\n                    it.containsFlag(PipeRoutingConnectionType.canRouteTo) &&\n                    it.filters.none { filter -> filter.blockRouting() || filter.isBlocked == filter.isFilteredItem(itemid) } &&\n                    it.destination.logisticsModule != null &&\n                    it.destination.logisticsModule.receivePassive() &&\n                    it.destination.pipe != null &&\n                    it.destination.pipe.isEnabled &&\n                    !it.destination.pipe.isOnSameContainer(sourceRouter.pipe)\n        }.sorted().forEachOrdered {\n            val reply: SinkReply?\n            val module: LogisticsModule = it.destination.logisticsModule\n            reply = when {\n                result == null -> module.sinksItem(stack, itemid, -1, 0, canBeDefault, true, true)\n                result!!.maxNumberOfItems < 0 -> null\n                else -> module.sinksItem(stack, itemid, result!!.fixedPriority.ordinal, result!!.customPriority, canBeDefault, true, true)\n            }\n\n            if (reply != null && (result == null ||\n                            reply.fixedPriority.ordinal > result!!.fixedPriority.ordinal ||\n                            (reply.fixedPriority == result!!.fixedPriority && reply.customPriority > result!!.customPriority))) {\n                resultRouterId = it.destination.simpleID\n                result = reply\n            }\n        }\n\n        return result?.let { sinkReply ->\n            resultRouterId?.let { destinationRouterId ->\n                val pipe = SimpleServiceLocator.routerManager.getServerRouter(destinationRouterId)!!.pipe!!\n                pipe.useEnergy(sinkReply.energyUse)\n                pipe.spawnParticle(Particles.BlueParticle, 10)\n                Pair(destinationRouterId, sinkReply)\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/AsyncAdvancedExtractor.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory\nimport network.rs485.logisticspipes.property.BooleanProperty\nimport network.rs485.logisticspipes.property.ItemIdentifierInventoryProperty\nimport network.rs485.logisticspipes.property.Property\nimport network.rs485.logisticspipes.util.matchingSequence\nimport logisticspipes.gui.hud.modules.HUDAdvancedExtractor\nimport logisticspipes.interfaces.*\nimport logisticspipes.network.NewGuiHandler\nimport logisticspipes.network.PacketHandler\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider\nimport logisticspipes.network.guis.module.inhand.AdvancedExtractorModuleInHand\nimport logisticspipes.network.guis.module.inpipe.AdvancedExtractorModuleSlot\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket\nimport logisticspipes.network.packets.module.ModuleInventory\nimport logisticspipes.network.packets.modules.AdvancedExtractorInclude\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.proxy.computers.interfaces.CCCommand\nimport logisticspipes.utils.ISimpleInventoryEventHandler\nimport logisticspipes.utils.item.ItemIdentifierInventory\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.world.IBlockAccess\nimport kotlinx.coroutines.Deferred\n\n\nclass AsyncAdvancedExtractor : AsyncModule<ExtractorJob, Unit>(), SimpleFilter, SneakyDirection,\n    IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver, IModuleInventoryReceive,\n    ISimpleInventoryEventHandler, Gui {\n\n    companion object {\n        @JvmStatic\n        val name: String = \"extractor_advanced\"\n    }\n\n    private val filterInventory = ItemIdentifierInventoryProperty(ItemIdentifierInventory(9, \"Item list\", 1), \"\")\n    val itemsIncluded = BooleanProperty(true, \"itemsIncluded\")\n    override val properties: List<Property<*>>\n        get() = extractor.properties + listOf(filterInventory, itemsIncluded)\n\n    private val hud = HUDAdvancedExtractor(this)\n    private val extractor = AsyncExtractorModule(\n        inverseFilter = {\n            it.isEmpty || itemsIncluded.value != filterInventory.matchingSequence(it).any()\n        },\n    )\n\n    override var sneakyDirection: EnumFacing?\n        get() = extractor.sneakyDirection\n        set(value) {\n            extractor.sneakyDirection = value\n        }\n\n    override val everyNthTick: Int\n        get() = extractor.everyNthTick\n\n    override val module = this\n\n    override val pipeGuiProvider: ModuleCoordinatesGuiProvider\n        get() = NewGuiHandler.getGui(AdvancedExtractorModuleSlot::class.java).setAreItemsIncluded(itemsIncluded.value)\n\n    override val inHandGuiProvider: ModuleInHandGuiProvider\n        get() = NewGuiHandler.getGui(AdvancedExtractorModuleInHand::class.java)\n\n    override fun finishInit() {\n        val isInitialized = super.initialized\n        super.finishInit()\n        if (isInitialized) return\n        if (_service != null) {\n            val blockAccess: IBlockAccess? = _world?.world\n            MainProxy.runOnServer(blockAccess) {\n                Runnable {\n                    itemsIncluded.addObserver {\n                        MainProxy.sendToPlayerList(\n                            PacketHandler.getPacket(AdvancedExtractorInclude::class.java)\n                                .setFlag(it.copyValue())\n                                .setModulePos(this),\n                            extractor.localModeWatchers,\n                        )\n                    }\n                }\n            }\n        }\n    }\n\n    override fun getLPName(): String = name\n\n    override fun registerHandler(world: IWorldProvider?, service: IPipeServiceProvider?) {\n        super.registerHandler(world, service)\n        extractor.registerHandler(world, service)\n    }\n\n    override fun registerPosition(slot: ModulePositionType, positionInt: Int) {\n        super.registerPosition(slot, positionInt)\n        extractor.registerPosition(slot, positionInt)\n    }\n\n    override fun receivePassive(): Boolean = false\n\n    override fun hasGenericInterests(): Boolean = false\n\n    override fun interestedInUndamagedID(): Boolean = false\n\n    override fun interestedInAttachedInventory(): Boolean = false\n\n    override fun jobSetup(): ExtractorJob = extractor.jobSetup()\n\n    override fun completeJob(deferred: Deferred<Unit?>) = extractor.completeJob(deferred)\n\n    override suspend fun tickAsync(setupObject: ExtractorJob) = extractor.tickAsync(setupObject)\n\n    override fun runSyncWork() = extractor.runSyncWork()\n\n    @CCCommand(description = \"Returns the FilterInventory of this Module\")\n    override fun getFilterInventory(): IItemIdentifierInventory {\n        return filterInventory\n    }\n\n    override fun handleInvContent(items: MutableCollection<ItemIdentifierStack>) =\n        filterInventory.handleItemIdentifierList(items)\n\n    override fun InventoryChanged(inventory: IInventory?) {\n        MainProxy.runOnServer(world) {\n            Runnable {\n                MainProxy.sendToPlayerList(\n                    PacketHandler.getPacket(ModuleInventory::class.java)\n                        .setIdentList(ItemIdentifierStack.getListFromInventory(inventory))\n                        .setModulePos(this),\n                    extractor.localModeWatchers,\n                )\n            }\n        }\n    }\n\n    override fun getClientInformation(): MutableList<String> {\n        val clientInformation = extractor.clientInformation\n        clientInformation.add(if (itemsIncluded.value) \"Included\" else \"Excluded\")\n        clientInformation.add(\"Filter:\")\n        clientInformation.addAll(filterInventory.clientInformation)\n        return clientInformation\n    }\n\n    override fun startWatching(player: EntityPlayer?) {\n        extractor.startWatching(player)\n        MainProxy.sendPacketToPlayer(\n            PacketHandler.getPacket(ModuleInventory::class.java)\n                .setIdentList(ItemIdentifierStack.getListFromInventory(filterInventory))\n                .setModulePos(this),\n            player,\n        )\n        MainProxy.sendPacketToPlayer(\n            PacketHandler.getPacket(AdvancedExtractorInclude::class.java)\n                .setFlag(itemsIncluded.value)\n                .setModulePos(this),\n            player,\n        )\n    }\n\n    override fun stopWatching(player: EntityPlayer?) = extractor.stopWatching(player)\n\n    override fun startHUDWatching() {\n        MainProxy.sendPacketToServer(\n            PacketHandler.getPacket(HUDStartModuleWatchingPacket::class.java).setModulePos(this),\n        )\n    }\n\n    override fun getHUDRenderer(): IHUDModuleRenderer = hud\n\n    override fun stopHUDWatching() {\n        MainProxy.sendPacketToServer(\n            PacketHandler.getPacket(HUDStopModuleWatchingPacket::class.java).setModulePos(this),\n        )\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/AsyncComputerQuicksort.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport logisticspipes.interfaces.IClientInformationProvider\nimport logisticspipes.interfaces.IModuleWatchReciver\nimport logisticspipes.interfaces.IPipeServiceProvider\nimport logisticspipes.interfaces.IWorldProvider\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.utils.PlayerCollectionList\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.ItemStack\nimport net.minecraft.nbt.NBTTagCompound\nimport kotlinx.coroutines.Deferred\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\n\nclass AsyncComputerQuicksort : AsyncModule<Pair<Int, ItemStack>?, QuicksortAsyncResult?>(), Gui,\n    IClientInformationProvider, IModuleWatchReciver {\n\n    companion object {\n        @JvmStatic\n        val name: String = \"quick_sort_cc\"\n    }\n\n    private val quicksort = AsyncQuicksortModule()\n    private val localModeWatchers = PlayerCollectionList()\n\n    private var _timeout: Int = 100\n    var timeout: Int\n        get() = _timeout\n        set(value) {\n            _timeout = if (value == 0) 100 else value\n            MainProxy.runOnServer(world) {\n                Runnable {\n//                    MainProxy.sendToPlayerList(PacketHandler.getPacket(CCBasedQuickSortMode::class.java).setTimeOut(timeout).setModulePos(this), localModeWatchers)\n                }\n            }\n        }\n\n    private var _sinkSize: Int = 0\n    var sinkSize: Int\n        get() = _sinkSize\n        set(value) {\n            _sinkSize = value\n            MainProxy.runOnServer(world) {\n                Runnable {\n//                    MainProxy.sendToPlayerList(PacketHandler.getPacket(CCBasedQuickSortSinkSize::class.java).setSinkSize(sinkSize).setModulePos(this), localModeWatchers)\n                }\n            }\n        }\n\n    override val module = this\n    override val pipeGuiProvider: ModuleCoordinatesGuiProvider\n        get() = TODO(\"Reimplement CCBasedQuickSortSlot\")\n    override val inHandGuiProvider: ModuleInHandGuiProvider\n        get() = TODO(\"Reimplement CCBasedQuickSortInHand\")\n\n    init {\n        TODO(\"Class still needs to be implemented\")\n    }\n\n    override fun getLPName(): String = name\n\n    override fun registerHandler(world: IWorldProvider?, service: IPipeServiceProvider?) {\n        super.registerHandler(world, service)\n        quicksort.registerHandler(world, service)\n    }\n\n    override fun registerPosition(slot: ModulePositionType, positionInt: Int) {\n        super.registerPosition(slot, positionInt)\n        quicksort.registerPosition(slot, positionInt)\n    }\n\n    override fun jobSetup(): Pair<Int, ItemStack>? = quicksort.jobSetup()\n\n    override suspend fun tickAsync(setupObject: Pair<Int, ItemStack>?): QuicksortAsyncResult? =\n        quicksort.tickAsync(setupObject)\n\n    @ExperimentalCoroutinesApi\n    override fun completeJob(deferred: Deferred<QuicksortAsyncResult?>) = quicksort.completeJob(deferred)\n\n    override fun runSyncWork() = quicksort.runSyncWork()\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        super.readFromNBT(tag)\n        quicksort.readFromNBT(tag)\n        timeout = tag.getInteger(\"Timeout\")\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) {\n        super.writeToNBT(tag)\n        quicksort.writeToNBT(tag)\n        tag.setInteger(\"Timeout\", timeout)\n    }\n\n    override fun finishInit() {\n        super.finishInit()\n        quicksort.finishInit()\n    }\n\n    override fun receivePassive(): Boolean = false\n\n    override fun hasGenericInterests(): Boolean = false\n\n    override fun interestedInUndamagedID(): Boolean = false\n\n    override fun interestedInAttachedInventory(): Boolean = false\n\n    override fun getClientInformation(): MutableList<String> = mutableListOf(\"Timeout: $timeout\")\n\n    override fun startWatching(player: EntityPlayer?) {\n        localModeWatchers.add(player)\n//        MainProxy.sendPacketToPlayer(PacketHandler.getPacket(CCBasedQuickSortMode::class.java).setTimeOut(timeout).setModulePos(this), player)\n//        MainProxy.sendPacketToPlayer(PacketHandler.getPacket(CCBasedQuickSortSinkSize::class.java).setSinkSize(sinkSize).setModulePos(this), player)\n    }\n\n    override fun stopWatching(player: EntityPlayer?) {\n        localModeWatchers.remove(player)\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/AsyncExtractorModule.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport network.rs485.logisticspipes.logistics.LogisticsManager\nimport network.rs485.logisticspipes.property.NullableEnumProperty\nimport network.rs485.logisticspipes.property.Property\nimport network.rs485.logisticspipes.util.equalsWithNBT\nimport network.rs485.logisticspipes.util.getExtractionMax\nimport logisticspipes.config.Configs\nimport logisticspipes.interfaces.*\nimport logisticspipes.network.NewGuiHandler\nimport logisticspipes.network.PacketHandler\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider\nimport logisticspipes.network.guis.module.inhand.SneakyModuleInHandGuiProvider\nimport logisticspipes.network.guis.module.inpipe.SneakyModuleInSlotGuiProvider\nimport logisticspipes.network.packets.hud.HUDStartModuleWatchingPacket\nimport logisticspipes.network.packets.hud.HUDStopModuleWatchingPacket\nimport logisticspipes.network.packets.modules.SneakyModuleDirectionUpdate\nimport logisticspipes.pipefxhandlers.Particles\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.routing.AsyncRouting\nimport logisticspipes.routing.AsyncRouting.needsRoutingTableUpdate\nimport logisticspipes.routing.AsyncRouting.updateServerRouterLsa\nimport logisticspipes.routing.ServerRouter\nimport logisticspipes.utils.PlayerCollectionList\nimport logisticspipes.utils.item.ItemIdentifier\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport net.minecraftforge.fml.client.FMLClientHandler\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.ItemStack\nimport net.minecraft.util.EnumFacing\nimport java.util.*\nimport kotlin.math.min\nimport kotlin.math.pow\nimport kotlinx.coroutines.Deferred\nimport kotlinx.coroutines.channels.Channel\nimport kotlinx.coroutines.flow.consumeAsFlow\n\nclass ExtractorJob(private val module: AsyncExtractorModule, private val inventoryGetter: () -> IInventoryUtil?) {\n    private var inventorySize = inventoryGetter()?.sizeInventory ?: 0\n    private val slotsPerTick: Int = determineSlotsPerTick(module.everyNthTick, inventorySize)\n    private val slotStartIter =\n        if (slotsPerTick == 0) emptyList<Int>().iterator()\n        else IntProgression.fromClosedRange(0, inventorySize - 1, slotsPerTick).iterator()\n    private var itemsLeft = module.itemsToExtract\n    private var stacksLeft = module.stacksToExtract\n    private val updateRoutingTableMsgChannel: Channel<Unit> = Channel(Channel.CONFLATED)\n    private val slotItemsToExtract: MutableMap<Int, ItemIdentifierStack> = HashMap()\n\n    fun runSyncWork() {\n        try {\n            val serverRouter = module.serverRouter\n            val inventory = inventoryGetter()\n            if (slotsPerTick == 0 || !slotStartIter.hasNext() || serverRouter == null || inventory == null) {\n                updateRoutingTableMsgChannel.close()\n                return\n            }\n            inventorySize = inventory.sizeInventory\n            val startSlot = slotStartIter.next()\n            val stopSlot = if (slotStartIter.hasNext()) {\n                min(inventorySize, startSlot + slotsPerTick)\n            } else inventorySize\n\n            val slotRange = startSlot until stopSlot\n            for (slot in slotRange) {\n                val stack = inventory.getStackInSlot(slot)\n                if (module.inverseFilter(stack)) continue // filters the stack out by the given filter method\n                val toExtract = min(itemsLeft, stack.count)\n                itemsLeft -= toExtract\n                --stacksLeft\n                slotItemsToExtract[slot] = ItemIdentifierStack(ItemIdentifier.get(stack), toExtract)\n                if (itemsLeft < 1) break\n                if (stacksLeft < 1) break\n            }\n            serverRouter.updateServerRouterLsa()\n            if (serverRouter.needsRoutingTableUpdate()) {\n                updateRoutingTableMsgChannel.trySend(Unit)\n            } else {\n                extractAndSend(serverRouter, inventory)\n            }\n            if (!slotStartIter.hasNext()) {\n                updateRoutingTableMsgChannel.close()\n            }\n        } catch (error: Exception) {\n            updateRoutingTableMsgChannel.close(error)\n            throw error\n        }\n    }\n\n    suspend fun runAsyncWork() {\n        if (!Configs.DISABLE_ASYNC_WORK) {\n            updateRoutingTableMsgChannel.consumeAsFlow().collect {\n                module.serverRouter?.also { serverRouter ->\n                    AsyncRouting.updateRoutingTable(serverRouter)\n                }\n            }\n        }\n    }\n\n    fun extractAndSend(serverRouter: ServerRouter, inventory: IInventoryUtil) {\n        slotItemsToExtract.forEach { (slot, itemIdStack) ->\n            extractAndSendStack(serverRouter, inventory, slot, itemIdStack)\n        }\n        slotItemsToExtract.clear()\n    }\n\n    private fun extractAndSendStack(\n        serverRouter: ServerRouter,\n        inventory: IInventoryUtil,\n        slot: Int,\n        itemIdStack: ItemIdentifierStack,\n    ) {\n        val service = module.service ?: return\n        val pointedOrientation = service.pointedOrientation ?: return\n        val stack = inventory.getStackInSlot(slot)\n        if (!itemIdStack.item.equalsWithNBT(stack)) return\n        var sourceStackLeft = itemIdStack.stackSize\n        val validDestinationSequence = LogisticsManager.allDestinations(\n            stack = stack,\n            itemid = ItemIdentifier.get(stack),\n            canBeDefault = true,\n            sourceRouter = serverRouter,\n        ) { sourceStackLeft > 0 }\n        validDestinationSequence.forEach { (destRouterId, sinkReply) ->\n            var extract = getExtractionMax(stack.count, sourceStackLeft, sinkReply)\n            if (extract < 1) return@forEach\n            while (!service.useEnergy(module.energyPerItem * extract)) {\n                service.spawnParticle(Particles.OrangeParticle, 2)\n                if (extract < 2) break\n                extract /= 2\n            }\n            val toSend = inventory.decrStackSize(slot, extract)\n            if (toSend.isEmpty) return@forEach\n            service.sendStack(toSend, destRouterId, sinkReply, module.itemSendMode, pointedOrientation)\n            sourceStackLeft -= toSend.count\n        }\n    }\n}\n\nclass AsyncExtractorModule(\n    val inverseFilter: (ItemStack) -> Boolean = { stack -> stack.isEmpty },\n) : AsyncModule<ExtractorJob, Unit>(), Gui, SneakyDirection,\n    IClientInformationProvider, IHUDModuleHandler, IModuleWatchReciver {\n\n    companion object {\n        @JvmStatic\n        val name: String = \"extractor\"\n    }\n\n    private val sneakyDirectionProp = NullableEnumProperty(null, \"sneakydirection\", EnumFacing.values())\n\n    override val properties: List<Property<*>>\n        get() = listOf(sneakyDirectionProp)\n\n    override var sneakyDirection: EnumFacing?\n        get() = sneakyDirectionProp.value\n        set(value) {\n            sneakyDirectionProp.value = value\n            MainProxy.sendToPlayerList(\n                PacketHandler.getPacket(SneakyModuleDirectionUpdate::class.java)\n                    .setDirection(sneakyDirection)\n                    .setModulePos(this),\n                localModeWatchers,\n            )\n        }\n\n    private val hudRenderer: IHUDModuleRenderer = HUDAsyncExtractor(this)\n    val localModeWatchers = PlayerCollectionList()\n    override val module = this\n    private var currentJob: ExtractorJob? = null\n\n    internal val serverRouter: ServerRouter?\n        get() = _service?.router as? ServerRouter\n\n    internal val service: IPipeServiceProvider?\n        get() = _service\n\n    override val pipeGuiProvider: ModuleCoordinatesGuiProvider\n        get() =\n            NewGuiHandler.getGui(SneakyModuleInSlotGuiProvider::class.java).setSneakyOrientation(sneakyDirection)\n\n    override val inHandGuiProvider: ModuleInHandGuiProvider\n        get() =\n            NewGuiHandler.getGui(SneakyModuleInHandGuiProvider::class.java)\n\n    override val everyNthTick: Int\n        get() = (80 / upgradeManager.let { 2.0.pow(it.actionSpeedUpgrade) }).toInt() + Configs.MINIMUM_JOB_TICK_LENGTH\n\n    val stacksToExtract: Int\n        get() = 1 + upgradeManager.itemStackExtractionUpgrade\n\n    val itemsToExtract: Int\n        get() = upgradeManager.let { 4 * it.itemExtractionUpgrade + 64 * upgradeManager.itemStackExtractionUpgrade }\n            .coerceAtLeast(1)\n\n    internal val energyPerItem: Int\n        get() = upgradeManager.let {\n            5 * 1.1.pow(it.itemExtractionUpgrade) * 1.2.pow(it.itemStackExtractionUpgrade)\n        }.toInt()\n\n    internal val itemSendMode: CoreRoutedPipe.ItemSendMode\n        get() = upgradeManager.let { um ->\n            CoreRoutedPipe.ItemSendMode.Fast.takeIf { um.itemExtractionUpgrade > 0 }\n        } ?: CoreRoutedPipe.ItemSendMode.Normal\n\n    private val connectedInventory: IInventoryUtil?\n        get() = _service?.availableSneakyInventories(sneakyDirection)?.firstOrNull()\n\n    override fun getLPName(): String = name\n\n    override fun jobSetup(): ExtractorJob = ExtractorJob(this) { connectedInventory }.also {\n        currentJob = it\n        it.runSyncWork()\n    }\n\n    override fun runSyncWork() {\n        currentJob?.runSyncWork()\n    }\n\n    override suspend fun tickAsync(setupObject: ExtractorJob) {\n        setupObject.runAsyncWork()\n    }\n\n    override fun completeJob(deferred: Deferred<Unit?>) {\n        val serverRouter = module.serverRouter ?: return\n        val inventory = connectedInventory ?: return\n        serverRouter.ensureLatestRoutingTable()\n        currentJob?.extractAndSend(serverRouter, inventory)\n    }\n\n    override fun receivePassive(): Boolean = false\n\n    override fun hasGenericInterests(): Boolean = false\n\n    override fun interestedInUndamagedID(): Boolean = false\n\n    override fun interestedInAttachedInventory(): Boolean = true\n\n    override fun getClientInformation(): MutableList<String> =\n        mutableListOf(\"Extraction: ${sneakyDirection?.name ?: \"DEFAULT\"}\")\n\n    override fun stopHUDWatching() {\n        MainProxy.sendPacketToServer(\n            PacketHandler.getPacket(HUDStopModuleWatchingPacket::class.java).setModulePos(this),\n        )\n    }\n\n    override fun getHUDRenderer(): IHUDModuleRenderer = hudRenderer\n\n    override fun startHUDWatching() {\n        MainProxy.sendPacketToServer(\n            PacketHandler.getPacket(HUDStartModuleWatchingPacket::class.java).setModulePos(this),\n        )\n    }\n\n    override fun startWatching(player: EntityPlayer?) {\n        Objects.requireNonNull(player, \"player must not be null\")\n        localModeWatchers.add(player)\n        MainProxy.sendPacketToPlayer(\n            PacketHandler.getPacket(SneakyModuleDirectionUpdate::class.java).setDirection(sneakyDirection)\n                .setModulePos(this),\n            player,\n        )\n    }\n\n    override fun stopWatching(player: EntityPlayer?) {\n        Objects.requireNonNull(player, \"player must not be null\")\n        if (localModeWatchers.contains(player)) localModeWatchers.remove(player)\n    }\n\n    class HUDAsyncExtractor(private val module: AsyncExtractorModule) : IHUDModuleRenderer {\n        override fun renderContent(shifted: Boolean) {\n            val mc = FMLClientHandler.instance().client\n\n            val d: EnumFacing? = module.sneakyDirection\n            mc.fontRenderer.drawString(\"Extract\", -22, -22, 0)\n            mc.fontRenderer.drawString(\"from:\", -22, -9, 0)\n            mc.fontRenderer.drawString(d?.name ?: \"DEFAULT\", -22, 18, 0)\n        }\n\n        override fun getButtons(): MutableList<IHUDButton>? = null\n\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/AsyncModule.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport network.rs485.grow.Coroutines\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.modules.LogisticsModule\nimport net.minecraft.client.Minecraft\nimport net.minecraft.tileentity.TileEntity\nimport java.time.Duration\nimport kotlinx.coroutines.Deferred\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.TimeoutCancellationException\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.time.withTimeout\n\nabstract class AsyncModule<S, C> : LogisticsModule() {\n    private var currentJob: Deferred<C?>? = null\n\n    /**\n     * Represents the wait time in ticks until the next job is started.\n     */\n    open val everyNthTick: Int = 20\n\n    /**\n     * A debug helper for adding the connected [TileEntity] to error\n     * information. May return null, if the information is not\n     * available.\n     */\n    private val connectedEntity: TileEntity?\n        get() = _service?.availableAdjacent?.inventories()?.firstOrNull()?.tileEntity\n\n    @ExperimentalCoroutinesApi\n    override fun tick() {\n        val currentJobTemp = currentJob\n        if (currentJobTemp?.isActive == true) {\n            runSyncWork()\n        } else {\n            if (currentJobTemp?.isCompleted == true) {\n                try {\n                    runSyncWork()\n                    completeJob(currentJobTemp)\n                } finally {\n                    currentJob = null\n                }\n            }\n\n            if (_service?.isNthTick(everyNthTick) == true) {\n                val setup = jobSetup()\n                currentJob = Coroutines.asynchronousScope.async {\n                    try {\n                        return@async withTimeout(Duration.ofSeconds(90)) {\n                            tickAsync(setup)\n                        }\n                    } catch (e: RuntimeException) {\n                        val isGamePaused = world?.isRemote == false && Minecraft.getMinecraft().isGamePaused\n                        if (e !is TimeoutCancellationException && !isGamePaused) {\n                            val connected = connectedEntity?.let { \" connected to $it at ${it.pos}\" } ?: \"\"\n                            LogisticsPipes.log.error(\"Error in ticking async module $module$connected\", e)\n                        }\n                    }\n                    return@async null\n                }\n            }\n        }\n    }\n\n    /**\n     * Setup function which is run on every new module tick.\n     *\n     * @return setup object S which is passed to [tickAsync].\n     */\n    abstract fun jobSetup(): S\n\n    /**\n     * Completion function that is run after every successful module\n     * tick and all asynchronous work is done.\n     *\n     * @param deferred the [Deferred] of the asynchronous work.\n     */\n    abstract fun completeJob(deferred: Deferred<C?>)\n\n    /**\n     * Asynchronous tick function that is run with a timeout. Takes the\n     * setup object and returns an object for [completeJob].\n     *\n     * @param setupObject the setup object from [jobSetup].\n     * @return a completion object for [completeJob].\n     */\n    abstract suspend fun tickAsync(setupObject: S): C\n\n    /**\n     * Runs every tick while the [current async task][currentJob] is active.\n     */\n    abstract fun runSyncWork()\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/AsyncQuicksortModule.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport network.rs485.grow.Coroutines\nimport network.rs485.logisticspipes.logistics.LogisticsManager\nimport network.rs485.logisticspipes.property.Property\nimport network.rs485.logisticspipes.util.equalsWithNBT\nimport network.rs485.logisticspipes.util.getExtractionMax\nimport logisticspipes.config.Configs\nimport logisticspipes.interfaces.IInventoryUtil\nimport logisticspipes.network.PacketHandler\nimport logisticspipes.network.packets.modules.QuickSortState\nimport logisticspipes.pipefxhandlers.Particles\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.routing.AsyncRouting\nimport logisticspipes.routing.AsyncRouting.needsRoutingTableUpdate\nimport logisticspipes.routing.AsyncRouting.updateServerRouterLsa\nimport logisticspipes.routing.ServerRouter\nimport logisticspipes.utils.PlayerCollectionList\nimport logisticspipes.utils.SinkReply\nimport logisticspipes.utils.item.ItemIdentifier\nimport net.minecraft.entity.player.EntityPlayer\nimport net.minecraft.item.ItemStack\nimport kotlinx.coroutines.Deferred\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutines.withContext\n\nconst val STALLED_DELAY = 24\nconst val NORMAL_DELAY = 6\n\ndata class QuicksortAsyncResult(\n    val slot: Int,\n    val itemid: ItemIdentifier,\n    val destRouterId: Int,\n    val sinkReply: SinkReply,\n)\n\nclass AsyncQuicksortModule : AsyncModule<Pair<Int, ItemStack>?, QuicksortAsyncResult?>() {\n    companion object {\n        @JvmStatic\n        val name: String = \"quick_sort\"\n    }\n\n    private val localSlotWatchers = PlayerCollectionList()\n    private var stalled = true\n    private var currentSlot = 0\n        set(value) {\n            field = value\n            MainProxy.sendToPlayerList(PacketHandler.getPacket(QuickSortState::class.java).setInteger(value)\n                .setModulePos(this), localSlotWatchers)\n        }\n    private var stallSlot = 0\n\n    override val properties: List<Property<*>>\n        get() = emptyList()\n\n    private val energyPerStack: Int\n        get() = upgradeManager.let { 500 + 1000 * it.itemStackExtractionUpgrade }.toInt()\n    override val everyNthTick: Int\n        get() = if (stalled) STALLED_DELAY else NORMAL_DELAY\n\n    override fun getLPName(): String = name\n\n    override fun jobSetup(): Pair<Int, ItemStack>? {\n        val serverRouter = this._service?.router as? ServerRouter ?: return null\n        val inventory = _service?.availableInventories()?.firstOrNull() ?: return null\n        if (inventory.sizeInventory == 0) return null\n        if (currentSlot >= inventory.sizeInventory) currentSlot = 0\n        val slot = currentSlot++\n        val stack = inventory.getStackInSlot(slot)\n        if (!stalled && slot == stallSlot) stalled = true\n        if (stack.isEmpty) return null\n        serverRouter.updateServerRouterLsa()\n        if (!Configs.DISABLE_ASYNC_WORK && serverRouter.needsRoutingTableUpdate()) {\n            // go async\n            return slot to stack\n        }\n        val itemid = ItemIdentifier.get(stack)\n        val result = LogisticsManager.getDestination(stack, itemid, false, serverRouter, emptyList()) ?: return null\n        extractAndSend(slot, stack, inventory, result.first, result.second)\n        return null\n    }\n\n    override suspend fun tickAsync(setupObject: Pair<Int, ItemStack>?): QuicksortAsyncResult? {\n        if (setupObject == null) return null\n        val serverRouter = this._service?.router as? ServerRouter ?: return null\n        AsyncRouting.updateRoutingTable(serverRouter)\n        val itemid = ItemIdentifier.get(setupObject.second)\n        val result = withContext(Coroutines.serverScope.coroutineContext) {\n            LogisticsManager.getDestination(setupObject.second, itemid, false, serverRouter, emptyList())\n        } ?: return null\n        return QuicksortAsyncResult(setupObject.first, itemid, result.first, result.second)\n    }\n\n    @ExperimentalCoroutinesApi\n    override fun completeJob(deferred: Deferred<QuicksortAsyncResult?>) {\n        val result = deferred.getCompleted() ?: return\n        val inventory = _service?.availableInventories()?.firstOrNull() ?: return\n        if (result.slot >= inventory.sizeInventory) return\n        val stack = inventory.getStackInSlot(result.slot)\n        if (result.itemid.equalsWithNBT(stack)) {\n            extractAndSend(result.slot, stack, inventory, result.destRouterId, result.sinkReply)\n        }\n    }\n\n    private fun extractAndSend(\n        slot: Int,\n        stack: ItemStack,\n        inventory: IInventoryUtil,\n        destRouterId: Int,\n        sinkReply: SinkReply,\n    ) {\n        val service = _service ?: return\n        val pointedOrientation = service.pointedOrientation ?: return\n        val toExtract = getExtractionMax(stack.count, stack.maxStackSize, sinkReply)\n        if (toExtract <= 0) return\n        if (!service.useEnergy(energyPerStack)) return\n        stalled = false\n        stallSlot = slot\n        val extracted = inventory.decrStackSize(slot, toExtract)\n        if (extracted.isEmpty) return\n        service.sendStack(\n            extracted,\n            destRouterId,\n            sinkReply,\n            CoreRoutedPipe.ItemSendMode.Fast,\n            pointedOrientation,\n        )\n        service.spawnParticle(Particles.OrangeParticle, 8)\n    }\n\n    override fun runSyncWork() {}\n\n    override fun receivePassive(): Boolean = false\n\n    override fun hasGenericInterests(): Boolean = false\n\n    override fun interestedInUndamagedID(): Boolean = false\n\n    override fun interestedInAttachedInventory(): Boolean = false\n\n    fun addWatchingPlayer(player: EntityPlayer) {\n        localSlotWatchers.add(player)\n        MainProxy.sendPacketToPlayer(PacketHandler.getPacket(QuickSortState::class.java).setInteger(currentSlot)\n            .setModulePos(this), player)\n    }\n\n    fun removeWatchingPlayer(player: EntityPlayer) {\n        localSlotWatchers.remove(player)\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/Gui.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport logisticspipes.modules.LogisticsModule\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider\n\ninterface Gui {\n    val module: LogisticsModule\n    val pipeGuiProvider: ModuleCoordinatesGuiProvider\n    val inHandGuiProvider: ModuleInHandGuiProvider\n\n    companion object {\n        @JvmStatic\n        fun getPipeGuiProvider(gui: Gui): ModuleCoordinatesGuiProvider {\n            return gui.pipeGuiProvider.setSlot(gui.module.slot).setPositionInt(gui.module.positionInt)\n        }\n\n        @JvmStatic\n        fun getInHandGuiProvider(gui: Gui): ModuleInHandGuiProvider {\n            return gui.inHandGuiProvider.setInvSlot(gui.module.positionInt)\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/PipeServiceProviderUtil.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport logisticspipes.interfaces.IInventoryUtil\nimport logisticspipes.interfaces.IPipeServiceProvider\nimport logisticspipes.interfaces.ISlotUpgradeManager\nimport logisticspipes.pipes.PipeLogisticsChassis\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntity\nimport network.rs485.logisticspipes.connection.NeighborTileEntity\nimport network.rs485.logisticspipes.connection.getInventoryUtil\nimport network.rs485.logisticspipes.connection.sneakyInsertion\nimport java.util.*\n\nfun IPipeServiceProvider.availableSneakyInventories(sneakyDirection: EnumFacing?): List<IInventoryUtil?> = sneakyDirection?.let {\n    availableAdjacent.inventories().map { adjacent -> adjacent.sneakyInsertion().from(sneakyDirection).getInventoryUtil() }\n} ?: availableInventories()\n\nfun IPipeServiceProvider.availableSneakyInventories(upgradeManager: ISlotUpgradeManager): List<IInventoryUtil?> =\n    availableAdjacent.inventories().map { adjacent -> adjacent.sneakyInsertion().from(upgradeManager).getInventoryUtil() }\n\nfun IPipeServiceProvider.availableInventories(): List<IInventoryUtil?> =\n    availableAdjacent.inventories().map(NeighborTileEntity<TileEntity>::getInventoryUtil)\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/SimpleFilter.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport logisticspipes.network.NewGuiHandler\nimport logisticspipes.network.abstractguis.ModuleCoordinatesGuiProvider\nimport logisticspipes.network.abstractguis.ModuleInHandGuiProvider\nimport logisticspipes.network.guis.module.inhand.SimpleFilterInventoryInHand\nimport logisticspipes.network.guis.module.inpipe.SimpleFilterInventorySlot\nimport net.minecraft.inventory.IInventory\n\ninterface SimpleFilter {\n    fun getFilterInventory(): IInventory\n\n    companion object {\n        @JvmStatic\n        fun getPipeGuiProvider(): ModuleCoordinatesGuiProvider {\n            return NewGuiHandler.getGui(SimpleFilterInventorySlot::class.java)\n        }\n\n        @JvmStatic\n        fun getInHandGuiProvider(): ModuleInHandGuiProvider {\n            return NewGuiHandler.getGui(SimpleFilterInventoryInHand::class.java)\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/SneakyDirection.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport net.minecraft.nbt.NBTTagCompound\nimport net.minecraft.util.EnumFacing\n\nconst val SNEAKY_DIRECTION_NBT: String = \"sneakydirection\"\n\ninterface SneakyDirection {\n    var sneakyDirection: EnumFacing?\n\n    companion object {\n        @JvmStatic\n        fun readSneakyDirection(nbt: NBTTagCompound): EnumFacing? {\n            return if (nbt.hasKey(SNEAKY_DIRECTION_NBT)) {\n                // will read direction index 6 as null (was ForgeDirection.UNKNOWN)\n                nbt.getInteger(SNEAKY_DIRECTION_NBT).let { if (it in EnumFacing.VALUES.indices) EnumFacing.VALUES[it] else null }\n            } else {\n                null\n            }\n        }\n\n        @JvmStatic\n        fun writeSneakyDirection(direction: EnumFacing?, nbt: NBTTagCompound) {\n            direction?.let { nbt.setInteger(SNEAKY_DIRECTION_NBT, it.ordinal) }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/module/Util.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.module\n\nimport logisticspipes.config.Configs\n\n/**\n * Checks inventory size, everyNthTick and configuration values\n * to determine the number of slot accesses per tick.\n *\n * @param inventorySize the size of the connected inventory.\n * @return 0, if no work can be done and a value greater zero otherwise.\n */\nfun determineSlotsPerTick(everyNthTick: Int, inventorySize: Int): Int {\n    var slotsPerTick = 0\n    if (inventorySize > 0) {\n        slotsPerTick = (inventorySize / everyNthTick).coerceAtLeast(Configs.MINIMUM_INVENTORY_SLOT_ACCESS_PER_TICK)\n    }\n    if (Configs.MAXIMUM_INVENTORY_SLOT_ACCESS_PER_TICK > 0) {\n        slotsPerTick = slotsPerTick.coerceAtMost(Configs.MAXIMUM_INVENTORY_SLOT_ACCESS_PER_TICK)\n    }\n    return slotsPerTick\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/AdjacentProperty.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport network.rs485.logisticspipes.connection.*\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.utils.EnumFacingUtil\nimport net.minecraft.nbt.NBTTagCompound\nimport net.minecraft.nbt.NBTTagList\nimport net.minecraft.nbt.NBTTagString\nimport net.minecraft.util.EnumFacing\n\nclass AdjacentProperty @JvmOverloads constructor(\n    defaultValue: Adjacent = NoAdjacent,\n    private val pipe: CoreRoutedPipe,\n    override val tagKey: String,\n) : ValueProperty<Adjacent>(defaultValue) {\n\n    override fun copyValue(): Adjacent = value // Adjacent is immutable\n\n    override fun copyProperty(): AdjacentProperty = AdjacentProperty(value, pipe, tagKey)\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        if (tag.hasKey(tagKey)) {\n            val adjacentConnectionsTagList = tag.getTagList(tagKey, 8)\n            assert(adjacentConnectionsTagList.tagCount() in 0..6)\n            if (adjacentConnectionsTagList.tagCount() == 0) {\n                value = NoAdjacent\n                return\n            }\n            val adjacentConnections = (0..5).map { idx -> adjacentConnectionsTagList.getStringTagAt(idx) }\n            val activeConnections = adjacentConnections.withIndex().filter { it.value.isNotBlank() }\n            value = when (activeConnections.size) {\n                0 -> NoAdjacent\n                1 -> SingleAdjacent(\n                    parent = pipe,\n                    dir = EnumFacingUtil.getOrientation(activeConnections[0].index)!!,\n                    adjacentType = ConnectionType.valueOf(activeConnections[0].value),\n                )\n                else -> DynamicAdjacent(\n                    parent = pipe,\n                    cache = Array(6) { idx ->\n                        adjacentConnections[idx].takeIf { it.isNotBlank() }?.let(ConnectionType::valueOf)\n                    }\n                )\n            }\n        }\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) {\n        tag.setTag(tagKey, NBTTagList().also { list ->\n            if (value == NoAdjacent) {\n                return@also\n            }\n            EnumFacing.VALUES.map { dir -> NBTTagString(value[dir]?.name ?: \"\") }.forEach(list::appendTag)\n        })\n    }\n\n    fun getDirectionOrNull(): EnumFacing? = (value as? SingleAdjacent)?.dir\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/ItemIdentifierInventoryProperty.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport logisticspipes.utils.item.ItemIdentifierInventory\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport net.minecraft.item.ItemStack\nimport net.minecraft.nbt.NBTTagCompound\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory\nimport network.rs485.logisticspipes.inventory.SlotAccess\nimport java.util.concurrent.CopyOnWriteArraySet\n\nclass ItemIdentifierInventoryProperty(private val inv: ItemIdentifierInventory, override val tagKey: String) :\n    InventoryProperty<ItemIdentifierInventory>, IItemIdentifierInventory by inv, Collection<ItemIdentifierStack> {\n\n    /* FIXME: after 1.12\n    init {\n        require(tagKey.isNotBlank())\n    }\n    */\n\n    override val slotAccess: SlotAccess = object : SlotAccess by inv.slotAccess {\n        override fun mergeSlots(intoSlot: Int, fromSlot: Int) =\n            inv.slotAccess.mergeSlots(intoSlot, fromSlot).alsoIChanged()\n    }\n\n    override val propertyObservers: CopyOnWriteArraySet<ObserverCallback<ItemIdentifierInventory>> =\n        CopyOnWriteArraySet()\n\n    override val size: Int = sizeInventory\n\n    override fun decrStackSize(index: Int, count: Int): ItemStack = inv.decrStackSize(index, count).alsoIChanged()\n\n    override fun removeStackFromSlot(index: Int): ItemStack = inv.removeStackFromSlot(index).alsoIChanged()\n\n    override fun setInventorySlotContents(index: Int, stack: ItemStack) =\n        inv.setInventorySlotContents(index, stack).alsoIChanged()\n\n    override fun setInventorySlotContents(i: Int, itemstack: ItemIdentifierStack?) =\n        inv.setInventorySlotContents(i, itemstack).alsoIChanged()\n\n    override fun setField(id: Int, value: Int) = inv.setField(id, value).alsoIChanged()\n\n    override fun handleItemIdentifierList(_allItems: Collection<ItemIdentifierStack>) =\n        inv.handleItemIdentifierList(_allItems).alsoIChanged()\n\n    override fun clear() = inv.clear().alsoIChanged()\n\n    override fun recheckStackLimit() = inv.recheckStackLimit().alsoIChanged()\n\n    override fun clearInventorySlotContents(i: Int) = inv.clearInventorySlotContents(i).alsoIChanged()\n\n    override fun readFromNBT(tag: NBTTagCompound) {\n        // FIXME: after 1.12 remove this items appending crap\n        if (tag.hasKey(tagKey + \"items\")) inv.readFromNBT(tag, tagKey).alsoIChanged()\n    }\n\n    override fun writeToNBT(tag: NBTTagCompound) = inv.writeToNBT(tag, tagKey)\n\n    override fun copyValue(): ItemIdentifierInventory = ItemIdentifierInventory(inv)\n\n    override fun copyProperty(): ItemIdentifierInventoryProperty = ItemIdentifierInventoryProperty(copyValue(), tagKey)\n\n    override fun contains(element: ItemIdentifierStack): Boolean = inv.itemCount(element.item) >= element.stackSize\n\n    override fun containsAll(elements: Collection<ItemIdentifierStack>): Boolean = inv.itemsAndCount.let { items ->\n        elements.all { items[it.item]?.run { compareTo(it.stackSize) >= 0 } ?: false }\n    }\n\n    override fun iterator(): Iterator<ItemIdentifierStack> =\n        inv.itemsAndCount.map { it.key.makeStack(it.value) }.iterator()\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/PropertyUpdater.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport logisticspipes.modules.LogisticsModule\nimport logisticspipes.network.PacketHandler\nimport logisticspipes.network.packets.module.ModulePropertiesUpdate\nimport logisticspipes.proxy.MainProxy\nimport net.minecraft.entity.player.EntityPlayer\nimport network.rs485.grow.Coroutines.scheduleServerTask\nimport java.lang.ref.WeakReference\nimport java.util.function.Consumer\n\nclass PropertyUpdater(\n    player: EntityPlayer,\n    moduleIn: LogisticsModule,\n    propertiesIn: List<Property<*>>\n) : Consumer<Property<*>> {\n\n    private val weakPlayer: WeakReference<EntityPlayer> = WeakReference(player)\n    private val properties: List<Property<*>> = propertiesIn.also { it.addObserver(this::accept) }\n    private val changedProperties = HashSet<Property<*>>()\n    private val module: LogisticsModule = moduleIn\n    private var shouldUpdate = false\n\n    override fun accept(property: Property<*>) {\n        changedProperties.add(property)\n        if (!shouldUpdate) {\n            shouldUpdate = true\n            scheduleServerTask(5) { sendPropertyUpdate() }\n        }\n    }\n\n    private fun sendPropertyUpdate() {\n        if (shouldUpdate && !weakPlayer.isEnqueued) {\n            val player = weakPlayer.get() ?: return\n            val packet = PacketHandler.getPacket(ModulePropertiesUpdate::class.java)\n            changedProperties.writeToNBT(packet.tag)\n            changedProperties.clear()\n            MainProxy.sendPacketToPlayer(packet.setModulePos(module), player)\n            shouldUpdate = false\n        }\n    }\n\n    internal fun removeForPlayer(entityPlayer: EntityPlayer): Boolean {\n        val shouldBeRemoved = (weakPlayer.isEnqueued\n                || weakPlayer.get() == null || weakPlayer.get() === entityPlayer)\n        if (shouldBeRemoved) {\n            properties.removeObserver(this::accept)\n            shouldUpdate = false\n        }\n        return shouldBeRemoved\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/PropertyUpdaterEventListener.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport network.rs485.logisticspipes.inventory.container.LPBaseContainer\nimport logisticspipes.proxy.MainProxy\nimport net.minecraftforge.event.entity.player.PlayerContainerEvent\nimport net.minecraftforge.fml.common.eventhandler.SubscribeEvent\n\nobject PropertyUpdaterEventListener {\n    private val propertyUpdaters: ArrayList<PropertyUpdater> = ArrayList()\n\n    @SubscribeEvent\n    fun openContainer(event: PlayerContainerEvent.Open) {\n        val player = event.entityPlayer ?: return\n        MainProxy.runOnServer(player.world) {\n            Runnable {\n                val guiContainer = event.container\n                if (guiContainer is LPBaseContainer<*>) {\n                    val module = guiContainer.module\n                    propertyUpdaters.add(\n                        PropertyUpdater(player, module, module.properties)\n                    )\n                }\n            }\n        }\n    }\n\n    @SubscribeEvent\n    fun closeContainer(event: PlayerContainerEvent.Close) {\n        val player = event.entityPlayer ?: return\n        MainProxy.runOnServer(player.world) {\n            Runnable {\n                propertyUpdaters.removeIf { propertyUpdater: PropertyUpdater ->\n                    propertyUpdater.removeForPlayer(event.entityPlayer)\n                }\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/SimpleInventoryProperty.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport logisticspipes.utils.item.SimpleStackInventory\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\nimport net.minecraft.nbt.NBTTagCompound\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.world.World\nimport java.util.concurrent.CopyOnWriteArraySet\nimport java.util.stream.Stream\n\nclass SimpleInventoryProperty(private val inv: SimpleStackInventory, override val tagKey: String) :\n    Property<SimpleStackInventory>, IInventory by inv {\n\n    override val propertyObservers: CopyOnWriteArraySet<ObserverCallback<SimpleStackInventory>> =\n        CopyOnWriteArraySet()\n\n    override fun copyValue(): SimpleStackInventory = SimpleStackInventory(inv)\n\n    override fun copyProperty(): Property<SimpleStackInventory> = SimpleInventoryProperty(copyValue(), tagKey)\n\n    override fun readFromNBT(tag: NBTTagCompound) = inv.readFromNBT(tag, tagKey)\n\n    override fun writeToNBT(tag: NBTTagCompound) = inv.writeToNBT(tag, tagKey)\n\n    fun clearInventorySlotContents(i: Int) = inv.clearInventorySlotContents(i).alsoIChanged()\n\n    fun dropContents(world: World, pos: BlockPos) = inv.dropContents(world, pos).alsoIChanged()\n\n    fun addCompressed(toAdd: ItemStack, ignoreMaxStackSize: Boolean): Int =\n        inv.addCompressed(toAdd, ignoreMaxStackSize).alsoIChanged()\n\n    override fun decrStackSize(index: Int, count: Int): ItemStack = inv.decrStackSize(index, count).alsoIChanged()\n\n    override fun removeStackFromSlot(index: Int): ItemStack = inv.removeStackFromSlot(index).alsoIChanged()\n\n    override fun setInventorySlotContents(index: Int, stack: ItemStack) =\n        inv.setInventorySlotContents(index, stack).alsoIChanged()\n\n    override fun markDirty() = inv.markDirty().alsoIChanged()\n\n    override fun clear() = inv.clear().alsoIChanged()\n\n    @Deprecated(\"delegate not implemented\")\n    override fun setField(id: Int, value: Int) = inv.setField(id, value).alsoIChanged()\n\n    @Deprecated(\"delegate not implemented\")\n    override fun getFieldCount(): Int = inv.fieldCount\n\n    @Deprecated(\"delegate not implemented\")\n    override fun getField(id: Int): Int = inv.getField(id)\n\n    @Deprecated(\"do not change returned ItemStack or call markDirty afterwards\")\n    override fun getStackInSlot(index: Int): ItemStack = inv.getStackInSlot(index)\n\n    fun isSlotEmpty(index: Int): Boolean = inv.getStackInSlot(index).isEmpty\n\n    /**\n     * @see SimpleStackInventory.stackStream\n     */\n    fun stackStream(): Stream<ItemStack> {\n        return inv.stackStream()\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/SlottedModule.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport logisticspipes.modules.LogisticsModule\nimport logisticspipes.modules.LogisticsModule.ModulePositionType\n\nconst val SLOT_INDEX_KEY = \"slotted_module.slot\"\nconst val MODULE_NAME_KEY = \"slotted_module.name\"\n\ndata class SlottedModule(val slot: Int, val module: LogisticsModule?) {\n    fun isEmpty() = module == null\n\n    fun registerPosition() = module?.registerPosition(ModulePositionType.SLOT, slot)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/SlottedModuleListProperty.kt",
    "content": "/*\n * Copyright (c) 2022  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2022  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport logisticspipes.LPItems\nimport logisticspipes.items.ItemModule\nimport logisticspipes.modules.LogisticsModule\nimport net.minecraft.item.Item\nimport net.minecraft.nbt.NBTTagCompound\n\nclass SlottedModuleListProperty(slots: Int, override val tagKey: String) :\n    ListProperty<SlottedModule>(MutableList(slots) { SlottedModule(it, null) }) {\n\n    override fun defaultValue(idx: Int): SlottedModule = SlottedModule(idx, null)\n\n    override fun readSingleFromNBT(tag: NBTTagCompound, key: String): SlottedModule {\n        val slottedModuleTag = tag.getCompoundTag(key)\n        val slot = slottedModuleTag.getInteger(SLOT_INDEX_KEY)\n        val moduleName = if (slottedModuleTag.hasKey(MODULE_NAME_KEY)) {\n            slottedModuleTag.getString(MODULE_NAME_KEY)\n        } else null\n        val moduleResource = moduleName?.let { LPItems.modules[it] }\n        val itemModule = moduleResource?.let { Item.REGISTRY.getObject(moduleResource) as? ItemModule }\n        // FIXME: move module creation to before readFromNBT\n        val logisticsModule = itemModule?.getModule(null, null, null)\n        return logisticsModule?.let { module ->\n            module.readFromNBT(slottedModuleTag)\n            SlottedModule(slot = slot, module = module).also { list[slot] = it }\n        } ?: list[slot]\n    }\n\n    override fun writeSingleToNBT(tag: NBTTagCompound, key: String, value: SlottedModule) {\n        tag.setTag(key, NBTTagCompound()\n            .also { value.module?.writeToNBT(it) }\n            .apply {\n                setInteger(SLOT_INDEX_KEY, value.slot)\n                value.module?.also { setString(MODULE_NAME_KEY, it.lpName) }\n            })\n    }\n\n    override fun copyValue(obj: SlottedModule): SlottedModule = obj.copy(slot = obj.slot, module = null)\n\n    override fun copyProperty(): SlottedModuleListProperty =\n        SlottedModuleListProperty(size, tagKey).apply { addAll(list) }\n\n    fun set(slot: Int, module: LogisticsModule) = set(slot, SlottedModule(slot, module))\n    fun clear(slot: Int) = set(slot, SlottedModule(slot, null))\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/property/UpgradeManagerListProperty.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.property\n\nimport logisticspipes.pipes.PipeLogisticsChassis\nimport logisticspipes.pipes.upgrades.ModuleUpgradeManager\nimport net.minecraft.nbt.NBTTagCompound\n\nclass UpgradeManagerListProperty : ListProperty<ModuleUpgradeManager> {\n    override val tagKey: String\n    private val parentChassis: PipeLogisticsChassis\n    private val subProperties = arrayListOf<Property<*>>()\n\n    private constructor(\n        parentChassis: PipeLogisticsChassis,\n        tagKey: String,\n        list: MutableList<ModuleUpgradeManager>,\n    ) : super(list) {\n        this.parentChassis = parentChassis\n        this.tagKey = tagKey\n        this.subProperties.ensureCapacity(list.size)\n        ensureObservingContents()\n    }\n\n    constructor(\n        slots: Int,\n        parentChassis: PipeLogisticsChassis,\n        tagKey: String,\n    ) : this(\n        parentChassis = parentChassis,\n        tagKey = tagKey,\n        list = MutableList(slots) {\n            ModuleUpgradeManager(\n                parentChassis,\n                parentChassis.originalUpgradeManager,\n            )\n        },\n    )\n\n    private fun ensureObservingContents() {\n        // TODO: check possibility of a generalized ListProperty of Property\n        val propertiesToUnobserve: MutableSet<Property<*>> = subProperties.toMutableSet()\n        list.forEach {\n            if (!propertiesToUnobserve.remove(it.inv)) {\n                it.inv.addObserver(this::contentObserver)\n                subProperties.add(it.inv)\n            }\n        }\n        propertiesToUnobserve.forEach {\n            it.propertyObservers.remove(this::contentObserver)\n        }\n        subProperties.removeAll(propertiesToUnobserve)\n    }\n\n    private fun contentObserver(property: Property<*>) {\n        super.iChanged()\n    }\n\n    override fun iChanged() {\n        super.iChanged()\n        ensureObservingContents()\n    }\n\n    override fun copyValue(obj: ModuleUpgradeManager): ModuleUpgradeManager = ModuleUpgradeManager(obj)\n\n    override fun defaultValue(idx: Int): ModuleUpgradeManager = ModuleUpgradeManager(\n        parentChassis,\n        parentChassis.originalUpgradeManager,\n    )\n\n    override fun readSingleFromNBT(tag: NBTTagCompound, key: String): ModuleUpgradeManager = ModuleUpgradeManager(\n        parentChassis,\n        parentChassis.originalUpgradeManager,\n    ).apply {\n        if (tag.hasKey(key)) {\n            readFromNBT(tag.getCompoundTag(key), \"\")\n        }\n    }\n\n    override fun writeSingleToNBT(tag: NBTTagCompound, key: String, value: ModuleUpgradeManager) {\n        tag.setTag(key, NBTTagCompound().also {\n            value.writeToNBT(it, \"\")\n        })\n    }\n\n    override fun copyProperty(): Property<out MutableList<ModuleUpgradeManager>> =\n        UpgradeManagerListProperty(\n            parentChassis = parentChassis,\n            tagKey = tagKey,\n            list = MutableList(size) { idx -> ModuleUpgradeManager(get(idx)) },\n        )\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/proxy/StorageDrawersProxy.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy\n\nimport logisticspipes.LPConstants\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.proxy.SimpleServiceLocator\nimport net.minecraftforge.fml.common.Loader\nimport network.rs485.logisticspipes.proxy.StorageDrawersProxyImpl.Companion.drawerGroupCapability\n\nobject StorageDrawersProxy {\n    private val impl: StorageDrawersProxyImpl? by lazy {\n        if (Loader.isModLoaded(LPConstants.storagedrawersModID) && drawerGroupCapability != null) {\n            try {\n                val implClass = Loader.instance().modClassLoader.loadClass(\"network.rs485.logisticspipes.proxy.StorageDrawersProxyImpl\")\n                return@lazy (implClass.getDeclaredConstructor().newInstance() as? StorageDrawersProxyImpl)\n            } catch (e: ReflectiveOperationException) {\n                LogisticsPipes.log.fatal(\"Could not load proxy implementation for mod ${LPConstants.storagedrawersModID}\", e)\n            }\n        }\n        null\n    }\n\n    fun registerInventoryHandler() = impl?.let(SimpleServiceLocator.inventoryUtilFactory::registerHandler)\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/proxy/StorageDrawersProxyImpl.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.proxy\n\nimport network.rs485.logisticspipes.inventory.ProviderMode\nimport network.rs485.logisticspipes.util.equalsWithNBT\nimport logisticspipes.LPConstants\nimport logisticspipes.proxy.specialinventoryhandler.SpecialInventoryHandler\nimport logisticspipes.utils.item.ItemIdentifier\nimport com.jaquadro.minecraft.storagedrawers.api.storage.IDrawer\nimport com.jaquadro.minecraft.storagedrawers.api.storage.IDrawerAttributes\nimport com.jaquadro.minecraft.storagedrawers.api.storage.IDrawerGroup\nimport net.minecraftforge.common.capabilities.Capability\nimport net.minecraftforge.common.capabilities.CapabilityInject\nimport net.minecraftforge.fml.common.Loader\nimport net.minecraftforge.fml.common.versioning.ArtifactVersion\nimport net.minecraftforge.fml.common.versioning.DefaultArtifactVersion\nimport net.minecraftforge.fml.common.versioning.VersionRange\nimport net.minecraft.item.ItemStack\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport kotlin.math.min\n\nclass StorageDrawersProxyImpl : SpecialInventoryHandler.Factory {\n\n    companion object {\n        @JvmStatic\n        @CapabilityInject(IDrawerGroup::class)\n        val drawerGroupCapability: Capability<IDrawerGroup>? = null\n\n        @JvmStatic\n        @CapabilityInject(IDrawerAttributes::class)\n        val drawerAttributesCapability: Capability<IDrawerAttributes>? = null\n    }\n\n    override fun isType(tile: TileEntity, dir: EnumFacing?): Boolean = tile.hasCapability(drawerGroupCapability!!, dir)\n\n    override fun getUtilForTile(\n        tile: TileEntity,\n        direction: EnumFacing?,\n        mode: ProviderMode\n    ): SpecialInventoryHandler? =\n        drawerGroupCapability?.let {\n            val drawerAttributes = drawerAttributesCapability?.let { tile.getCapability(it, direction) }\n            tile.getCapability(drawerGroupCapability, direction)?.let { drawerGroup ->\n                StorageDrawersInventoryHandler(drawerGroup, drawerAttributes, mode)\n            }\n        }\n\n    override fun init(): Boolean =\n        Loader.instance().modList.firstOrNull { it.modId == LPConstants.storagedrawersModID }?.let {\n            val validVersions = VersionRange.createFromVersionSpec(\"[1.12.2-5.4.0,1.12.3)\")\n            val validVersionsFml = VersionRange.createFromVersionSpec(\"5.2.2\")\n            val version: ArtifactVersion = DefaultArtifactVersion(it.version)\n            (validVersions.containsVersion(version) || validVersionsFml.containsVersion(version))\n                    && drawerGroupCapability != null\n        } ?: false\n\n}\n\nclass StorageDrawersInventoryHandler(\n    private val drawerGroup: IDrawerGroup,\n    private val drawerAttributes: IDrawerAttributes?,\n    private val mode: ProviderMode,\n) : SpecialInventoryHandler() {\n\n    private fun checkSlot(slot: Int): Boolean = slot in mode.cropStart until (drawerGroup.drawerCount - mode.cropEnd)\n\n    private fun <T> fullDrawerApply(slot: Int, apply: (IDrawer) -> T) =\n        drawerGroup.getDrawer(slot).takeIf { it.isEnabled && !it.isEmpty }?.let(apply)\n\n    private fun accessibleDrawerSlots() = drawerGroup.accessibleDrawerSlots.filter(::checkSlot)\n\n    private fun slotMachine() = accessibleDrawerSlots()\n        .flatMap { slot ->\n            fullDrawerApply(slot) {\n                listOf(Triple(slot, it.storedItemPrototype, it.storedItemCount))\n            } ?: emptyList()\n        }\n\n    private fun Int.hideSinglePerTypeOrStack(): Int =\n        (if (mode.hideOnePerStack || mode.hideOnePerType) minus(1) else this).coerceAtLeast(0)\n\n    private fun Int.hideSinglePerStack(): Int = if (mode.hideOnePerStack) minus(1) else this\n\n    private fun enabledDrawerSequence(): Sequence<IDrawer> =\n        accessibleDrawerSlots().asSequence()\n            .map { slot -> drawerGroup.getDrawer(slot) }\n            .filter { drawer -> drawer.isEnabled }\n\n    override fun getItems(): MutableSet<ItemIdentifier> = accessibleDrawerSlots().flatMapTo(HashSet()) { slot ->\n        fullDrawerApply(slot) { listOf(ItemIdentifier.get(it.storedItemPrototype)) } ?: emptyList()\n    }\n\n    override fun getStackInSlot(slot: Int): ItemStack =\n        if (checkSlot(slot) && slot in drawerGroup.accessibleDrawerSlots) {\n            fullDrawerApply(slot) { it.storedItemPrototype } ?: ItemStack.EMPTY\n        } else ItemStack.EMPTY\n\n    override fun decrStackSize(slot: Int, amount: Int): ItemStack =\n        if (amount <= 0) ItemStack.EMPTY else getStackInSlot(slot).let { slotStack ->\n            if (slotStack.isEmpty) slotStack else slotStack.copy().also { stackCopy ->\n                if (drawerAttributes?.isUnlimitedStorage == true || drawerAttributes?.isUnlimitedVending == true) {\n                    stackCopy.count = amount\n                } else {\n                    val wantToDecrease = -min(amount, slotStack.count.hideSinglePerTypeOrStack())\n                    val toDecrease = drawerGroup.getDrawer(slot).adjustStoredItemCount(wantToDecrease)\n                    stackCopy.grow(toDecrease)\n                }\n            }\n        }\n\n    override fun itemCount(itemid: ItemIdentifier): Int = slotMachine()\n        .filter { (_, stack, _) -> itemid.equalsWithNBT(stack) }\n        .sumOf { (_, _, count) -> count.hideSinglePerStack() }\n        .apply { if (mode.hideOnePerType && !mode.hideOnePerStack) minus(1) }\n        .coerceAtLeast(0)\n\n    override fun getItemsAndCount(): MutableMap<ItemIdentifier, Int> = HashMap<ItemIdentifier, Int>().also { map ->\n        slotMachine().forEach { (_, stack, count) ->\n            map.compute(ItemIdentifier.get(stack)) { _, existing ->\n                count.hideSinglePerStack() + (existing ?: if (mode.hideOnePerType && !mode.hideOnePerStack) -1 else 0)\n            }\n        }\n        map.forEach { (k, v) -> map[k] = v.coerceAtLeast(0) }\n    }\n\n    override fun getSizeInventory(): Int = drawerGroup.drawerCount\n\n    override fun getMultipleItems(itemid: ItemIdentifier, count: Int): ItemStack {\n        var left = count\n        enabledDrawerSequence()\n            .takeWhile { left > 0 }\n            .filter { drawer -> !drawer.isEmpty && itemid.equalsWithNBT(drawer.storedItemPrototype) }\n            .forEach { drawer -> left = drawer.adjustStoredItemCount(-left) }\n        return itemid.makeNormalStack(count - left)\n    }\n\n    override fun containsUndamagedItem(itemid: ItemIdentifier): Boolean =\n        accessibleDrawerSlots().any { slot ->\n            fullDrawerApply(slot) { drawer -> itemid.equalsWithNBT(drawer.storedItemPrototype) } ?: false\n        }\n\n    override fun add(stack: ItemStack, orientation: EnumFacing?, doAdd: Boolean): ItemStack {\n        var left = stack.count\n        enabledDrawerSequence()\n            .takeWhile { left > 0 }\n            .filter { drawer -> drawer.canItemBeStored(stack) }\n            .forEach { drawer ->\n                left = if (doAdd) {\n                    drawer.adjustStoredItemCount(left)\n                } else {\n                    (left - drawer.acceptingRemainingCapacity).coerceAtLeast(0)\n                }\n            }\n        return stack.copy().also { it.grow(-left) }\n    }\n\n    override fun roomForItem(stack: ItemStack): Int = accessibleDrawerSlots().map { slot ->\n        drawerGroup.getDrawer(slot)\n            .let { if (it.isEnabled && it.canItemBeStored(stack)) it.acceptingRemainingCapacity else 0 }\n    }.sum()\n\n    override fun getSingleItem(item: ItemIdentifier?): ItemStack = throw NotImplementedError(\"Unused operation\")\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/util/ColorUtil.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\n/**\n * Extracts the 8 bits of alpha value information from the color code and returns them as an integer.\n * @return 8 bit (0-255) value of the Alpha channel.\n */\nfun Int.alpha(): Int = this shr 24 and 0xff\n\n/**\n * Extracts the 8 bits of alpha value information from the color code and returns them as an percentage float.\n * @return 8 bit (0-255) value of the Alpha channel as a float (0.0f - 1.0f).\n */\nfun Int.alphaF(): Float = alpha() / 255.0f\n\n/**\n * Extracts the 8 bits of red color information from the color code and returns them as an integer.\n * @return 8 bit (0-255) value of the Red channel.\n */\nfun Int.red(): Int = this shr 16 and 0xff\n\n/**\n * Extracts the 8 bits of red color information from the color code and returns them as an percentage float.\n * @return 8 bit (0-255) value of the Red channel as a float (0.0f - 1.0f).\n */\nfun Int.redF(): Float = red() / 255.0f\n\n/**\n * Extracts the 8 bits of green color information from the color code and returns them as an integer.\n * @return 8 bit (0-255) value of the Green channel.\n */\nfun Int.green(): Int = this shr 8 and 0xff\n\n/**\n * Extracts the 8 bits of green color information from the color code and returns them as an percentage float.\n * @return 8 bit (0-255) value of the Green channel as a float (0.0f - 1.0f).\n */\nfun Int.greenF(): Float = green() / 255.0f\n\n/**\n * Extracts the 8 bits of blue color information from the color code and returns them as an integer.\n * @return 8 bit (0-255) value of the Blue channel.\n */\nfun Int.blue(): Int = this and 0xFF\n\n/**\n * Extracts the 8 bits of blue color information from the color code and returns them as an percentage float.\n * @return 8 bit (0-255) value of the Blue channel as a float (0.0f - 1.0f).\n */\nfun Int.blueF(): Float = blue() / 255.0f\n\n/**\n * Prepends the pre-defined value of 255 on the alpha channel to ensure an opaque color.\n * @return the same left-most 24 bits but with the right 8 bits all being 1.\n */\nfun Int.opaque(): Int = prependAlpha(255)\n\n/**\n * Prepends the given value to the first 8 bits of a 32 bit integer.\n * @param alpha value of alpha that should be prepended. (0-255)\n * @return original int with the given alpha prepended.\n */\nfun Int.prependAlpha(alpha: Int) = (this and 0x00FFFFFF) or (alpha shl 24)\n\n/**\n * Cycles the input color in the range of 0..15. Descending when inverted is true.\n */\nfun cycleMinecraftColorId(color: Int, inverted: Boolean = false): Int {\n    var col = color\n    if (inverted) {\n        col--\n    } else {\n        col++\n    }\n    return when (col) {\n        16 -> 0\n        -1 -> 15\n        else -> col\n    }\n}"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/util/FuzzyUtil.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\nimport logisticspipes.utils.item.ItemIdentifier\nimport net.minecraft.item.ItemStack\nimport net.minecraft.nbt.NBTTagCompound\nimport network.rs485.logisticspipes.property.IBitSet\nimport java.util.*\n\nenum class FuzzyFlag(val bit: Int, val nbtName: String) {\n    IGNORE_DAMAGE(1, \"ignore_dmg\"),\n    IGNORE_NBT(2, \"ignore_nbt\"),\n    USE_ORE_DICT(0, \"use_od\"),\n    USE_ORE_CATEGORY(3, \"use_category\")\n}\n\ntypealias FuzzyFlagger = (flag: FuzzyFlag) -> Boolean\n\nobject FuzzyUtil {\n\n    fun readFromNBT(fuzzyBitSet: IBitSet, tag: NBTTagCompound) =\n        FuzzyFlag.values().forEach { fuzzyBitSet[it.bit] = tag.getBoolean(it.nbtName) }\n\n//    fun writeToNBT(fuzzyBitSet: IBitSet, tag: NBTTagCompound) =\n//        FuzzyFlag.values().forEach { tag.setBoolean(it.nbtName, fuzzyBitSet[it.bit]) }\n\n    fun set(fuzzyBitSet: IBitSet, flag: FuzzyFlag, value: Boolean) = fuzzyBitSet.set(flag.bit, value)\n    fun set(fuzzyBitSet: BitSet, flag: FuzzyFlag, value: Boolean) = fuzzyBitSet.set(flag.bit, value)\n    fun get(fuzzyBitSet: IBitSet, flag: FuzzyFlag): Boolean = fuzzyBitSet[flag.bit]\n    fun get(fuzzyBitSet: BitSet, flag: FuzzyFlag): Boolean = fuzzyBitSet[flag.bit]\n    fun getter(fuzzyBitSet: IBitSet): FuzzyFlagger = { get(fuzzyBitSet, it) }\n    fun getter(fuzzyBitSet: BitSet): FuzzyFlagger = { get(fuzzyBitSet, it) }\n\n    fun fuzzyMatches(\n        fuzzyFlagger: FuzzyFlagger,\n        firstItem: ItemIdentifier,\n        secondItem: ItemIdentifier,\n    ): Boolean {\n        val useOreCategory = fuzzyFlagger(FuzzyFlag.USE_ORE_CATEGORY)\n        if (fuzzyFlagger(FuzzyFlag.USE_ORE_DICT) || useOreCategory) {\n            val firstDictIdent = firstItem.dictIdentifiers\n            val secondDictIdent = secondItem.dictIdentifiers\n            if (firstDictIdent != null && secondDictIdent != null) {\n                if (firstDictIdent.canMatch(secondDictIdent, true, useOreCategory)) {\n                    return true\n                }\n            }\n        }\n        val firstStack: ItemStack = firstItem.makeNormalStack(1)\n        val secondStack: ItemStack = secondItem.makeNormalStack(1)\n        if (firstStack.item !== secondStack.item) {\n            return false\n        }\n        if (firstStack.itemDamage != secondStack.itemDamage) {\n            if (firstStack.hasSubtypes) {\n                return false\n            } else if (!fuzzyFlagger(FuzzyFlag.IGNORE_DAMAGE)) {\n                return false\n            }\n        }\n        if (fuzzyFlagger(FuzzyFlag.IGNORE_NBT)) {\n            return true\n        }\n        if (firstStack.hasTagCompound() xor secondStack.hasTagCompound()) {\n            return false\n        }\n        return if (!firstStack.hasTagCompound() && !secondStack.hasTagCompound()) {\n            true\n        } else ItemStack.areItemStackTagsEqual(firstStack, secondStack)\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/util/Item.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\nimport logisticspipes.utils.SinkReply\nimport logisticspipes.utils.item.ItemIdentifier\nimport net.minecraft.item.ItemStack\nimport network.rs485.logisticspipes.inventory.IItemIdentifierInventory\nimport kotlin.math.min\n\n\nfun ItemIdentifier.equalsWithNBT(stack: ItemStack): Boolean = this.item == stack.item &&\n        this.itemDamage == stack.itemDamage &&\n        ((this.tag == null && stack.tagCompound == null) ||\n                (this.tag != null && stack.tagCompound != null && this.tag == stack.tagCompound))\n\nfun IItemIdentifierInventory.matchingSequence(stack: ItemStack) =\n    (0 until sizeInventory).asSequence().map { getIDStackInSlot(it) }\n        .filter { it != null && it.item.equalsWithoutNBT(stack) }\n\n\nfun getExtractionMax(stackCount: Int, maxExtractionCount: Int, sinkReply: SinkReply): Int {\n    return min(stackCount, maxExtractionCount).let {\n        if (sinkReply.maxNumberOfItems > 0) {\n            min(it, sinkReply.maxNumberOfItems)\n        } else it\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/util/TextUtil.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\nimport net.minecraft.client.Minecraft\nimport net.minecraft.client.gui.FontRenderer\nimport net.minecraft.client.resources.I18n\nimport net.minecraft.item.ItemStack\nimport net.minecraft.util.text.TextFormatting\nimport java.text.NumberFormat\nimport java.util.*\n\nobject TextUtil {\n\n    private const val holdShiftTooltip: String = \"misc.holdshift\"\n    private val numberPrefixes: List<Pair<Double, String>> = listOf(1e0 to \"\", 1e3 to \"k\", 1e6 to \"M\", 1e9 to \"G\", 1e12 to \"T\", 1e15 to \"P\", 1e18 to \"E\")\n    private val formattingState: EnumSet<TextFormatting> = EnumSet.noneOf(TextFormatting::class.java)\n    private val baseFormattingState: EnumSet<TextFormatting> = EnumSet.noneOf(TextFormatting::class.java)\n    private val regexPattern =\n            TextFormatting.values().joinToString(\"|\", prefix = \"(\\\\$)(\", postfix = \")\") { it.friendlyName.uppercase() }\n                    .toRegex()\n\n    @JvmStatic\n    fun translate(\n            key: String,\n            vararg args: String\n    ): String =\n            translate(\n                    key = key,\n                    baseFormatting = EnumSet.noneOf(TextFormatting::class.java),\n                    args = args\n            )\n\n    @JvmStatic\n    fun translate(\n        key: String,\n        baseFormatting: EnumSet<TextFormatting> = EnumSet.noneOf(TextFormatting::class.java),\n        prepend: String = \"\",\n        append: String = \"\",\n        args: Array<out String>,\n    ): String = transform(prepend + I18n.format(key, *args) + append, baseFormatting)\n\n    @JvmStatic\n    fun getTrimmedString(text: String, maxWidth: Int, fontRenderer: FontRenderer, postfix: CharSequence = \"...\"): String {\n        if (fontRenderer.getStringWidth(text) < maxWidth) return text\n        var result = \"\"\n        text.takeWhile { char ->\n            (fontRenderer.getStringWidth(result + char + postfix) < maxWidth).also { fitsInWidth ->\n                if (fitsInWidth) {\n                    result += char\n                }\n            }\n        }\n        return result.trim() + postfix\n    }\n\n\n    /**\n     *  Turns the long value into a formatted number string following the metric prefixes.\n     *  The result is limited to 3 digits and to achieve it when the number is above 100 in\n     *  each scale it will be translated to the next higher scale as so: 0Px where P is the\n     *  higher prefix and x is the value in the hundreds equivalent to the previous prefix.\n     *  @param number to be formatted.\n     *  @param forceDisplayNumber whether 1 should return an empty string or itself.\n     *  @return 3 digit string, not constrained but should never exceed it.\n     */\n    @JvmStatic\n    fun getThreeDigitFormattedNumber(number: Long, forceDisplayNumber: Boolean): String {\n        return numberPrefixes.firstOrNull { prefix ->\n            number == 0L || (number >= prefix.first * 0.1 && number < prefix.first * 100)\n        }?.let { prefix ->\n            when {\n                number == 1L && !forceDisplayNumber -> \"\"\n                number < 1000 -> number.toString() // Don't touch less than 3 digit values\n                else -> (number / prefix.first).toInt().toString() + prefix.second + if (number > 10 * prefix.first) {\n                    \"\"\n                } else {\n                    ((number % prefix.first) / (prefix.first / 10)).toInt().takeIf { decimal -> decimal > 0 }?: \"\"\n                }\n            }\n        } ?: \"NaN\"\n    }\n\n    @JvmStatic\n    fun addTooltipInformation(stack: ItemStack, tooltip: MutableList<String>, extended: Boolean){\n        if(extended) {\n            var tooltipLine = 1\n            while(I18n.hasKey(\"${stack.translationKey}.tip$tooltipLine\")){\n                tooltip += translate(\"${stack.translationKey}.tip$tooltipLine\")\n                tooltipLine++\n            }\n        } else {\n            if(I18n.hasKey(\"${stack.translationKey}.tip1\")){\n                tooltip += translate(holdShiftTooltip)\n            }\n        }\n    }\n\n    /**\n     * Logistics Pipes localization files accept special (more descriptive)\n     * formatting tags this method is supposed to turn them into minecraft\n     * font renderer compatible tags. baseFormatting will be preserved over $RESET tags.\n     * @param text to be formatted\n     * @param baseFormatting to be applied at the start of the string and will be preserved throughout.\n     * @return formatted string ready to be rendered by Minecraft's font renderer.\n     */\n    fun transform(text: String, baseFormatting: EnumSet<TextFormatting>): String {\n        baseFormattingState.clear()\n        baseFormattingState.addAll(baseFormatting)\n        formattingState.clear()\n        var result = text.prependIndent(baseFormattingState.getColorTag() + baseFormattingState.getFormattingTags())\n        while (regexPattern.containsMatchIn(result)) {\n            result = regexPattern.replace(\n                    input = result,\n                    transform = { matchResult ->\n                        getReplacementString(matchResult.getTextFormatting())\n                    }\n            )\n        }\n        return result\n    }\n\n    @JvmStatic\n    fun formatNumberWithCommas(number: Long): String =\n            NumberFormat.getNumberInstance(Minecraft.getMinecraft().languageManager.currentLanguage.javaLocale).format(number)\n\n    private fun getReplacementString(formatting: TextFormatting): String {\n        if (formatting == TextFormatting.RESET) {\n            formattingState.clear()\n            return formatting.toString() + baseFormattingState.getColorTag() + baseFormattingState.getFormattingTags()\n        }\n        if (formatting.isColor) {\n            formattingState.removeAll { it.isColor }\n        }\n        formattingState.add(formatting)\n        return formattingState.getColorTag() + formattingState.getFormattingTags()\n    }\n\n    private fun MatchResult.getTextFormatting(): TextFormatting = TextFormatting.getValueByName(value.lowercase())!!\n\n    private fun EnumSet<TextFormatting>.getColorTag(): String =\n            this.firstOrNull { it.isColor }?.toString() ?: baseFormattingState.firstOrNull { it.isColor }?.toString()\n            ?: \"\"\n\n    private fun EnumSet<TextFormatting>.getFormattingTags(): String =\n            (this + baseFormattingState).filter { it.isFancyStyling }.joinToString(separator = \"\") { it.toString() }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/util/math/BorderedRectangle.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util.math\n\nimport network.rs485.logisticspipes.util.IRectangle\nimport network.rs485.logisticspipes.util.Rectangle\n\nclass BorderedRectangle<R : IRectangle>(\n    outer: R,\n    borderTop: Int,\n    borderLeft: Int,\n    borderBottom: Int,\n    borderRight: Int,\n) {\n\n    constructor(outer: R, border: Int) : this(outer, border, border, border, border)\n\n    val inner = MutableRectangle.fromRectangle(outer)\n        .translate(borderLeft, borderTop)\n        .grow(-borderLeft - borderRight, -borderTop - borderBottom)\n\n    // Corners\n    val topRight: IRectangle = Rectangle(inner.right to outer.top, outer.right to inner.top)\n    val topLeft: IRectangle = Rectangle(outer.left to outer.top, inner.left to inner.top)\n    val bottomLeft: IRectangle = Rectangle(outer.left to inner.bottom, inner.left to outer.bottom)\n    val bottomRight: IRectangle = Rectangle(inner.right to inner.bottom, outer.right to outer.bottom)\n\n    // Sides\n    val top: IRectangle = Rectangle(inner.left to outer.top, inner.right to inner.top)\n    val left: IRectangle = Rectangle(outer.left to inner.top, inner.left to inner.bottom)\n    val bottom: IRectangle = Rectangle(inner.left to inner.bottom, inner.right to outer.bottom)\n    val right: IRectangle = Rectangle(inner.right to inner.top, outer.right to inner.bottom)\n\n    val corners: List<IRectangle> = listOf(topRight, topLeft, bottomLeft, bottomRight)\n\n    val sides: List<IRectangle> = listOf(top, left, bottom, right)\n\n    val borderQuads: List<IRectangle> = listOf(topRight, top, topLeft, left, bottomLeft, bottom, bottomRight, right)\n\n    val quads: List<IRectangle> = borderQuads + inner\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/util/math/MutableRectangle.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util.math\n\nimport network.rs485.logisticspipes.util.IRectangle\nimport org.jetbrains.annotations.Contract\nimport kotlin.math.max\nimport kotlin.math.min\n\nclass MutableRectangle(\n    private var x: Float = 0.0f,\n    private var y: Float = 0.0f,\n    private var _width: Float,\n    private var _height: Float,\n) : IRectangle {\n\n    companion object {\n        fun fromRectangle(rect: IRectangle): MutableRectangle {\n            return MutableRectangle(rect.x0, rect.y0, rect.width, rect.height)\n        }\n    }\n\n    override val width: Float\n        get() = _width\n    override val height: Float\n        get() = _height\n    override val x0: Float\n        get() = x\n    override val y0: Float\n        get() = y\n\n    /**\n     * Default constructor, sets all fields to 0.\n     */\n    constructor() : this(0f, 0f, 0f, 0f)\n\n    /**\n     * Default constructor with integers as parameters.\n     */\n    constructor(x: Int, y: Int, width: Int, height: Int) : this(\n        x.toFloat(),\n        y.toFloat(),\n        width.toFloat(),\n        height.toFloat()\n    )\n\n    /**\n     * Creates rectangle at \"origin\" with set width and height\n     * @param width rectangle's width.\n     * @param height rectangle's height.\n     */\n    constructor(width: Int, height: Int) : this(0.0f, 0.0f, width.toFloat(), height.toFloat())\n\n    /**\n     * Creates rectangle from two points, since dimensions are Int the second point will be rounded down to accommodate.\n     * The exact corner that each point represents is not enforced but some things might break if it doesn't match this.\n     * @param firstPoint top-left point of the rectangle.\n     * @param secondPoint bottom-right point of the rectangle.\n     */\n    constructor(firstPoint: Pair<Float, Float>, secondPoint: Pair<Float, Float>) : this(\n        firstPoint.first,\n        firstPoint.second,\n        (secondPoint.first - firstPoint.first),\n        (secondPoint.second - firstPoint.second)\n    )\n\n    // Transformations\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun setSize(newWidth: Float, newHeight: Float): MutableRectangle = apply {\n        _width = newWidth\n        _height = newHeight\n    }\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun setSize(newWidth: Int, newHeight: Int): MutableRectangle = setSize(newWidth.toFloat(), newHeight.toFloat())\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun grow(growX: Float, growY: Float): MutableRectangle = apply {\n        _width += growX\n        _height += growY\n    }\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun grow(grow: Float): MutableRectangle = grow(grow, grow)\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun grow(growX: Int, growY: Int): MutableRectangle = grow(growX.toFloat(), growY.toFloat())\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun grow(grow: Int): MutableRectangle = grow(grow, grow)\n\n    fun setSizeFromRectangle(rect: IRectangle) = setSize(rect.width, rect.height)\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun scaleSize(multiplier: Float): MutableRectangle = apply {\n        _width *= multiplier\n        _height *= multiplier\n    }\n\n    // Translations\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun setPos(newX: Float, newY: Float): MutableRectangle = apply {\n        x = newX\n        y = newY\n    }\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun setPos(newX: Int, newY: Int): MutableRectangle = setPos(newX.toFloat(), newY.toFloat())\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun setPosFromRectangle(rect: IRectangle): MutableRectangle = setPos(rect.x0, rect.y0)\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun resetPos(): MutableRectangle = apply { setPos(0.0f, 0.0f) }\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun scalePos(multiplier: Float): MutableRectangle = apply {\n        x *= multiplier\n        y *= multiplier\n    }\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun translate(translate: Float): MutableRectangle = translate(translate, translate)\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun translate(translateX: Float = 0.0f, translateY: Float = 0.0f): MutableRectangle = apply {\n        x += translateX\n        y += translateY\n    }\n\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun translate(translate: Int): MutableRectangle = translate(translate, translate)\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun translate(translateX: Int = 0, translateY: Int = 0): MutableRectangle = apply {\n        x += translateX\n        y += translateY\n    }\n\n    // Non-destructive\n    override fun translated(translateX: Float, translateY: Float): MutableRectangle =\n        copy().translate(translateX, translateY)\n    override fun translated(translateX: Int, translateY: Int): MutableRectangle =\n        copy().translate(translateX, translateY)\n\n    // Both\n    @Contract(\"_ -> this\", mutates = \"this\")\n    fun scale(multiplier: Float): MutableRectangle = scalePos(multiplier).scaleSize(multiplier)\n\n    // Non-destructive\n    override fun scaled(multiplier: Float): MutableRectangle = copy().scalePos(multiplier).scaleSize(multiplier)\n\n    // Operations\n    override fun overlap(rect: IRectangle): MutableRectangle =\n        MutableRectangle(max(this.x, rect.x0) to max(this.y, rect.y0), min(this.x1, rect.x1) to min(this.y1, rect.y1))\n\n    fun copy(): MutableRectangle = MutableRectangle(x, y, _width, _height)\n\n    override fun toString(): String {\n        return \"Rectangle(x = $x, y = $y, width = $_width, height = $_height)\"\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/logisticspipes/world/WorldCoordinatesWrapper.kt",
    "content": "/*\n * Copyright (c) 2019-2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2019-2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.world\n\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.proxy.MainProxy\nimport logisticspipes.proxy.SimpleServiceLocator\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.world.World\nimport network.rs485.logisticspipes.connection.LPNeighborTileEntity\n\ndata class WorldCoordinatesWrapper(private val world: World, private val pos: BlockPos) {\n    constructor(tileEntity: TileEntity) : this(tileEntity.world, tileEntity.pos)\n\n    val tileEntity: TileEntity?\n        get() = world.getTileEntity(pos)\n\n    fun allNeighborTileEntities(): List<LPNeighborTileEntity<TileEntity>> =\n        EnumFacing.VALUES.mapNotNull { direction: EnumFacing -> getNeighbor(direction) }\n\n    fun connectedTileEntities(): List<LPNeighborTileEntity<TileEntity>> {\n        val pipe = tileEntity\n        if (SimpleServiceLocator.pipeInformationManager.isNotAPipe(pipe)) {\n            LogisticsPipes.log.warn(\"The coordinates didn't hold a pipe at all\", Throwable(\"Stack trace\"))\n            return emptyList()\n        }\n        return allNeighborTileEntities().filter { adjacent -> MainProxy.checkPipesConnections(pipe, adjacent.tileEntity, adjacent.direction) }\n    }\n\n    fun getNeighbor(direction: EnumFacing): LPNeighborTileEntity<TileEntity>? {\n        val tileEntity = world.getTileEntity(pos.offset(direction)) ?: return null\n        return LPNeighborTileEntity(tileEntity, direction)\n    }\n\n    override fun hashCode(): Int {\n        var result = world.hashCode()\n        result = 31 * result + pos.hashCode()\n        return result\n    }\n\n    override fun equals(other: Any?): Boolean {\n        if (other === this) return true\n        if (other !is WorldCoordinatesWrapper) return false\n        return world == other.world && pos == other.pos\n    }\n\n    override fun toString(): String {\n        return \"WorldCoordinatesWrapper(world=$world, pos=$pos)\"\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/markdown/Element.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.markdown\n\nimport logisticspipes.LPItems\nimport logisticspipes.LogisticsPipes\nimport logisticspipes.utils.MinecraftColor\nimport com.google.common.collect.ImmutableSet\nimport net.minecraft.item.Item\nimport net.minecraft.item.ItemStack\nimport net.minecraft.util.ResourceLocation\nimport java.util.*\n\ndata class InlineDrawableState(var format: Set<TextFormat>, var color: Int, var link: Link?)\n\nsealed class Link\n\ndata class WebLink(val url: String) : Link() {\n    init {\n        assert(url.isNotEmpty())\n    }\n}\n\ndata class PageLink(val page: String) : Link() {\n    init {\n        assert(page.isNotEmpty())\n    }\n}\n\nclass ItemLink(translationKey: String) : Link() {\n\n    val stack: ItemStack\n\n    init {\n        stack = if (translationKey.isNotEmpty() && translationKey.contains(\":\")) {\n            val resourceLocation = translationKey.split(\":\").let { it ->\n                ResourceLocation(\n                        it.getOrElse(0) { \"logisticspipes\" },\n                        it.getOrElse(1) { \"broken_item\" }\n                )\n            }\n            val item: Item? = Item.REGISTRY.getObject(resourceLocation)\n            if(item == null) {\n                LogisticsPipes.log.error(\"Item doesn't exist: $translationKey\")\n            }\n            ItemStack(item ?: LPItems.brokenItem)\n        } else {\n            ItemStack(LPItems.brokenItem)\n        }\n    }\n}\n\nsealed class InlineElement {\n    open fun changeDrawableState(state: InlineDrawableState) {}\n}\n\ndata class LinkFormatting(val link: Link?) : InlineElement() {\n    override fun changeDrawableState(state: InlineDrawableState) {\n        state.link = this.link\n    }\n}\n\ndata class TextFormatting(val format: EnumSet<TextFormat>) : InlineElement() {\n    override fun changeDrawableState(state: InlineDrawableState) {\n        state.format = this.format\n    }\n}\n\ndata class ColorFormatting(val color: Int) : InlineElement() {\n    override fun changeDrawableState(state: InlineDrawableState) {\n        state.color = this.color\n    }\n}\n\nobject Space : InlineElement() {\n    override fun toString(): String {\n        return \"Markdown Space Element\"\n    }\n}\n\nobject Break : InlineElement() {\n    override fun toString(): String {\n        return \"Markdown Break Element\"\n    }\n}\n\ndata class Word(val str: String) : InlineElement() {\n    init {\n        assert(str.isNotEmpty())\n    }\n}\n\n/**\n * Used to track the tags a token has so the renderer knows how to draw said token.\n */\nenum class TextFormat {\n    Italic,\n    Bold,\n    Strikethrough,\n    Underline,\n    Shadow;\n\n    companion object {\n        val none: EnumSet<TextFormat>\n            get() = EnumSet.noneOf(TextFormat::class.java)\n    }\n}\n\nfun Set<TextFormat>.italic() = this.contains(TextFormat.Italic)\n\nfun Set<TextFormat>.bold() = this.contains(TextFormat.Bold)\n\nfun Set<TextFormat>.strikethrough() = this.contains(TextFormat.Strikethrough)\n\nfun Set<TextFormat>.underline() = this.contains(TextFormat.Underline)\n\nfun Set<TextFormat>.shadow() = this.contains(TextFormat.Shadow)\n\nval defaultDrawableState = InlineDrawableState(\n        format = ImmutableSet.of(),\n        color = MinecraftColor.WHITE.colorCode,\n        link = null,\n)\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/markdown/MarkdownParser.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.markdown\n\nimport org.apache.http.NameValuePair\nimport org.apache.http.client.utils.URLEncodedUtils\nimport java.lang.Integer.min\nimport java.net.URI\nimport java.net.URISyntaxException\nimport java.util.*\nimport java.util.stream.IntStream\nimport kotlin.collections.ArrayList\n\ntypealias WordCreator = (String) -> Word?\ntypealias TextToElements = (CharSequence) -> List<InlineElement>\n\nobject MarkdownParser {\n    private val linkRegex = Regex(\"!?\\\\[(.+?)]\\\\((.+?)\\\\)\")\n    private val webLinkRegex = Regex(\"^https?://.+\", RegexOption.IGNORE_CASE)\n    private val boldItalicRegexes = (3 downTo 1)\n        .flatMap { times -> listOf(\"_\", \"\\\\*\").map { times to it.repeat(times) } }\n        .map { (times, formatChain) -> times to Regex(\"(?!\\\\\\\\)$formatChain(.+?)(?!\\\\\\\\)$formatChain\") }\n    private val pathRegex = Regex(\"^.*?://([^?]+)\")\n\n    private class LinkMatcher(val match: MatchResult) {\n        val text: String?\n            get() = match.groups[1]?.value\n        val link: String?\n            get() = match.groups[2]?.value\n        val path: String?\n            get() = link?.let { pathRegex.find(it) }?.groups?.get(1)?.value\n        val imageLinkFlag: Boolean\n            get() = match.value.trimStart().startsWith('!')\n        val uri: URI? by lazy {\n            link?.let {\n                try {\n                    URI(it)\n                } catch (error: URISyntaxException) {\n                    null\n                }\n            }\n        }\n        val queryComponents: List<NameValuePair>\n            get() = uri?.let { URLEncodedUtils.parse(it.query, Charsets.UTF_8) } ?: emptyList()\n\n        fun getMenuType() = if (uri?.scheme == \"menu\")\n            queryComponents.find { it.name == \"type\" }.let { type ->\n                when {\n                    type == null -> MenuParagraphType.LIST\n                    type.value == \"list\" -> MenuParagraphType.LIST\n                    type.value == \"tile\" -> MenuParagraphType.TILE\n                    else -> null\n                }\n            } else null\n\n        fun isPageLink() = link?.startsWith(\"page://\", ignoreCase = true) ?: false\n        fun isWebLink() = link?.matches(webLinkRegex) ?: false\n        fun isImageLink() = link?.startsWith(\"image://\", ignoreCase = true) ?: false\n        fun isItemLink() = link?.startsWith(\"item://\", ignoreCase = true) ?: false\n    }\n\n    private val htmlBreakRegex = Regex(\"<br(\\\\s*/)?>\")\n\n    internal fun splitWhitespaceCharactersAndWords(inputChars: CharSequence): List<InlineElement> {\n        // newlines are already handled as special break characters at this point\n        val chars = htmlBreakRegex.replace(inputChars, \"\\n\")\n\n        // breaks up all the words and returns them as inline elements without spaces\n        return chars\n            .split('\\n')\n            .map { words ->\n                splitAndFormatWords(words) + listOf(Break)\n            }\n            .flatten()\n            .dropLast(1)\n    }\n\n    class ReplacedCharSequence(val original: CharSequence) : CharSequence {\n        private val formattingStart = mutableListOf<Pair<Int, EnumSet<TextFormat>>>()\n        private val replacementMap = mutableListOf<Pair<IntRange, InlineElement>>()\n        private val stagingReplacementMap = mutableListOf<Triple<Int, IntRange, InlineElement>>()\n        private var cache: String? = null\n        val current: String\n            get() = cache ?: updateCachedSequence()\n\n        private fun updateCachedSequence(): String {\n            val sb = StringBuilder()\n            val append = { range: IntRange -> range.takeIf { !it.isEmpty() }?.also { sb.append(original.subSequence(it)) } }\n            var lastIdx = 0\n            replacementMap.forEach { (range, _) ->\n                assert(range.first >= lastIdx) { \"trying to replace already replaced index $lastIdx in $replacementMap\" }\n                append(lastIdx until range.first)\n                lastIdx = range.last + 1\n            }\n            append(lastIdx until original.length)\n            return sb.toString().also { cache = it }\n        }\n\n        private fun spaceReplacement(cutIndex: Int) = isWhitespaceAt(cutIndex).also { isSpace ->\n            if (isSpace) stageReplacingElement(cutIndex..cutIndex, Space)\n        }\n\n        fun addReplacement(fullRange: IntRange, innerRange: IntRange, format: EnumSet<TextFormat>) {\n            if (fullRange.first > 0) {\n                if (!spaceReplacement(innerRange.first)) spaceReplacement(fullRange.first - 1)\n            }\n            // add format end before start, so that $format is not detected as existing formatting and added here\n            stageReplacingElement((innerRange.last + 1)..fullRange.last, TextFormatting(TextFormat.none))\n            stageReplacingElement(fullRange.first until innerRange.first, TextFormatting(format.clone()))\n            enhanceExistingReplacements(innerRange, format)\n            if (fullRange.last + 1 < length) {\n                if (!spaceReplacement(innerRange.last)) spaceReplacement(fullRange.last + 1)\n            }\n        }\n\n        private fun enhanceExistingReplacements(range: IntRange, format: Set<TextFormat>) {\n            val (endReplacementMapIdx, _) = translateIndex(range.last)\n            if (endReplacementMapIdx == -1) return\n            val (startReplacementMapIdx, _) = translateIndex(range.first)\n            replacementMap.subList(startReplacementMapIdx + 1, endReplacementMapIdx + 1).forEach {\n                (it.second as? TextFormatting)?.format?.addAll(format)\n            }\n        }\n\n        private fun stageReplacingElement(range: IntRange, element: InlineElement) {\n            val (replacementMapIdx, translatedIdx) = translateIndex(range.first)\n            stagingReplacementMap.add(\n                Triple(replacementMapIdx + 1, translatedIdx..(range.last + translatedIdx - range.first), element)\n            )\n            if (element is TextFormatting) {\n                val newFormat = (translatedIdx to element.format)\n                if (formattingStart.isEmpty()) {\n                    formattingStart.add(newFormat)\n                } else {\n                    val formatIdx = formattingStart.binarySearch(newFormat, comparator = { o1, o2 ->\n                        o1.first.compareTo(o2.first)\n                    })\n                    val index = if (formatIdx < 0) -formatIdx - 1 else formatIdx + 1\n                    // add previous formatting, if applicable\n                    if (index > 0) newFormat.second.addAll(formattingStart[index - 1].second)\n                    formattingStart.add(index, newFormat)\n                }\n            }\n        }\n\n        private fun translateIndex(start: Int): Pair<Int, Int> {\n            var translatedIdx = start\n            var replacementMapIdx = -1\n            replacementMap.asSequence()\n                .takeWhile { translatedIdx >= it.first.first }\n                .forEachIndexed { curry, (range, _) ->\n                    translatedIdx += range.count()\n                    replacementMapIdx = curry\n                }\n            return replacementMapIdx to translatedIdx\n        }\n\n        fun commit() {\n            if (stagingReplacementMap.isNotEmpty()) {\n                stagingReplacementMap.sortedByDescending {\n                    // insertion into replacementMap needs to be ordered,\n                    // because the replacements' indices are translated\n                    it.second.last\n                }.forEach { (index: Int, replaceRange: IntRange, element: InlineElement) ->\n                    (index - 1).takeIf { replacementIndexIsTextFormatting(it, element) }\n                        ?.let { previousIdx -> replaceFormattingIfApplicable(previousIdx, replacementMap[previousIdx].first, replaceRange, element) }\n                    ?: index.takeIf { replacementIndexIsTextFormatting(index, element) }\n                        ?.let { idx -> replaceFormattingIfApplicable(idx, replaceRange, replacementMap[idx].first, replacementMap[idx].second) }\n                    ?: replacementMap.add(index, replaceRange to element)\n                }\n                cache = null\n                stagingReplacementMap.clear()\n            }\n        }\n\n        private fun replacementIndexIsTextFormatting(index: Int, element: InlineElement): Boolean =\n            index in replacementMap.indices && element is TextFormatting && replacementMap[index].second is TextFormatting\n\n        private fun replaceFormattingIfApplicable(\n            index: Int,\n            lowRange: IntRange,\n            highRange: IntRange,\n            element: InlineElement,\n        ): Pair<IntRange, InlineElement>? =\n            if (lowRange.last + 1 == highRange.first) {\n                (lowRange.first..highRange.last to element).also { replacementMap[index] = it }\n            } else null\n\n        fun forEachReplace(action: (Pair<IntRange, InlineElement>) -> Unit) = replacementMap.forEach(action)\n\n        override val length: Int\n            get() = current.length\n\n        fun isWhitespaceAt(index: Int): Boolean = get(index).isWhitespace()\n        override fun get(index: Int): Char = current[index]\n        override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = current.subSequence(startIndex, endIndex)\n        override fun chars(): IntStream = current.chars()\n        override fun codePoints(): IntStream = current.codePoints()\n        override fun equals(other: Any?): Boolean =\n            other is ReplacedCharSequence && original == other.original && replacementMap == other.replacementMap\n\n        override fun hashCode(): Int = original.hashCode() + replacementMap.hashCode()\n        override fun toString(): String =\n            \"${super.toString()}(original=\\\"${original.take(16)}[…]\\\",\" +\n                    \"replacementMap=${replacementMap.toString().take(16)}[…])\"\n\n    }\n\n    private fun splitAndFormatWords(inputChars: CharSequence, wordSplitter: TextToElements): List<InlineElement> {\n        val textLine = inputChars.trimEnd()\n        val replacingChars = ReplacedCharSequence(textLine)\n        boldItalicRegexes.forEach { (level, regex) ->\n            val format = when (level) {\n                3 -> EnumSet.of(TextFormat.Italic, TextFormat.Bold)\n                2 -> EnumSet.of(TextFormat.Bold)\n                1 -> EnumSet.of(TextFormat.Italic)\n                else -> TextFormat.none\n            }\n            regex.findAll(replacingChars).forEach { match ->\n                val textGroup = match.groups[1]!!\n                replacingChars.addReplacement(match.range, textGroup.range, format)\n            }\n            replacingChars.commit()\n        }\n        // TODO: add parsing for underline, strikethrough and shadow (with ~)\n        // TODO: add color parsing\n        val mappedWords = arrayListOf<InlineElement>()\n        fun addMappedWords(originalRange: IntRange) {\n            if (originalRange.isEmpty()) return\n            mappedWords.addAll(wordSplitter(textLine.subSequence(originalRange)))\n        }\n\n        var startIdx = 0\n        replacingChars.forEachReplace { (range, inlineElem) ->\n            addMappedWords(startIdx until range.first)\n            mappedWords.add(inlineElem)\n            startIdx = range.last + 1\n        }\n        addMappedWords(startIdx..replacingChars.original.lastIndex)\n        return mappedWords\n    }\n\n    internal fun splitAndFormatWords(inputChars: CharSequence): List<InlineElement> = splitAndFormatWords(inputChars, ::splitSpacesAndWords)\n\n    private fun splitSpacesAndWords(inputChars: CharSequence, makeWord: WordCreator): List<InlineElement> {\n        return inputChars\n            .split(' ')\n            .flatMap { word -> listOfNotNull(makeWord(word)) }\n            .plus(Space) // appended Space to be removed as the last right element in the following zipWithNext\n            .zipWithNext { left, right ->\n                // adds Spaces in between, makes sure Space always follows a Word\n                when {\n                    left is Word && right is Word -> listOf(left, Space)\n                    else -> listOf(left)\n                }\n            }\n            .flatten()\n    }\n\n    internal fun splitSpacesAndWords(inputChars: CharSequence): List<InlineElement> = splitSpacesAndWords(inputChars, ::parseTextElement)\n\n    private fun parseTextElement(word: String) = if (word.isNotBlank()) Word(word) else null\n\n    private fun parseLinks(inputChars: CharSequence): List<InlineElement> {\n        var lastCharLookedAt = 0\n        val postfixGetter = { if (lastCharLookedAt < inputChars.length) inputChars.subSequence(lastCharLookedAt, inputChars.length) else \"\" }\n        val isLastWhitespace = { lastCharLookedAt in 1 until inputChars.length && inputChars[lastCharLookedAt].isWhitespace() }\n        return linkRegex.findAll(inputChars)\n            .map { LinkMatcher(it) }\n            .flatMap { link ->\n                // checks link\n                val before = inputChars.subSequence(lastCharLookedAt, link.match.range.first)\n                listOf(\n                    splitWhitespaceCharactersAndWords(before).let { if (!isLastWhitespace() && it.isEmpty()) emptyList() else it + listOf(Space) },\n                    when {\n                        link.isPageLink() -> PageLink(link.path!!)\n                        link.isWebLink() -> WebLink(link.link!!)\n                        link.isItemLink() -> ItemLink(link.path!!)\n                        else -> null\n                    }?.let { linkRef ->\n                        listOf(\n                            listOfNotNull(Word(\"!\").takeIf { link.imageLinkFlag }),\n                            listOf(LinkFormatting(linkRef)),\n                            splitAndFormatWords(link.text!!),\n                            listOf(LinkFormatting(null)),\n                        ).flatten()\n                    } ?: splitWhitespaceCharactersAndWords(link.match.value),\n                ).flatten().also { lastCharLookedAt = link.match.range.last + 1 }\n            }\n            .toList()\n            .plus(if (isLastWhitespace()) listOf(Space) else emptyList())\n            .plus(splitWhitespaceCharactersAndWords(postfixGetter()))\n    }\n\n    private fun countChars(char: Char, str: String, index: Int = 0, maximum: Int = str.length): Int {\n        if (str[index] != char) return 0\n        var count = 1\n        val actualMax = min(str.length - index, maximum)\n        while (count < actualMax && str[index + count] == char) ++count\n        return count\n    }\n\n    fun parseParagraphs(str: String): List<Paragraph> {\n        val paragraphs = ArrayList<Paragraph>()\n        val sb = StringBuilder()\n        val lines = str.split('\\n')\n\n        fun completeParagraph() {\n            if (sb.isNotBlank()) {\n                paragraphs.add(RegularParagraph(parseLinks(sb)))\n            }\n            sb.clear()\n        }\n\n        lines.flatMap { line ->\n            // repack lines with special endings\n            bufferOrReturnLine(line, sb)\n        }.forEach { dirtyLine ->\n            val line = dirtyLine.trimStart()\n\n            fun dumpLineToBuffer() {\n                if (sb.isNotEmpty()) sb.append(' ')\n                sb.append(line)\n            }\n\n            val lineLinkMatch: LinkMatcher? by lazy {\n                linkRegex.find(line)?.takeIf { it.value == line.trimEnd() }?.let { LinkMatcher(it) }\n            }\n            when {\n                // every handling that is creating paragraphs\n                line.isEmpty() -> completeParagraph()\n                line.startsWith('#') -> {\n                    val charCount = countChars('#', line, maximum = 6)\n                    // check if there is at least one space and characters after the header indicators\n                    val text = line.trimStart('#')\n                    when {\n                        text.isBlank() -> dumpLineToBuffer()\n                        text[0] == ' ' -> {\n                            // it's an header!\n                            completeParagraph()\n                            paragraphs.add(HeaderParagraph(parseLinks(text.trimEnd('#')), charCount))\n                        }\n                        else -> dumpLineToBuffer()\n                    }\n                }\n                line.startsWith(\"===\") -> {\n                    paragraphs.add(if (sb.isBlank()) HorizontalLineParagraph else HeaderParagraph(parseLinks(sb.toString()), 1))\n                    sb.clear()\n                }\n                line.startsWith(\"---\") -> {\n                    paragraphs.add(if (sb.isBlank()) HorizontalLineParagraph else HeaderParagraph(parseLinks(sb.toString()), 2))\n                    sb.clear()\n                }\n                lineLinkMatch?.getMenuType() != null && !lineLinkMatch!!.imageLinkFlag ->\n                    lineLinkMatch?.also {\n                        completeParagraph()\n                        paragraphs.add(MenuParagraph(it.text!!, it.path!!, it.getMenuType()!!))\n                    }\n                lineLinkMatch?.isImageLink() == true && lineLinkMatch!!.imageLinkFlag ->\n                    lineLinkMatch?.also {\n                        completeParagraph()\n                        paragraphs.add(ImageParagraph(it.text!!, it.path!!))\n                    }\n                // TODO: add ListParagraph\n                else -> dumpLineToBuffer()\n            }\n        }\n        completeParagraph()\n        return paragraphs\n    }\n\n    private fun bufferOrReturnLine(line: String, buffer: StringBuilder): List<String> {\n        when {\n            line.endsWith('\\\\') -> {\n                // special handling for escaped line endings -> buffer line\n                buffer.append(line.substring(0, line.length - 1))\n                return emptyList()\n            }\n            line.endsWith(\"  \") -> {\n                // special handling for special line breaks -> add newline char\n                buffer.append(line.substring(0, line.length - 2))\n                buffer.append('\\n')\n            }\n            else -> buffer.append(line)\n        }\n        val concatLine = buffer.toString()\n        buffer.clear()\n        return listOf(concatLine)\n    }\n\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/markdown/Paragraph.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.markdown\n\nsealed class Paragraph\n\ndata class RegularParagraph(val elements: List<InlineElement>) : Paragraph()\n\ndata class HeaderParagraph(val elements: List<InlineElement>, val headerLevel: Int) : Paragraph()\n\ndata class MenuParagraph(val description: String, val link: String, val type: MenuParagraphType) : Paragraph()\n\nenum class MenuParagraphType {\n    TILE,\n    LIST,\n}\n\ndata class ImageParagraph(val alternative: String, val imagePath: String) : Paragraph()\n\nobject HorizontalLineParagraph : Paragraph()\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/util/ByteBufUtils.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.util\n\nimport io.netty.buffer.ByteBuf\n\ninternal fun ByteBuf.use(function: (ByteBuf) -> Unit) {\n    try {\n        function(this)\n    } finally {\n        release()\n    }\n}\n"
  },
  {
    "path": "src/main/kotlin/network/rs485/util/SystemUtil.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.util\n\nfun checkBooleanProperty(name: String) =\n    System.getProperty(name).let { it != null && it.equals(\"true\", true) }\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/integration/CraftingTest.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.integration\n\nimport network.rs485.logisticspipes.integration.MinecraftTest.TIMEOUT_MODIFIER\nimport network.rs485.logisticspipes.integration.MinecraftTest.regularTest\nimport network.rs485.logisticspipes.integration.MinecraftTest.skippedTest\nimport network.rs485.logisticspipes.util.FuzzyFlag\nimport network.rs485.logisticspipes.util.FuzzyUtil\nimport network.rs485.minecraft.BlockPlacer\nimport network.rs485.minecraft.BlockPosSelector\nimport network.rs485.minecraft.configurator\nimport logisticspipes.LPBlocks\nimport logisticspipes.LPItems\nimport logisticspipes.blocks.LogisticsSolidBlock\nimport logisticspipes.blocks.crafting.LogisticsCraftingTableTileEntity\nimport logisticspipes.pipes.PipeItemsBasicLogistics\nimport logisticspipes.pipes.PipeItemsCraftingLogistics\nimport logisticspipes.pipes.PipeItemsRequestLogistics\nimport logisticspipes.pipes.upgrades.FuzzyUpgrade\nimport logisticspipes.pipes.upgrades.UpgradeManager\nimport logisticspipes.utils.item.ItemIdentifier\nimport net.minecraft.block.BlockChest\nimport net.minecraft.block.BlockPlanks\nimport net.minecraft.init.Blocks\nimport net.minecraft.item.Item\nimport net.minecraft.item.ItemStack\nimport net.minecraft.tileentity.TileEntityChest\nimport net.minecraft.util.EnumFacing\nimport java.time.Duration\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\nimport kotlinx.coroutines.CompletableDeferred\nimport kotlinx.coroutines.delay\n\n@Suppress(\"FunctionName\")\nobject CraftingTest {\n    private val fuzzyUpgradeItem = Item.REGISTRY.getObject(LPItems.upgrades[FuzzyUpgrade.getName()])!!\n\n    suspend fun `test single fuzzy ingredient crafting fails multi-request with mixed OreDict input`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = skippedTest(loggerIn, selector) {\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata),\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.DARK_OAK.metadata),\n            ),\n        )\n        selector.finalize()\n        delay(5000) // FIXME: delay and pipe update should not be needed\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        val stacks = listOf(ItemStack(Blocks.CHEST))\n        setup.requesterPipe.requestItems(stacks, mustSucceed = false)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(stacks) },\n        )\n        assertTrue(message = \"a chest item was found in the requester chest\") {\n            waitForChestResult === null\n        }\n    }\n\n    suspend fun `test single fuzzy ingredient crafting fails with mixed OreDict input`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = skippedTest(loggerIn, selector) {\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata),\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.DARK_OAK.metadata),\n            ),\n        )\n        selector.finalize()\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        setup.requesterPipe.requestItem(ItemStack(Blocks.CHEST), mustSucceed = false)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(listOf(ItemStack(Blocks.CHEST))) },\n        )\n        assertTrue(message = \"a chest item was found in the requester chest\") {\n            waitForChestResult === null\n        }\n    }\n\n    suspend fun `test single fuzzy ingredient crafting succeeds with sufficient input of one OreDict type`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = skippedTest(loggerIn, selector) {\n        val trapItems = ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata)\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                trapItems,\n                ItemStack(Blocks.PLANKS, 8, BlockPlanks.EnumType.DARK_OAK.metadata),\n            ),\n        )\n        selector.finalize()\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        setup.requesterPipe.requestItem(ItemStack(Blocks.CHEST), mustSucceed = true)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(listOf(ItemStack(Blocks.CHEST))) },\n        )\n        assertTrue(message = \"a chest item was not found before a timeout\") {\n            waitForChestResult !== null\n        }\n        setup.providerChest.containsOnly(listOf(trapItems))\n    }\n\n    suspend fun `test single fuzzy ingredient crafting succeeds multi-request with sufficient input of one OreDict type`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = skippedTest(loggerIn, selector) {\n        val trapItems = ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata)\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                trapItems,\n                ItemStack(Blocks.PLANKS, 8, BlockPlanks.EnumType.DARK_OAK.metadata),\n            ),\n        )\n        selector.finalize()\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        val stacks = listOf(ItemStack(Blocks.CHEST))\n        setup.requesterPipe.requestItems(stacks, mustSucceed = true)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(stacks) },\n        )\n        assertTrue(message = \"a chest item was not found before a timeout\") {\n            waitForChestResult !== null\n        }\n        setup.providerChest.containsOnly(listOf(trapItems))\n    }\n\n    suspend fun `test single fuzzy ingredient crafting fails with mixed OreDict input on two provider pipes on one double chest`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = skippedTest(loggerIn, selector) {\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata),\n            ),\n        )\n        selector.direction(EnumFacing.NORTH)\n            .apply {\n                place(PipePlacer(PipeItemsBasicLogistics(LPItems.pipeBasic)))\n                setupProvidingChest(EnumFacing.WEST,\n                    ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.DARK_OAK.metadata))\n            }\n            .finalize()\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        setup.requesterPipe.requestItem(ItemStack(Blocks.CHEST), mustSucceed = false)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(listOf(ItemStack(Blocks.CHEST))) },\n        )\n        assertTrue(message = \"a chest item was found in the requester chest\") {\n            waitForChestResult === null\n        }\n    }\n\n    suspend fun `test single fuzzy ingredient crafting fails with mixed OreDict input on different providers`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = skippedTest(loggerIn, selector) {\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata),\n            ),\n        )\n        selector\n            .direction(EnumFacing.NORTH)\n            .place(UnroutedPipePlacer)\n            .direction(EnumFacing.NORTH)\n            .place(PipePlacer(PipeItemsBasicLogistics(LPItems.pipeBasic)))\n            .apply {\n                setupProvidingChest(EnumFacing.WEST,\n                    ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.DARK_OAK.metadata))\n            }\n            .finalize()\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        setup.requesterPipe.requestItem(ItemStack(Blocks.CHEST), mustSucceed = false)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(listOf(ItemStack(Blocks.CHEST))) },\n        )\n        assertTrue(message = \"a chest item was found in the requester chest\") {\n            waitForChestResult === null\n        }\n    }\n\n    suspend fun `test split fuzzy ingredients crafting succeeds with mixed OreDict input`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = regularTest(loggerIn, selector) {\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata),\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.DARK_OAK.metadata),\n            ),\n        )\n        selector.finalize()\n        (0 until 8).forEach {\n            setup.craftingPipe.dummyInventory.setInventorySlotContents(it,\n                ItemStack(Blocks.PLANKS, 1, BlockPlanks.EnumType.OAK.metadata))\n            FuzzyUtil.set(setup.craftingPipe.logisticsModule.inputFuzzy(it), FuzzyFlag.USE_ORE_DICT, true)\n        }\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        setup.requesterPipe.requestItem(ItemStack(Blocks.CHEST), mustSucceed = true)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(listOf(ItemStack(Blocks.CHEST))) },\n        )\n        assertTrue(message = \"a chest item was not found before a timeout\") {\n            waitForChestResult !== null\n        }\n    }\n\n    suspend fun `test split fuzzy ingredients crafting succeeds multi-request with mixed OreDict input`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = regularTest(loggerIn, selector) {\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata),\n                ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.DARK_OAK.metadata),\n            ),\n        )\n        selector.finalize()\n        (0 until 8).forEach {\n            setup.craftingPipe.dummyInventory.setInventorySlotContents(it,\n                ItemStack(Blocks.PLANKS, 1, BlockPlanks.EnumType.OAK.metadata))\n            FuzzyUtil.set(setup.craftingPipe.logisticsModule.inputFuzzy(it), FuzzyFlag.USE_ORE_DICT, true)\n        }\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        val stacks = listOf(ItemStack(Blocks.CHEST))\n        setup.requesterPipe.requestItems(stacks, mustSucceed = true)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(stacks) },\n        )\n        assertTrue(message = \"a chest item was not found before a timeout\") {\n            waitForChestResult !== null\n        }\n        assertTrue(message = \"the provider chest must be empty after providing all planks\") {\n            setup.providerChest.isEmpty\n        }\n    }\n\n    suspend fun `test split fuzzy ingredients crafting succeeds with leftover mixed OreDict input`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = regularTest(loggerIn, selector) {\n        val oakPlanksStack = ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata)\n        val oakPlankItemIdent = ItemIdentifier.get(oakPlanksStack)\n        val darkOakPlanksStack = ItemStack(Blocks.PLANKS, 8, BlockPlanks.EnumType.DARK_OAK.metadata)\n        val darkOakPlankItemIdent = ItemIdentifier.get(darkOakPlanksStack)\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(oakPlanksStack, darkOakPlanksStack),\n        )\n        selector.finalize()\n        (0 until 8).forEach {\n            setup.craftingPipe.dummyInventory.setInventorySlotContents(it,\n                ItemStack(Blocks.PLANKS, 1, BlockPlanks.EnumType.OAK.metadata))\n            FuzzyUtil.set(setup.craftingPipe.logisticsModule.inputFuzzy(it), FuzzyFlag.USE_ORE_DICT, true)\n        }\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        setup.requesterPipe.requestItem(ItemStack(Blocks.CHEST), mustSucceed = true)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(listOf(ItemStack(Blocks.CHEST))) },\n        )\n        assertTrue(message = \"a chest item was not found before a timeout\") {\n            waitForChestResult !== null\n        }\n        val providerPlanksLeft = setup.providerChest.amountOf(listOf(oakPlankItemIdent, darkOakPlankItemIdent))\n        assertEquals(4, providerPlanksLeft, message = \"the provider chest must still contain 4 planks\")\n    }\n\n    suspend fun `test split fuzzy ingredients crafting succeeds multi-request with leftover mixed OreDict input`(\n        loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n    ) = regularTest(loggerIn, selector) {\n        val oakPlanksStack = ItemStack(Blocks.PLANKS, 4, BlockPlanks.EnumType.OAK.metadata)\n        val oakPlankItemIdent = ItemIdentifier.get(oakPlanksStack)\n        val darkOakPlanksStack = ItemStack(Blocks.PLANKS, 8, BlockPlanks.EnumType.DARK_OAK.metadata)\n        val darkOakPlankItemIdent = ItemIdentifier.get(darkOakPlanksStack)\n        val setup = `setup fuzzy crafting chest`(\n            selector = selector,\n            providerStacks = arrayOf(oakPlanksStack, darkOakPlanksStack),\n        )\n        selector.finalize()\n        (0 until 8).forEach {\n            setup.craftingPipe.dummyInventory.setInventorySlotContents(it,\n                ItemStack(Blocks.PLANKS, 1, BlockPlanks.EnumType.OAK.metadata))\n            FuzzyUtil.set(setup.craftingPipe.logisticsModule.inputFuzzy(it), FuzzyFlag.USE_ORE_DICT, true)\n        }\n        delay(5000)\n        setup.requesterPipe.router.update(true, setup.requesterPipe)\n        val stacks = listOf(ItemStack(Blocks.CHEST))\n        setup.requesterPipe.requestItems(stacks, mustSucceed = true)\n        val waitForChestResult = waitForOrNull(\n            timeout = Duration.ofSeconds(3 * TIMEOUT_MODIFIER),\n            check = { setup.requesterChest.containsOnly(stacks) },\n        )\n        assertTrue(message = \"a chest item was not found before a timeout\") {\n            waitForChestResult !== null\n        }\n        val providerPlanksLeft = setup.providerChest.amountOf(listOf(oakPlankItemIdent, darkOakPlankItemIdent))\n        assertEquals(4, providerPlanksLeft, message = \"the provider chest must still contain 4 planks\")\n    }\n\n    private suspend fun `setup fuzzy crafting chest`(\n        selector: BlockPosSelector,\n        providerStacks: Array<ItemStack>,\n        extraCraftingTableConfigurator: LogisticsCraftingTableTileEntity.() -> Unit = {},\n    ): FuzzyCraftingSetup {\n        val fuzzyCraftingTableHasRecipe = CompletableDeferred<Unit>()\n        val fuzzyCraftingTablePlacer = BlockPlacer(block = LPBlocks.crafterFuzzy) { placer ->\n            placer.getTileEntity<LogisticsCraftingTableTileEntity>().apply {\n                (0 until 9).filter { it != 4 }.forEach {\n                    matrix.setInventorySlotContents(it, ItemStack(Blocks.PLANKS))\n                    FuzzyUtil.set(inputFuzzy(it), FuzzyFlag.USE_ORE_DICT, true)\n                }\n                extraCraftingTableConfigurator()\n                cacheRecipe()\n            }\n            fuzzyCraftingTableHasRecipe.complete(Unit)\n        }\n\n        val craftingPipeInitialized = CompletableDeferred<PipeItemsCraftingLogistics>()\n        val craftingPipePlacer = PipePlacer(PipeItemsCraftingLogistics(LPItems.pipeCrafting)) {\n            (it.pipe.upgradeManager as UpgradeManager).inv.apply {\n                setInventorySlotContents(0, ItemStack(fuzzyUpgradeItem))\n                markDirty()\n            }\n            it.waitForPipeInitialization()\n            assertTrue(message = \"Expected crafting pipe to have fuzzy upgrade\") {\n                it.pipe.logisticsModule.hasFuzzyUpgrade()\n            }\n            craftingPipeInitialized.complete(it.pipe)\n            it.updateConnectionsAndWait()\n        }\n\n        return selector.place(fuzzyCraftingTablePlacer)\n            .direction(EnumFacing.NORTH)\n            .place(craftingPipePlacer)\n            .configure(configurator(name = \"crafting recipe importer\") {\n                fuzzyCraftingTableHasRecipe.await()\n                val craftingPipe = craftingPipeInitialized.await()\n                craftingPipe.logisticsModule.importFromCraftingTable(null)\n            })\n            .run {\n                setupLogisticsPower(EnumFacing.EAST, 100000F)\n                val (_, providerChestPlacer) = setupProvidingChest(EnumFacing.WEST, *providerStacks)\n                val (requesterPipePlacer, requesterChestPlacer) = setupRequestingChest(EnumFacing.UP)\n                object : FuzzyCraftingSetup {\n                    override val requesterPipePlacer = requesterPipePlacer\n                    override val requesterChestPlacer = requesterChestPlacer\n                    override val providerChestPlacer = providerChestPlacer\n                    override val craftingPipePlacer = craftingPipePlacer\n                    override val fuzzyCraftingTablePlacer = fuzzyCraftingTablePlacer\n                }\n            }\n    }\n\n    interface FuzzyCraftingSetup {\n        val requesterPipePlacer: PipePlacer<PipeItemsRequestLogistics>\n        val requesterPipe: PipeItemsRequestLogistics\n            get() = requesterPipePlacer.pipe\n        val requesterChestPlacer: BlockPlacer<BlockChest>\n        val requesterChest: TileEntityChest\n            get() = requesterChestPlacer.getTileEntity()\n        val providerChestPlacer: BlockPlacer<BlockChest>\n        val providerChest: TileEntityChest\n            get() = providerChestPlacer.getTileEntity()\n        val craftingPipePlacer: PipePlacer<PipeItemsCraftingLogistics>\n        val craftingPipe: PipeItemsCraftingLogistics\n            get() = craftingPipePlacer.pipe\n        val fuzzyCraftingTablePlacer: BlockPlacer<LogisticsSolidBlock>\n        @Suppress(\"unused\")\n        val fuzzyCraftingTable: LogisticsCraftingTableTileEntity\n            get() = fuzzyCraftingTablePlacer.getTileEntity()\n    }\n\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/integration/LPTestBuilder.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.integration\n\nimport network.rs485.grow.ServerTickDispatcher\nimport network.rs485.minecraft.BlockPlacer\nimport network.rs485.minecraft.BlockPosSelector\nimport logisticspipes.LPBlocks\nimport logisticspipes.LPItems\nimport logisticspipes.blocks.LogisticsSolidBlock\nimport logisticspipes.blocks.powertile.LogisticsPowerJunctionTileEntity\nimport logisticspipes.interfaces.routing.IRequestItems\nimport logisticspipes.pipes.PipeItemsBasicLogistics\nimport logisticspipes.pipes.PipeItemsProviderLogistics\nimport logisticspipes.pipes.PipeItemsRequestLogistics\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.request.RequestLog\nimport logisticspipes.request.RequestTree\nimport logisticspipes.request.resources.IResource\nimport logisticspipes.routing.order.LinkedLogisticsOrderList\nimport logisticspipes.utils.item.ItemIdentifier\nimport logisticspipes.utils.item.ItemIdentifierStack\nimport net.minecraft.block.BlockChest\nimport net.minecraft.init.Blocks\nimport net.minecraft.inventory.IInventory\nimport net.minecraft.item.ItemStack\nimport net.minecraft.tileentity.TileEntityChest\nimport net.minecraft.util.EnumFacing\nimport java.time.Duration\nimport kotlin.test.assertFalse\nimport kotlin.test.assertNotNull\nimport kotlin.test.assertTrue\nimport kotlin.test.fail\nimport kotlinx.coroutines.CompletableDeferred\nimport kotlinx.coroutines.cancelAndJoin\nimport kotlinx.coroutines.time.withTimeoutOrNull\n\nfun BlockPosSelector.setupLogisticsPower(\n    direction: EnumFacing,\n    amount: Float,\n): Pair<PipePlacer<PipeItemsBasicLogistics>, BlockPlacer<LogisticsSolidBlock>> =\n    resetOffsetAfter {\n        val basicPipePlacer = PipePlacer(PipeItemsBasicLogistics(LPItems.pipeBasic))\n            .also { direction(direction).place(it) }\n        val powerJunctionPlacer = BlockPlacer(LPBlocks.powerJunction) {\n            it.getTileEntity<LogisticsPowerJunctionTileEntity>().apply {\n                addEnergy(amount)\n            }\n        }.also { direction(direction).place(it) }\n        basicPipePlacer to powerJunctionPlacer\n    }\n\nfun BlockPosSelector.setupProvidingChest(\n    direction: EnumFacing,\n    vararg stacks: ItemStack,\n): Pair<PipePlacer<PipeItemsProviderLogistics>, BlockPlacer<BlockChest>> =\n    resetOffsetAfter {\n        val providerPlacer = PipePlacer(PipeItemsProviderLogistics(LPItems.pipeProvider))\n            .also { direction(direction).place(it) }\n        val chestPlacer = BlockPlacer(Blocks.CHEST) {\n            it.getTileEntity<TileEntityChest>().apply {\n                stacks.forEachIndexed { index, itemStack -> setInventorySlotContents(index, itemStack) }\n            }\n        }.also { direction(direction).place(it) }\n        providerPlacer to chestPlacer\n    }\n\nfun BlockPosSelector.setupRequestingChest(\n    direction: EnumFacing,\n): Pair<PipePlacer<PipeItemsRequestLogistics>, BlockPlacer<BlockChest>> =\n    resetOffsetAfter {\n        val requesterPlacer = PipePlacer(PipeItemsRequestLogistics(LPItems.pipeRequest))\n            .also { direction(direction).place(it) }\n        val chestPlacer = BlockPlacer(Blocks.CHEST)\n            .also { direction(direction).place(it) }\n        requesterPlacer to chestPlacer\n    }\n\nfun IInventory.containsOnly(stacks: Collection<ItemStack>): Boolean {\n    val stacksLeft = stacks.associateByTo(\n        destination = HashMap(),\n        keySelector = { ItemIdentifier.get(it) },\n        valueTransform = { it.count }\n    )\n    (0 until sizeInventory).map(this::getStackInSlot).filterNot(ItemStack::isEmpty).forEach { stack ->\n        stacksLeft.compute(ItemIdentifier.get(stack)) { _, amount ->\n            assertNotNull(amount, \"unexpected $stack in the inventory\")\n            (amount - stack.count).also {\n                assertFalse(it < 0, \"there are ${-it} items more of ${stack.item} in the inventory than expected\")\n            }.takeIf { it > 0 }\n        }\n    }\n    return stacksLeft.isEmpty()\n}\n\nfun IInventory.amountOf(itemIdents: List<ItemIdentifier>): Int {\n    return (0 until sizeInventory)\n        .asSequence()\n        .map(this::getStackInSlot)\n        .filterNot(ItemStack::isEmpty)\n        .filter { stack ->\n            val stacksItemIdent = ItemIdentifier.get(stack)\n            return@filter itemIdents.any(stacksItemIdent::equals)\n        }\n        .map { stack -> stack.count }\n        .sum()\n}\n\nsuspend fun waitForOrNull(timeout: Duration, check: () -> Boolean): Unit? =\n    CompletableDeferred<Unit>().let { response ->\n        withTimeoutOrNull(timeout) {\n            fun reschedule() {\n                ServerTickDispatcher.scheduleNextTick {\n                    try {\n                        when {\n                            response.isCancelled -> return@scheduleNextTick\n                            check() -> response.complete(Unit)\n                            else -> reschedule()\n                        }\n                    } catch (e: Exception) {\n                        response.completeExceptionally(e)\n                    }\n                }\n            }\n\n            reschedule()\n            response.await()\n        }.also {\n            if (response.isActive) response.cancelAndJoin()\n        }\n    }\n\nsuspend fun waitFor(timeout: Duration, check: () -> Boolean, lazyErrorMessage: () -> Any) =\n    waitForOrNull(timeout, check) ?: error(lazyErrorMessage())\n\n\nclass TestRequestLog(\n    private val requestFinished: CompletableDeferred<Boolean>,\n    private val mustSucceed: Boolean,\n) : RequestLog {\n\n    override fun handleMissingItems(resources: List<IResource>) {\n        if (mustSucceed) {\n            fail(\"Request should have succeeded. Missing items: $resources\")\n        } else {\n            requestFinished.complete(true)\n        }\n    }\n\n    override fun handleSucessfullRequestOf(item: IResource, parts: LinkedLogisticsOrderList) {\n        if (mustSucceed) {\n            requestFinished.complete(true)\n        } else {\n            fail(\"Request should have failed. Requested $item with parts $parts\")\n        }\n    }\n\n    override fun handleSucessfullRequestOfList(\n        resources: List<IResource>,\n        parts: LinkedLogisticsOrderList\n    ) {\n        if (mustSucceed) {\n            requestFinished.complete(true)\n        } else {\n            fail(\"Request should have failed. Requested list $resources with parts $parts\")\n        }\n    }\n}\n\nsuspend fun <T> T.requestItem(\n    stack: ItemStack,\n    mustSucceed: Boolean,\n) where T : CoreRoutedPipe, T : IRequestItems {\n    val requestFinished = CompletableDeferred<Boolean>()\n    RequestTree.request(\n        ItemIdentifierStack.getFromStack(stack),\n        this,\n        TestRequestLog(requestFinished, mustSucceed),\n        false, false, true, false,\n        RequestTree.defaultRequestFlags.clone().apply {\n            add(RequestTree.ActiveRequestType.LogMissing)\n        },\n        null,\n    )\n    val requestAsPlanned = withTimeoutOrNull(Duration.ofSeconds(1 * MinecraftTest.TIMEOUT_MODIFIER)) {\n        requestFinished.await()\n    }\n    assertTrue(message = \"the request did not end up as planned: mustSucceed=$mustSucceed\") {\n        requestAsPlanned == true\n    }\n}\n\nsuspend fun <T> T.requestItems(\n    stacks: List<ItemStack>,\n    mustSucceed: Boolean\n) where T : CoreRoutedPipe, T : IRequestItems {\n    val requestFinished = CompletableDeferred<Boolean>()\n    RequestTree.request(\n        stacks.map { ItemIdentifierStack.getFromStack(it) },\n        this,\n        TestRequestLog(requestFinished, mustSucceed),\n        RequestTree.defaultRequestFlags.clone().apply {\n            add(RequestTree.ActiveRequestType.LogMissing)\n        },\n        null,\n    )\n    val requestAsPlanned = withTimeoutOrNull(Duration.ofSeconds(1 * MinecraftTest.TIMEOUT_MODIFIER)) {\n        requestFinished.await()\n    }\n    assertTrue(message = \"the request did not end up as planned: mustSucceed=$mustSucceed\") {\n        requestAsPlanned == true\n    }\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/integration/MinecraftTest.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.integration\n\nimport network.rs485.grow.Coroutines\nimport network.rs485.minecraft.BlockPosSelector\nimport network.rs485.minecraft.TestState\nimport network.rs485.util.checkBooleanProperty\nimport logisticspipes.LogisticsPipes\nimport net.minecraftforge.fml.common.FMLCommonHandler\nimport net.minecraftforge.fml.common.event.FMLServerStartedEvent\nimport net.minecraft.server.dedicated.DedicatedServer\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.world.WorldServer\nimport java.lang.management.ManagementFactory\nimport java.time.Duration\nimport kotlin.test.assertTrue\nimport kotlinx.coroutines.*\nimport kotlinx.coroutines.time.withTimeout\n\n@Suppress(\"unused\", \"MemberVisibilityCanBePrivate\")\nobject MinecraftTest {\n\n    /**\n     * If not debugging, the server watch dog is not disabled and the server is shut down after running the tests.\n     */\n    private val isDebugging = checkBooleanProperty(\"logisticspipes.test.debug\")\n\n    private lateinit var world: WorldServer\n    private lateinit var firstBlockPos: BlockPos\n    private lateinit var testBlockBuilder: TestWorldBuilder\n\n    const val TIMEOUT_MODIFIER: Long = 1L\n\n    fun serverStart(event: FMLServerStartedEvent) {\n        assertTrue(message = \"Test suite must run on the server\") { event.side.isServer }\n        val serverInstance = FMLCommonHandler.instance().minecraftServerInstance as DedicatedServer\n        world = serverInstance.worlds[0]\n        firstBlockPos = BlockPos(0, LEVEL, 0)\n        if (isDebugging) {\n            serverInstance.setProperty(\"max-tick-time\", 0L)\n            serverInstance.saveProperties()\n            val threadmxbean = ManagementFactory.getThreadMXBean()\n            val athreadinfo = threadmxbean.dumpAllThreads(true, true)\n            val watchdog = athreadinfo.find { it.threadName == \"Server Watchdog\" }\n            if (watchdog != null) error(\"Watchdog already running! Set max-tick-time to 0, please restart the server!\")\n\n            // set rules for spawning players without annoying stuff\n            world.spawnPoint = firstBlockPos\n            world.gameRules.setOrCreateGameRule(\"spawnRadius\", \"0\")\n            world.gameRules.setOrCreateGameRule(\"doDaylightCycle\", \"false\")\n            world.gameRules.setOrCreateGameRule(\"doWeatherCycle\", \"false\")\n            world.worldTime = 5000\n            world.worldInfo.cleanWeatherTime = 15000\n            world.worldInfo.rainTime = 0\n            world.worldInfo.thunderTime = 0\n            world.worldInfo.isRaining = false\n            world.worldInfo.isThundering = false\n        }\n        val task = startTests(LogisticsPipes.log::info)\n        task.invokeOnCompletion {\n            if (it != null) throw it\n            repeat(3) {\n                LogisticsPipes.log.info(\"All Tests done.\")\n            }\n            if (!isDebugging) serverInstance.initiateShutdown()\n        }\n    }\n\n    fun startTests(logger: (Any) -> Unit) =\n        Coroutines.serverScope.launch(CoroutineName(\"logisticspipes.test\")) {\n            delay(Duration.ofSeconds(1 * TIMEOUT_MODIFIER).toMillis())\n            logger(\"[STARTING LOGISTICSPIPES TESTS]\")\n            withTimeout(Duration.ofMinutes(3)) {\n                testBlockBuilder = TestWorldBuilder(world, firstBlockPos)\n                world.spawnPoint = testBlockBuilder.buildSpawnPlatform()\n                listOf(\n                    async {\n                        CraftingTest.`test single fuzzy ingredient crafting fails multi-request with mixed OreDict input`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test single fuzzy ingredient crafting fails with mixed OreDict input`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test single fuzzy ingredient crafting succeeds multi-request with sufficient input of one OreDict type`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test single fuzzy ingredient crafting succeeds with sufficient input of one OreDict type`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test split fuzzy ingredients crafting succeeds multi-request with mixed OreDict input`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test split fuzzy ingredients crafting succeeds with leftover mixed OreDict input`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test split fuzzy ingredients crafting succeeds multi-request with leftover mixed OreDict input`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test single fuzzy ingredient crafting fails with mixed OreDict input on two provider pipes on one double chest`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test single fuzzy ingredient crafting fails with mixed OreDict input on different providers`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                    async {\n                        CraftingTest.`test split fuzzy ingredients crafting succeeds with mixed OreDict input`(\n                            loggerIn = logger,\n                            selector = testBlockBuilder.newSelector(),\n                        )\n                    },\n                ).awaitAll()\n            }\n        }\n\n    suspend inline fun runTest(\n        crossinline loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n        throwable: Throwable = Throwable(),\n        crossinline runnable: suspend () -> Unit,\n        onFail: (logger: (Any) -> Unit, error: Throwable) -> Unit,\n    ) {\n        val testName = throwable.stackTrace[0].methodName\n        val logger = { msg: Any -> loggerIn(\"$testName $msg\") }\n        try {\n            runnable()\n            selector.setVisibleState(TestState.PASSED)\n            logger(\"[PASSED]\")\n        } catch (e: Throwable) {\n            onFail(logger, e)\n        }\n    }\n\n    suspend inline fun skippedTest(\n        crossinline loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n        throwable: Throwable = Throwable(),\n        crossinline runnable: suspend () -> Unit,\n    ) = runTest(loggerIn = loggerIn, selector = selector, throwable = throwable, runnable = runnable) { logger, _ ->\n        selector.setVisibleState(TestState.SKIPPED)\n        logger(\"[SKIPPED]\")\n    }\n\n    suspend inline fun regularTest(\n        crossinline loggerIn: (Any) -> Unit,\n        selector: BlockPosSelector,\n        throwable: Throwable = Throwable(),\n        crossinline runnable: suspend () -> Unit,\n    ) = runTest(loggerIn = loggerIn, selector = selector, throwable = throwable, runnable = runnable) { logger, error ->\n        selector.setVisibleState(TestState.FAILED)\n        logger(\"[FAILED]\\n==> ${error.stackTraceToString()}\")\n    }\n\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/integration/PipePlacer.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\npackage network.rs485.logisticspipes.integration\n\nimport logisticspipes.LPBlocks\nimport logisticspipes.pipes.basic.CoreRoutedPipe\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.world.WorldServer\nimport network.rs485.minecraft.Configurator\nimport network.rs485.minecraft.Placer\nimport network.rs485.minecraft.configurator\nimport java.time.Duration\nimport kotlin.test.assertTrue\n\nclass PipePlacer<T : CoreRoutedPipe>(\n    val pipe: T,\n    private val pipePlacerConfigurator: suspend (PipePlacer<T>) -> Unit = {\n        it.waitForPipeInitialization()\n        it.updateConnectionsAndWait()\n    },\n) : Placer {\n\n    private lateinit var world: WorldServer\n    private lateinit var pos: BlockPos\n    private var placed = false\n\n    override suspend fun place(world: WorldServer, pos: BlockPos): Configurator {\n        placed = true\n        this.pos = pos\n        this.world = world\n        assertTrue(message = \"Expected $pipe to be placed at $pos (${world})\") {\n            LogisticsBlockGenericPipe.placePipe(pipe, world, pos, LPBlocks.pipe)\n        }\n        return configurator(name = \"$pipe at $pos\") { pipePlacerConfigurator(this@PipePlacer) }\n    }\n\n    suspend fun waitForPipeInitialization() {\n        waitFor(\n            timeout = Duration.ofSeconds(1 * MinecraftTest.TIMEOUT_MODIFIER),\n            check = { !pipe.initialInit() },\n            lazyErrorMessage = { \"Timed out waiting for pipe init on $pipe at $pos\" },\n        )\n    }\n\n    suspend fun updateConnectionsAndWait() {\n        pipe.connectionUpdate()\n        val recheckConnections =\n            CoreRoutedPipe::class.java.getDeclaredField(\"recheckConnections\").let {\n                it.isAccessible = true\n                it::getBoolean\n            }\n        waitFor(\n            timeout = Duration.ofSeconds(1 * MinecraftTest.TIMEOUT_MODIFIER),\n            check = { !recheckConnections(pipe) },\n            lazyErrorMessage = { \"Timed out waiting for connection update on $pipe at $pos\" },\n        )\n    }\n\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/integration/TestWorldBuilder.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.integration\n\nimport network.rs485.minecraft.BlockPosSelector\nimport network.rs485.minecraft.WorldBuilder\nimport network.rs485.minecraft.minus\nimport logisticspipes.LogisticsPipes\nimport net.minecraftforge.common.ForgeChunkManager\nimport net.minecraft.block.state.IBlockState\nimport net.minecraft.entity.item.EntityItem\nimport net.minecraft.init.Blocks\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.util.math.ChunkPos\nimport net.minecraft.util.math.Vec3i\nimport net.minecraft.world.WorldServer\nimport kotlin.math.min\n\nconst val LEVEL = 100\nval ONE_VECTOR = Vec3i(1, 1, 1)\n\nclass TestWorldBuilder(override val world: WorldServer, val firstBlockPos: BlockPos) : WorldBuilder {\n\n    private val selectors = ArrayList<Pair<BlockPosSelector, BlockPos>>()\n\n    // TODO: grouping and expanding groups in z needs collecting all selectors/builds before configuration\n    private var nextPos = firstBlockPos\n    private var lowest = LEVEL\n\n    private val tickets: HashSet<ForgeChunkManager.Ticket> = HashSet()\n    private val chunksToLoad: MutableSet<ChunkPos> = HashSet()\n\n    fun newSelector() = BlockPosSelector(worldBuilder = this)\n\n    init {\n        ForgeChunkManager.setForcedChunkLoadingCallback(LogisticsPipes.instance) { ticketsIn, world ->\n            if (world == this@TestWorldBuilder.world) tickets.addAll(ticketsIn!!)\n        }\n        tickets.add(ForgeChunkManager.requestTicket(LogisticsPipes.instance, world, ForgeChunkManager.Type.NORMAL)!!)\n    }\n\n    override fun finalPosition(selector: BlockPosSelector): BlockPos = (nextPos - selector.localStart).also {\n        selectors.add(selector to it)\n        val start = it.add(selector.localStart)\n        val borderStart = start.subtract(ONE_VECTOR)\n        val end = it.add(selector.localEnd)\n        val borderEnd = end.add(ONE_VECTOR)\n        lowest = min(lowest, borderStart.y)\n        nextPos = BlockPos(borderEnd.x + 2, LEVEL, 0)\n        world.setBlocksToAir(start = borderStart, end = borderEnd)\n        world.removeItemsOnGround(start = borderStart, end = borderEnd)\n        world.setBlocks(\n            start = BlockPos(borderStart.x, lowest, borderStart.z),\n            end = BlockPos(borderStart.x, lowest, borderEnd.z),\n            state = Blocks.DOUBLE_STONE_SLAB.defaultState,\n        )\n        world.setBlocks(\n            start = BlockPos(borderStart.x, lowest, borderEnd.z),\n            end = BlockPos(borderEnd.x, lowest, borderEnd.z),\n            state = Blocks.DOUBLE_STONE_SLAB.defaultState,\n        )\n        world.setBlocks(\n            start = BlockPos(borderEnd.x, lowest, borderStart.z),\n            end = BlockPos(borderEnd.x, lowest, borderEnd.z),\n            state = Blocks.DOUBLE_STONE_SLAB.defaultState,\n        )\n        world.setBlocks(\n            start = BlockPos(borderStart.x, lowest, borderStart.z),\n            end = BlockPos(borderEnd.x, lowest, borderStart.z),\n            state = Blocks.DOUBLE_STONE_SLAB.defaultState,\n        )\n        world.setBlocks(\n            start = BlockPos(start.x, lowest, start.z),\n            end = BlockPos(end.x, lowest, end.z),\n            state = Blocks.STONE.defaultState,\n        )\n    }\n\n    override fun loadChunk(pos: ChunkPos) {\n        if (chunksToLoad.add(pos)) ForgeChunkManager.forceChunk(tickets.first(), pos)\n    }\n\n    fun buildSpawnPlatform(): BlockPos {\n        val start = firstBlockPos.subtract(ONE_VECTOR)\n        world.setBlocks(\n            start = BlockPos(start.x - 5, start.y, start.z),\n            end = BlockPos(start.x - 1, start.y, start.z + 4),\n            state = Blocks.OBSIDIAN.defaultState,\n        )\n        return BlockPos(start.x - 3, firstBlockPos.y, start.z + 2)\n    }\n\n}\n\nprivate fun WorldServer.setBlocks(start: BlockPos, end: BlockPos, state: IBlockState) =\n    blocksIn(start, end).forEach { setBlockState(it, state) }\n\nprivate fun WorldServer.setBlocksToAir(start: BlockPos, end: BlockPos) =\n    blocksIn(start, end).forEach(::setBlockToAir)\n\nprivate fun WorldServer.removeItemsOnGround(start: BlockPos, end: BlockPos) =\n    blocksIn(start, end).map { getChunk(it) }.distinct()\n        .forEach { chunk ->\n            chunk.entityLists.flatMap { it.getByClass(EntityItem::class.java) }.forEach { removeEntity(it) }\n        }\n\nprivate fun blocksIn(start: BlockPos, end: BlockPos): List<BlockPos> {\n    assert(start.x <= end.x)\n    assert(start.y <= end.y)\n    assert(start.z <= end.z)\n    return (start.x..end.x).flatMap { x ->\n        (start.y..end.y).flatMap { y ->\n            (start.z..end.z).map { z -> BlockPos(x, y, z) }\n        }\n    }\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/integration/UnroutedPipePlacer.kt",
    "content": "/*\n * Copyright (c) 2023  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2023  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.integration\n\nimport logisticspipes.LPBlocks\nimport logisticspipes.LPItems\nimport logisticspipes.pipes.basic.LogisticsBlockGenericPipe\nimport logisticspipes.pipes.unrouted.PipeItemsBasicTransport\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.world.WorldServer\nimport network.rs485.minecraft.Configurator\nimport network.rs485.minecraft.Placer\nimport network.rs485.minecraft.configurator\nimport kotlin.test.assertTrue\n\nobject UnroutedPipePlacer : Placer {\n\n    override suspend fun place(world: WorldServer, pos: BlockPos): Configurator {\n        val unroutedPipe = PipeItemsBasicTransport(LPItems.pipeUnrouted)\n        assertTrue(message = \"Expected unrouted pipe to be placed at $pos (${world})\") {\n            LogisticsBlockGenericPipe.placePipe(unroutedPipe, world, pos, LPBlocks.pipe)\n        }\n        return configurator { unroutedPipe.updateEntity() }\n    }\n\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/util/LPDataIOWrapperTest.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\nimport io.netty.buffer.Unpooled\nimport net.minecraft.item.ItemStack\nimport net.minecraft.nbt.NBTTagCompound\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.NonNullList\nimport network.rs485.logisticspipes.util.TestUtil.Companion.getBytesFromInteger\nimport network.rs485.util.use\nimport java.util.*\nimport kotlin.test.*\n\nprivate const val BUFFER_EMPTY_MSG = \"Buffer must be empty\"\n\nclass LPDataIOWrapperTest {\n    @Test\n    fun `test reading and writing to direct buffer`() {\n        Unpooled.directBuffer().use { directBuf ->\n            LPDataIOWrapper.writeData(directBuf) { output: LPDataOutput ->\n                output.writeInt(12)\n                output.writeByte(13)\n            }\n            LPDataIOWrapper.provideData(directBuf) { input: LPDataInput ->\n                val firstReadVal = input.readInt()\n                val secondReadVal = input.readByte()\n\n                assertEquals(12, firstReadVal)\n                assertEquals(13, secondReadVal)\n            }\n            val bytesLeft = directBuf.readableBytes()\n            assertEquals(0, bytesLeft, BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test provideData on byte array`() {\n        val result = 16909060\n        LPDataIOWrapper.provideData(getBytesFromInteger(result)) { input: LPDataInput ->\n            val actual = input.readInt()\n\n            assertEquals(result, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test provideData with a ByteBuf`() {\n        val result = 1234\n        Unpooled.wrappedBuffer(getBytesFromInteger(result)).use { dataBuffer ->\n            LPDataIOWrapper.provideData(dataBuffer) { dataInput: LPDataInput -> assertEquals(result, dataInput.readInt()) }\n            val actual = dataBuffer.readableBytes()\n\n            assertEquals(0, actual, BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeData on ByteBuf`() {\n        Unpooled.buffer(Integer.BYTES).use { dataBuffer ->\n            LPDataIOWrapper.writeData(dataBuffer) { dataOutput: LPDataOutput -> dataOutput.writeInt(5) }\n            val actual = dataBuffer.readInt()\n\n            assertEquals(5, actual)\n            assertEquals(0, dataBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test collectData with an integer`() {\n        val value = 7890\n        val expected = getBytesFromInteger(value)\n        val arr = LPDataIOWrapper.collectData { dataOutput: LPDataOutput -> dataOutput.writeInt(value) }\n\n        assertTrue(expected.contentEquals(arr))\n    }\n\n    @Test\n    fun `test writeByteArray to a ByteBuf`() {\n        Unpooled.buffer(Int.SIZE_BYTES * 2).use { dataBuffer ->\n            val arr = getBytesFromInteger(-1)\n            LPDataIOWrapper.writeData(dataBuffer) { dataOutput: LPDataOutput -> dataOutput.writeByteArray(arr) }\n            val firstReadVal = dataBuffer.readInt()\n            val secondReadVal = dataBuffer.readInt()\n\n            assertEquals(4, firstReadVal)\n            assertEquals(-1, secondReadVal)\n\n            val bytesLeft = dataBuffer.readableBytes()\n            assertEquals(0, bytesLeft, BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeByteArray and readByteArray with null`() {\n        Unpooled.buffer().use { dataBuffer ->\n            LPDataIOWrapper.writeData(dataBuffer) { output: LPDataOutput -> output.writeByteArray(null) }\n            LPDataIOWrapper.provideData(dataBuffer) { input: LPDataInput ->\n                val actual = input.readByteArray()\n\n                assertNull(actual)\n            }\n            val bytesLeft = dataBuffer.readableBytes()\n            assertEquals(0, bytesLeft, BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readByteArray with four bytes`() {\n        Unpooled.buffer(Int.SIZE_BYTES * 2).use { dataBuffer ->\n            dataBuffer.writeInt(4)\n            dataBuffer.writeInt(-1)\n            LPDataIOWrapper.provideData(dataBuffer) { dataInput: LPDataInput ->\n                val expected = getBytesFromInteger(-1)\n                val actual = dataInput.readByteArray()!!\n\n                assertTrue(expected.contentEquals(actual))\n            }\n            val bytesLeft = dataBuffer.readableBytes()\n            assertEquals(0, bytesLeft, BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeByte with a single byte`() {\n        val value: Byte = 0x6f\n        Unpooled.buffer(Byte.SIZE_BYTES).use { expected ->\n            expected.writeByte(value.toInt())\n            Unpooled.buffer(Byte.SIZE_BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeByte(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeByte with a byte converted to int`() {\n        val byteValue = 0x6f\n        Unpooled.buffer(Byte.SIZE_BYTES).use { expected ->\n            expected.writeByte(byteValue)\n            Unpooled.buffer(Byte.SIZE_BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeByte(byteValue) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeShort with a single short`() {\n        val value: Short = 0x6f0f\n        Unpooled.buffer(java.lang.Short.BYTES).use { expected ->\n            expected.writeShort(value.toInt())\n            Unpooled.buffer(java.lang.Short.BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeShort(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeShort with a short converted to int`() {\n        val shortValue = 0x6f0f\n        Unpooled.buffer(java.lang.Short.BYTES).use { expected ->\n            expected.writeShort(shortValue)\n            Unpooled.buffer(java.lang.Short.BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeShort(shortValue) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeInt with a single int`() {\n        val value = 0x6f0f9f3f\n        Unpooled.buffer(Int.SIZE_BYTES).use { expected ->\n            expected.writeInt(value)\n            Unpooled.buffer(Int.SIZE_BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeInt(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeLong with a single long`() {\n        val value = 0x6f0f9f3f6f0f9f3fL\n        Unpooled.buffer(Long.SIZE_BYTES).use { expected ->\n            expected.writeLong(value)\n            Unpooled.buffer(Long.SIZE_BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeLong(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeFloat with a single float`() {\n        val value = 0.123456f\n        Unpooled.buffer(java.lang.Float.BYTES).use { expected ->\n            expected.writeFloat(value)\n            Unpooled.buffer(java.lang.Float.BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeFloat(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeDouble with a single double value`() {\n        val value = 0.1234567890123456\n        Unpooled.buffer(java.lang.Double.BYTES).use { expected ->\n            expected.writeDouble(value)\n            Unpooled.buffer(java.lang.Double.BYTES).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeDouble(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeBoolean with a single boolean`() {\n        val value = true\n        Unpooled.buffer(1).use { expected ->\n            expected.writeBoolean(value)\n            Unpooled.buffer(1).use { actual ->\n                LPDataIOWrapper.writeData(actual) { output: LPDataOutput -> output.writeBoolean(value) }\n\n                assertEquals(expected, actual)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeUTF and readUTF with a unicode string`() {\n        val value = \"◘ËTest♀StringßüöäÜÖÄ\"\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeUTF(value) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readUTF()\n\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeUTF and readUTF with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeUTF(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readUTF()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeFacing and readFacing for a single EnumFacing value`() {\n        val value = EnumFacing.UP\n        Unpooled.buffer(Long.SIZE_BYTES).use { testBuffer ->\n            LPDataIOWrapper.writeData(testBuffer) { output: LPDataOutput -> output.writeFacing(value) }\n            LPDataIOWrapper.provideData(testBuffer) { input: LPDataInput ->\n                val actual = input.readFacing()\n\n                assertEquals(value, actual)\n                assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeFacing and readFacing with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeFacing(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readFacing()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeBitSet and readBitSet`() {\n        val value = BitSet(9)\n        value[3] = true\n        value[4] = true\n        value[9] = true\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeBitSet(value) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readBitSet()\n\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeBooleanArray and readBooleanArray`() {\n        val arr = booleanArrayOf(true, false, true, true)\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeBooleanArray(arr) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readBooleanArray()!!\n\n            assertTrue(arr.contentEquals(actual))\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeBooleanArray and readBooleanArray with empty array`() {\n        val arr = BooleanArray(0)\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeBooleanArray(arr) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readBooleanArray()!!\n\n            assertTrue(arr.contentEquals(actual))\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeBooleanArray and readBooleanArray with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeBooleanArray(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readBooleanArray()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readBooleanArray with invalid values`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput ->\n            output.writeInt(12)\n            output.writeByteArray(null)\n        }\n\n        assertFailsWith<NullPointerException> {\n            LPDataIOWrapper.provideData(data) { obj: LPDataInput -> obj.readBooleanArray() }\n        }\n    }\n\n    @Test\n    fun `test writeIntArray and readIntArray`() {\n        val arr = intArrayOf(12, 13, 13513, Int.MAX_VALUE, Int.MIN_VALUE)\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeIntArray(arr) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readIntArray()!!\n\n            assertTrue(arr.contentEquals(actual))\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeIntArray and readIntArray with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeIntArray(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readIntArray()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writing and reading bytes via ByteBuf`() {\n        val arr = getBytesFromInteger(741893247)\n        Unpooled.buffer(arr.size).use { testBuffer ->\n            LPDataIOWrapper.writeData(testBuffer) { output: LPDataOutput -> output.writeBytes(arr) }\n\n            // buffer in byte array\n            val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeByteBuf(testBuffer) }\n            LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n                LPDataIOWrapper.provideData(input.readByteBuf()) { bufferInput: LPDataInput ->\n                    val actual = bufferInput.readBytes(arr.size)\n\n                    assertTrue(arr.contentEquals(actual))\n                    assertEquals(0, (bufferInput as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n                }\n                assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n            }\n        }\n    }\n\n    @Test\n    fun `test writeByteBuf with null`() {\n        assertFailsWith<NullPointerException> {\n            LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeByteBuf(null) }\n        }\n    }\n\n    @Test\n    fun `test readByteBuf with invalid values`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeByteArray(null) }\n        assertFailsWith<NullPointerException> {\n            LPDataIOWrapper.provideData(data) { obj: LPDataInput -> obj.readByteBuf() }\n        }\n    }\n\n    @Test\n    fun `test writeLongArray and readLongArray`() {\n        val arr = longArrayOf(12L, 13L, 1351312398172398L, Long.MAX_VALUE, Long.MIN_VALUE)\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeLongArray(arr) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readLongArray()!!\n\n            assertTrue(arr.contentEquals(actual))\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeLongArray and readLongArray with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeLongArray(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readLongArray()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readShort with regular value`() {\n        val value: Short = 12\n        val dataBuffer = Unpooled.buffer(java.lang.Short.BYTES)\n        dataBuffer.writeShort(value.toInt())\n        LPDataIOWrapper.provideData(dataBuffer) { input: LPDataInput ->\n            val actual = input.readShort()\n\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readLong with regular value`() {\n        val value = 1092347801374L\n        val dataBuffer = Unpooled.buffer(Long.SIZE_BYTES)\n        dataBuffer.writeLong(value)\n        LPDataIOWrapper.provideData(dataBuffer) { input: LPDataInput ->\n            val actual = input.readLong()\n\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readFloat with regular value`() {\n        val value = 0.123456f\n        val dataBuffer = Unpooled.buffer(java.lang.Float.BYTES)\n        dataBuffer.writeFloat(value)\n        LPDataIOWrapper.provideData(dataBuffer) { input: LPDataInput ->\n            val actual = input.readFloat()\n\n            // compares floating point numbers correctly in Kotlin\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readDouble with regular value`() {\n        val value = 0.1234567890123456\n        val dataBuffer = Unpooled.buffer(java.lang.Double.BYTES)\n        dataBuffer.writeDouble(value)\n        LPDataIOWrapper.provideData(dataBuffer) { input: LPDataInput ->\n            val actual = input.readDouble()\n\n            // compares floating point numbers correctly in Kotlin\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readBoolean with regular value`() {\n        val value = true\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeBoolean(value) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readBoolean()\n\n            assertEquals(value, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeNBTTagCompound and readNBTTagCompound with plenty information`() {\n        val tag = NBTTagCompound()\n        tag.setBoolean(\"bool\", true)\n        tag.setByte(\"byte\", 127.toByte())\n        tag.setByteArray(\"byteArray\", byteArrayOf(-1, 127, 0, 12))\n        tag.setDouble(\"double\", 0.12)\n        tag.setFloat(\"float\", 0.13f)\n        tag.setIntArray(\"intArray\", intArrayOf(Int.MIN_VALUE, 0, Int.MAX_VALUE, -1))\n        tag.setInteger(\"int\", 12)\n        tag.setLong(\"long\", -1)\n        tag.setShort(\"short\", 15.toShort())\n        tag.setString(\"string\", \"text\")\n        tag.setTag(\"tag\", NBTTagCompound())\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeNBTTagCompound(tag) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readNBTTagCompound()\n\n            assertEquals(tag, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeNBTTagCompound and readNBTTagCompound with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeNBTTagCompound(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readNBTTagCompound()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test readItemStack with EMPTY value`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeItemStack(ItemStack.EMPTY) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readItemStack()\n\n            assertEquals(ItemStack.EMPTY, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readArrayList with UTF strings`() {\n        val arr = arrayListOf(\"drölf\", \"text\")\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection(arr) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readArrayList<String> { obj: LPDataInput -> obj.readUTF() }\n\n            assertEquals(arr, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readArrayList with null UTF string`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection<String>(null) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readArrayList { obj: LPDataInput -> obj.readUTF() }\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readLinkedList with UTF strings`() {\n        val linkedList = LinkedList<String>()\n        linkedList.add(\"drölf\")\n        linkedList.add(\"text\")\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection(linkedList) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readLinkedList<String> { obj: LPDataInput -> obj.readUTF() }\n\n            assertEquals(linkedList, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readLinkedList with UTF null value`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection<String>(null) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readLinkedList { obj: LPDataInput -> obj.readUTF() }\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readSet with UTF strings`() {\n        val expected = setOf(\"drölf\", \"text\")\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection(expected) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readSet { obj: LPDataInput -> obj.readUTF() }\n\n            assertEquals(expected, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readSet with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput ->\n            output.writeCollection<String>(null) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) }\n        }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readSet { obj: LPDataInput -> obj.readUTF() }\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readNonNullList with UTF strings`() {\n        val expected = NonNullList.withSize(3, \"\")\n        expected[0] = \"drölf\"\n        expected[1] = \"text\"\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection(expected) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readNonNullList({ obj: LPDataInput -> obj.readUTF() }, \"\")\n\n            assertEquals(expected, actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeCollection and readNonNullList with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeCollection<String>(null) { obj: LPDataOutput, s: String? -> obj.writeUTF(s) } }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readNonNullList({ obj: LPDataInput -> obj.readUTF() }, \"\")\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeUTFArray and readUTFArray`() {\n        val arr = arrayOf(\"◘ËTest♀StringßüöäÜÖÄ\", \"◘ËTest♀TESTpartßüöäÜÖÄ\")\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeUTFArray(arr) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readUTFArray()!!\n\n            assertTrue(arr.contentEquals(actual))\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeUTFArray and readUTFArray with null`() {\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeUTFArray(null) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readUTFArray()\n\n            assertNull(actual)\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n\n    @Test\n    fun `test writeUTFArray and readUTFArray with null value`() {\n        val array = arrayOf(\"◘ËTest♀StringßüöäÜÖÄ\", null)\n        val data = LPDataIOWrapper.collectData { output: LPDataOutput -> output.writeUTFArray(array) }\n        LPDataIOWrapper.provideData(data) { input: LPDataInput ->\n            val actual = input.readUTFArray()!!\n\n            assertTrue(array.contentEquals(actual))\n            assertEquals(0, (input as LPDataIOWrapper).localBuffer.readableBytes(), BUFFER_EMPTY_MSG)\n        }\n    }\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/logisticspipes/util/TestUtil.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.logisticspipes.util\n\nimport net.minecraft.util.text.TextFormatting\nimport java.util.*\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\nimport kotlin.test.assertTrue\n\nclass TestUtil {\n    companion object {\n        @JvmStatic\n        fun getBytesFromInteger(i: Int): ByteArray = byteArrayOf(i.ushr(24).toByte(), i.ushr(16).toByte(), i.ushr(8).toByte(), i.toByte())\n    }\n\n    @Test\n    fun `test getBytesFromInteger for 0`() {\n        assertTrue(byteArrayOf(0, 0, 0, 0).contentEquals(getBytesFromInteger(0)))\n    }\n\n    @Test\n    fun `test getBytesFromInteger for byte array (1, 2, 3, 4)`() {\n        assertTrue(byteArrayOf(1, 2, 3, 4).contentEquals(getBytesFromInteger(16909060)))\n    }\n\n    @Test\n    fun `test getBytesFromInteger for min integer`() {\n        assertTrue(byteArrayOf(-128, 0, 0, 0).contentEquals(getBytesFromInteger(Int.MIN_VALUE)))\n    }\n\n    @Test\n    fun `test getBytesFromInteger for max integer`() {\n        assertTrue(byteArrayOf(127, -1, -1, -1).contentEquals(getBytesFromInteger(Int.MAX_VALUE)))\n    }\n\n    @Test\n    fun `test getBytesFromInteger for -1`() {\n        assertTrue(byteArrayOf(-1, -1, -1, -1).contentEquals(getBytesFromInteger(-1)))\n    }\n\n    @Test\n    fun `test transform with starting formatting`() {\n        assertEquals(\"§7§oThis is a semi §c§oformatted§r§7§o string.\", TextUtil.transform(text = \"This is a semi \\$REDformatted\\$RESET string.\", baseFormatting = EnumSet.of(TextFormatting.GRAY, TextFormatting.ITALIC)))\n    }\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/markdown/MarkdownParserTest.kt",
    "content": "/*\n * Copyright (c) 2020  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2020  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.markdown\n\nimport network.rs485.markdown.MarkdownParser.parseParagraphs\nimport network.rs485.markdown.MarkdownParser.splitAndFormatWords\nimport network.rs485.markdown.MarkdownParser.splitSpacesAndWords\nimport network.rs485.markdown.MarkdownParser.splitWhitespaceCharactersAndWords\nimport java.util.*\nimport kotlin.test.Ignore\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\ninternal class MarkdownParserTest {\n\n    @Test\n    fun `default text case in splitToInlineElements`() {\n        val str = \"Split this please\"\n        val splitElements = splitAndFormatWords(str)\n\n        assertEquals(listOf(Word(\"Split\"), Space, Word(\"this\"), Space, Word(\"please\")), splitElements)\n    }\n\n    @Test\n    fun `empty string in splitToInlineElements`() {\n        val str = \"\"\n        val splitElements = splitWhitespaceCharactersAndWords(str)\n\n        assertEquals(emptyList(), splitElements)\n    }\n\n    @Test\n    fun `too many spaces in splitToInlineElements`() {\n        val str = \"  two text    nodes   \"\n        val splitElements = splitAndFormatWords(str)\n\n        assertEquals(listOf(Word(\"two\"), Space, Word(\"text\"), Space, Word(\"nodes\")), splitElements)\n    }\n\n    @Test\n    fun `single word in splitToInlineElements`() {\n        val str = \"word\"\n        val splitElements = splitAndFormatWords(str)\n\n        assertEquals(listOf(Word(str)), splitElements)\n    }\n\n    @Test\n    fun `special line break in splitToInlineElements`() {\n        val firstStr = \"one\"\n        val secondStr = \"paragraph\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"$firstStr\\n$secondStr\")\n\n        assertEquals(listOf(Word(firstStr), Break, Word(secondStr)), splitElements)\n    }\n\n    @Test\n    fun `special line break after word in splitToInlineElements`() {\n        val str = \"word\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"$str\\n\")\n\n        assertEquals(listOf(Word(str), Break), splitElements)\n    }\n\n    @Test\n    fun `special line break before word in splitToInlineElements`() {\n        val str = \"weird\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"\\n$str\")\n\n        assertEquals(listOf(Break, Word(str)), splitElements)\n    }\n\n    @Test\n    fun `special line break and spaces in splitToInlineElements`() {\n        val str = \"weird\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"  \\n $str\")\n\n        assertEquals(listOf(Break, Word(str)), splitElements)\n    }\n\n    @Test\n    fun `html line break in splitToInlineElements`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"$firstStr<br>$secondStr\")\n\n        assertEquals(listOf(Word(firstStr), Break, Word(secondStr)), splitElements)\n    }\n\n    @Test\n    fun `xhtml line break in splitToInlineElements`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"$firstStr<br/>$secondStr\")\n\n        assertEquals(listOf(Word(firstStr), Break, Word(secondStr)), splitElements)\n    }\n\n    @Test\n    fun `xhtml line break with one space in splitToInlineElements`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"$firstStr<br />$secondStr\")\n\n        assertEquals(listOf(Word(firstStr), Break, Word(secondStr)), splitElements)\n    }\n\n    @Test\n    fun `xhtml line break with multiple space in splitToInlineElements`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val splitElements = splitWhitespaceCharactersAndWords(\"$firstStr<br   />$secondStr\")\n\n        assertEquals(listOf(Word(firstStr), Break, Word(secondStr)), splitElements)\n    }\n\n    @Test\n    fun `parse simple text in parseParagraphs`() {\n        val str = \"Just some text\"\n        val paragraphs = parseParagraphs(str)\n\n        assertEquals(listOf(RegularParagraph(splitAndFormatWords(str))), paragraphs)\n    }\n\n    @Test\n    fun `parse empty text in parseParagraphs`() {\n        val paragraphs = parseParagraphs(\"\")\n\n        assertEquals(emptyList(), paragraphs)\n    }\n\n    @Test\n    fun `parse two regular paragraphs with text in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n\\n$secondStr\")\n\n        assertEquals(listOf(RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)), RegularParagraph(splitWhitespaceCharactersAndWords(secondStr))), paragraphs)\n    }\n\n    @Test\n    fun `parse html line break in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr<br>$secondStr\")\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(firstStr), Break, Word(secondStr)))), paragraphs)\n    }\n\n    @Test\n    fun `parse xhtml line break in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr<br />$secondStr\")\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(firstStr), Break, Word(secondStr)))), paragraphs)\n    }\n\n    @Test\n    fun `special line break with two spaces in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr  \\n$secondStr\")\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(firstStr), Break, Word(secondStr)))), paragraphs)\n    }\n\n    @Test\n    fun `special line break with too many spaces in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr     \\n $secondStr\")\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(firstStr), Break, Word(secondStr)))), paragraphs)\n    }\n\n    @Test\n    fun `line break with one space in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr \\n$secondStr\")\n\n        assertEquals(listOf(RegularParagraph(splitWhitespaceCharactersAndWords(\"$firstStr $secondStr\"))), paragraphs)\n    }\n\n    @Test\n    fun `escaped line break in parseParagraphs`() {\n        val firstStr = \"Split\"\n        val secondStr = \"text\"\n        val paragraphs = parseParagraphs(\"$firstStr\\\\\\n$secondStr\")\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(\"$firstStr$secondStr\")))), paragraphs)\n    }\n\n    @Test\n    fun `escaped line break and no content in parseParagraphs`() {\n        val paragraphs = parseParagraphs(\"\\\\\\n\")\n\n        assertEquals(emptyList(), paragraphs)\n    }\n\n    @Test\n    fun `parse simple header in parseParagraphs`() {\n        val headerStr = \"I am header!\"\n        val paragraphs = parseParagraphs(\"# $headerStr\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1)), paragraphs)\n    }\n\n    @Test\n    fun `parse non-header in parseParagraphs`() {\n        val noHeaderStr = \"#I ain't no header!\"\n        val paragraphs = parseParagraphs(noHeaderStr)\n\n        assertEquals(listOf(RegularParagraph(splitWhitespaceCharactersAndWords(noHeaderStr))), paragraphs)\n    }\n\n    @Test\n    fun `parse header with spaces in parseParagraphs`() {\n        val headerStr = \"I am header!\"\n        val paragraphs = parseParagraphs(\"  #  $headerStr\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1)), paragraphs)\n    }\n\n    @Test\n    fun `parse level two header in parseParagraphs`() {\n        val headerStr = \"I am header lvl 2!\"\n        val paragraphs = parseParagraphs(\"## $headerStr\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 2)), paragraphs)\n    }\n\n    @Test\n    fun `parse level six header in parseParagraphs`() {\n        val headerStr = \"I am header lvl 6!\"\n        val paragraphs = parseParagraphs(\"###### $headerStr\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 6)), paragraphs)\n    }\n\n    @Test\n    fun `parse level seven header in parseParagraphs`() {\n        val headerStr = \"I am also header lvl 6!\"\n        val paragraphs = parseParagraphs(\"####### $headerStr\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 6)), paragraphs)\n    }\n\n    @Test\n    fun `parse uber level header in parseParagraphs`() {\n        val headerStr = \"I am also header lvl 6!\"\n        val paragraphs = parseParagraphs(\"############## $headerStr\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 6)), paragraphs)\n    }\n\n    @Test\n    fun `escaped line break for simple header in parseParagraphs`() {\n        val firstStr = \"Multiline\"\n        val secondStr = \"Header\"\n        val paragraphs = parseParagraphs(\"# $firstStr \\\\\\n$secondStr\")\n\n        assertEquals(listOf(HeaderParagraph(listOf(Word(firstStr), Space, Word(secondStr)), 1)), paragraphs)\n    }\n\n    @Test\n    fun `parse text paragraph before header in parseParagraphs`() {\n        val textStr = \"Before!\"\n        val headerStr = \"Header!\"\n        val paragraphs = parseParagraphs(\n                \"$textStr\\n\" +\n                        \"\\n\" +\n                        \"# $headerStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(textStr)),\n                HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1)\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse text paragraph after header in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val textStr = \"After!\"\n        val paragraphs = parseParagraphs(\n                \"# $headerStr\\n\" +\n                        \"\\n\" +\n                        textStr)\n\n        val expectedParagraphs = listOf(\n                HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1),\n                RegularParagraph(splitWhitespaceCharactersAndWords(textStr))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse text paragraph before and after header in parseParagraphs`() {\n        val firstStr = \"Before!\"\n        val headerStr = \"Header!\"\n        val secondStr = \"After!\"\n        val paragraphs = parseParagraphs(\n                \"$firstStr\\n\" +\n                        \"\\n\" +\n                        \"# $headerStr\\n\" +\n                        \"\\n\" +\n                        secondStr)\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1),\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse text without extra newlines before and after header in parseParagraphs`() {\n        val firstStr = \"Before!\"\n        val headerStr = \"Header!\"\n        val secondStr = \"After!\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n ## $headerStr\\n $secondStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 2),\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse first level underscored header in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val paragraphs = parseParagraphs(\"$headerStr\\n===\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1)), paragraphs)\n    }\n\n    @Test\n    fun `parse first level uber underscored header in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val paragraphs = parseParagraphs(\"$headerStr\\n=============================\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1)), paragraphs)\n    }\n\n    @Test\n    fun `dont parse first level underscored header in parseParagraphs`() {\n        val str = \"Not a header\"\n        val noHeaderStr = \"$str\\n==\"\n        val paragraphs = parseParagraphs(noHeaderStr)\n\n        assertEquals(listOf(RegularParagraph(splitWhitespaceCharactersAndWords(\"$str ==\"))), paragraphs)\n    }\n\n    @Test\n    fun `parse first level underscored header and then text in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val textStr = \"Hello..\"\n        val paragraphs = parseParagraphs(\"$headerStr\\n=======\\n$textStr\")\n\n        val expectedParagraphs = listOf(\n                HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 1),\n                RegularParagraph(splitWhitespaceCharactersAndWords(textStr))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse second level underscored header in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val paragraphs = parseParagraphs(\"$headerStr\\n---\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 2)), paragraphs)\n    }\n\n    @Test\n    fun `parse second level uber underscored header in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val paragraphs = parseParagraphs(\"$headerStr\\n----------------------------------\")\n\n        assertEquals(listOf(HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 2)), paragraphs)\n    }\n\n    @Test\n    fun `dont parse second level underscored header in parseParagraphs`() {\n        val str = \"Not a header\"\n        val noHeaderStr = \"$str\\n--\"\n        val paragraphs = parseParagraphs(noHeaderStr)\n\n        assertEquals(listOf(RegularParagraph(splitWhitespaceCharactersAndWords(\"$str --\"))), paragraphs)\n    }\n\n    @Test\n    fun `parse second level underscored header and then text in parseParagraphs`() {\n        val headerStr = \"Header!\"\n        val textStr = \"Hello..\"\n        val paragraphs = parseParagraphs(\"$headerStr\\n-------\\n$textStr\")\n\n        val expectedParagraphs = listOf(\n                HeaderParagraph(splitWhitespaceCharactersAndWords(headerStr), 2),\n                RegularParagraph(splitWhitespaceCharactersAndWords(textStr))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse double horizontal line in parseParagraphs`() {\n        val str = \"===\"\n        val paragraphs = parseParagraphs(str)\n\n        assertEquals(listOf(HorizontalLineParagraph), paragraphs)\n    }\n\n    @Test\n    fun `dont parse double horizontal line in parseParagraphs`() {\n        val str = \"==\"\n        val paragraphs = parseParagraphs(str)\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(str)))), paragraphs)\n    }\n\n    @Test\n    fun `parse single horizontal line in parseParagraphs`() {\n        val str = \"---\"\n        val paragraphs = parseParagraphs(str)\n\n        assertEquals(listOf(HorizontalLineParagraph), paragraphs)\n    }\n\n    @Test\n    fun `dont parse single horizontal line in parseParagraphs`() {\n        val str = \"--\"\n        val paragraphs = parseParagraphs(str)\n\n        assertEquals(listOf(RegularParagraph(listOf(Word(str)))), paragraphs)\n    }\n\n    @Test\n    fun `parse double horizontal line with text around in parseParagraphs`() {\n        val firstStr = \"Hello\"\n        val secondStr = \"World!\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n\\n===\\n\\n$secondStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                HorizontalLineParagraph,\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr)))\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse double horizontal line with text around and less newlines in parseParagraphs`() {\n        val firstStr = \"Hello\"\n        val secondStr = \"World!\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n\\n===\\n$secondStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                HorizontalLineParagraph,\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr)))\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse single horizontal line with text around in parseParagraphs`() {\n        val firstStr = \"Hello\"\n        val secondStr = \"World!\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n\\n---\\n\\n$secondStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                HorizontalLineParagraph,\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr)))\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse single horizontal line with text around and less newlines in parseParagraphs`() {\n        val firstStr = \"Hello\"\n        val secondStr = \"World!\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n\\n---\\n$secondStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                HorizontalLineParagraph,\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr)))\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `dont parse single horizontal line with text around in parseParagraphs`() {\n        val firstStr = \"Hello\"\n        val secondStr = \"World!\"\n        val paragraphs = parseParagraphs(\"$firstStr\\n\\n--\\n\\n$secondStr\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitWhitespaceCharactersAndWords(firstStr)),\n                RegularParagraph(listOf(Word(\"--\"))),\n                RegularParagraph(splitWhitespaceCharactersAndWords(secondStr)))\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse a simple tile menu tag`() {\n        val text = \"Main Menu\"\n        val link = \"main_menu\"\n        val paragraphs = parseParagraphs(\"[$text](menu://$link?type=tile)\")\n\n        val expectedParagraphs = listOf(\n            MenuParagraph(text, link, MenuParagraphType.TILE)\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse a simple list menu tag`() {\n        val text = \"Main Menu\"\n        val link = \"main_menu\"\n        val paragraphs = parseParagraphs(\"[$text](menu://$link?type=list)\")\n\n        val expectedParagraphs = listOf(\n            MenuParagraph(text, link, MenuParagraphType.LIST)\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse a list menu tag as default`() {\n        val text = \"Main Menu\"\n        val link = \"main_menu\"\n        val paragraphs = parseParagraphs(\"[$text](menu://$link)\")\n\n        val expectedParagraphs = listOf(\n            MenuParagraph(text, link, MenuParagraphType.LIST)\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse an incomplete menu tag`() {\n        val str = \"[Menu(menu://main_menu)\"\n        val paragraphs = parseParagraphs(str)\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(listOf(Word(str)))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse an invalid combination of menu tags`() {\n        val test1 = \"[Test1](menu://test_menu_1)\"\n        val test2 = \"[Test2](menu://test_menu_2)\"\n        val paragraphs = parseParagraphs(\"$test1 $test2\")\n\n        val expectedParagraphs = listOf(\n                RegularParagraph(splitAndFormatWords(\"$test1 $test2\"))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse a couple of menu tags`() {\n        val expectedParagraphs = (1..5).map { n -> MenuParagraph(\"Test $n\", \"test_menu_$n\", MenuParagraphType.LIST) }.toList()\n        val str = expectedParagraphs.joinToString(separator = \"\\n\") { \"[${it.description}](menu://${it.link})\" }\n\n        val paragraphs = parseParagraphs(str)\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse menu tag with blank appendix`() {\n        val menuText = \"Menu\"\n        val menuReference = \"theMenu\"\n        val word = \"Well\"\n        val str = \"[$menuText](menu://$menuReference?type=tile)  \\n$word\"\n        val paragraphs = parseParagraphs(str)\n\n        val expectedParagraphs = listOf(\n            MenuParagraph(menuText, menuReference, MenuParagraphType.TILE),\n            RegularParagraph(listOf(Word(word)))\n        )\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse a correct ImageParagraph`() {\n        val alt = \"Alternative Text\"\n        val link = \"logisticspipes:itemcard\"\n        val str = \"![$alt](image://$link)\"\n        val paragraphs = parseParagraphs(str)\n\n        val expectedParagraphs = listOf(\n            ImageParagraph(alternative = alt, imagePath = link)\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse an incorrect ImageParagraph`() {\n        val str = \"[Alternative Text](image://logisticspipes:itemcard)\"\n        val paragraphs = parseParagraphs(str)\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(splitWhitespaceCharactersAndWords(str))\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `try to parse an incorrect inline image link`() {\n        val str = \"this is not ![Alternative Text](image://logisticspipes:itemcard) working\"\n        val paragraphs = parseParagraphs(str)\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(splitWhitespaceCharactersAndWords(str))\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse an inline page link`() {\n        val linkText = \"page link\"\n        val pageLink = \"yay i am at work\"\n        val str1 = \"this is a\"\n        val str2 = \"at work\"\n        val paragraphs = parseParagraphs(\"$str1 [$linkText](page://$pageLink) $str2\")\n        val linkObject = PageLink(pageLink)\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    splitWhitespaceCharactersAndWords(str1),\n                    listOf(Space, LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), LinkFormatting(null), Space),\n                    splitWhitespaceCharactersAndWords(str2),\n                ).flatten()\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse two page links`() {\n        val link1Text = \"page link 1\"\n        val link2Text = \"page link 2\"\n        val pageLink = \"yay i am at work\"\n        val str1 = \"this is a\"\n        val str2 = \"at work\"\n        val paragraphs = parseParagraphs(\"$str1 [$link1Text](page://$pageLink) [$link2Text](page://$pageLink) $str2\")\n        val linkObject = PageLink(pageLink)\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    splitWhitespaceCharactersAndWords(str1),\n                    listOf(Space),\n                    listOf(LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), Space, Word(\"1\"), LinkFormatting(null)),\n                    listOf(Space),\n                    listOf(LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), Space, Word(\"2\"), LinkFormatting(null)),\n                    listOf(Space),\n                    splitWhitespaceCharactersAndWords(str2),\n                ).flatten()\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse two page links (no spacing)`() {\n        val link1Text = \"page link 1\"\n        val link2Text = \"page link 2\"\n        val pageLink = \"yay i am at work\"\n        val paragraphs = parseParagraphs(\"[$link1Text](page://$pageLink)[$link2Text](page://$pageLink)\")\n        val linkObject = PageLink(pageLink)\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    listOf(LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), Space, Word(\"1\"), LinkFormatting(null)),\n                    listOf(LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), Space, Word(\"2\"), LinkFormatting(null)),\n                ).flatten()\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse two page links (double space)`() {\n        val link1Text = \"page link 1\"\n        val link2Text = \"page link 2\"\n        val pageLink = \"yay i am at work\"\n        val str1 = \"this is a\"\n        val str2 = \"at work\"\n        val paragraphs = parseParagraphs(\"$str1 [$link1Text](page://$pageLink)  [$link2Text](page://$pageLink) $str2\")\n        val linkObject = PageLink(pageLink)\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    splitWhitespaceCharactersAndWords(str1),\n                    listOf(Space),\n                    listOf(LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), Space, Word(\"1\"), LinkFormatting(null)),\n                    listOf(Space),\n                    listOf(LinkFormatting(linkObject), Word(\"page\"), Space, Word(\"link\"), Space, Word(\"2\"), LinkFormatting(null)),\n                    listOf(Space),\n                    splitWhitespaceCharactersAndWords(str2),\n                ).flatten()\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse https web link`() {\n        val url = \"https://example.com\"\n        val linkText = \"My Link\"\n        val paragraphs = parseParagraphs(\"[$linkText]($url)\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(LinkFormatting(WebLink(url = url)))\n                    .plus(splitSpacesAndWords(linkText))\n                    .plus(LinkFormatting(null))\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse http web link`() {\n        val url = \"http://example.com\"\n        val linkText = \"My Link\"\n        val paragraphs = parseParagraphs(\"[$linkText]($url)\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(LinkFormatting(WebLink(url = url)))\n                    .plus(splitSpacesAndWords(linkText))\n                    .plus(LinkFormatting(null))\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse web link in header`() {\n        val url = \"https://example.com\"\n        val linkText = \"My Link\"\n        val paragraphs = parseParagraphs(\"# [$linkText]($url)\")\n\n        val expectedParagraphs = listOf(\n            HeaderParagraph(\n                listOf(LinkFormatting(WebLink(url = url)))\n                    .plus(splitSpacesAndWords(linkText))\n                    .plus(LinkFormatting(null)),\n                headerLevel = 1,\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse single italic formatting`() {\n        val str = \"a word\"\n        val paragraphs = parseParagraphs(\"*$str*\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    listOf(TextFormatting(EnumSet.of(TextFormat.Italic))),\n                    splitAndFormatWords(str),\n                    listOf(TextFormatting(TextFormat.none)),\n                ).flatten()\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse simple nested formatting`() {\n        val paragraphs = parseParagraphs(\"*a___b___*\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"a\"),\n                    TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Bold)),\n                    Word(\"b\"),\n                    TextFormatting(TextFormat.none),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse simple nested formatting 2`() {\n        val paragraphs = parseParagraphs(\"**a_b_**\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Word(\"a\"),\n                    TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Bold)),\n                    Word(\"b\"),\n                    TextFormatting(TextFormat.none),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse advanced nested formatting`() {\n        val paragraphs = parseParagraphs(\"*a__b__c*\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"a\"),\n                    TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Bold)),\n                    Word(\"b\"),\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"c\"),\n                    TextFormatting(TextFormat.none),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse unnecessary format enhancements`() {\n        val paragraphs = parseParagraphs(\"__a***b***c__\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Word(\"a\"),\n                    TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Bold)),\n                    Word(\"b\"),\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Word(\"c\"),\n                    TextFormatting(TextFormat.none),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse overlapping format enhancements`() {\n        val paragraphs = parseParagraphs(\"This _is **weirdly_ abnormal** markdown\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    Word(\"This\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"is\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Bold)),\n                    Word(\"weirdly\"),\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Space,\n                    Word(\"abnormal\"),\n                    TextFormatting(TextFormat.none),\n                    Space,\n                    Word(\"markdown\"),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse overlapping format enhancements 2`() {\n        val paragraphs = parseParagraphs(\"This __is *weirdly__ abnormal* markdown\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    Word(\"This\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Word(\"is\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Italic, TextFormat.Bold)),\n                    Word(\"weirdly\"),\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Space,\n                    Word(\"abnormal\"),\n                    TextFormatting(TextFormat.none),\n                    Space,\n                    Word(\"markdown\"),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse simple formatted string`() {\n        val paragraphs = parseParagraphs(\"This _is_ example **Markdown**. This ***should*** work.\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    Word(\"This\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"is\"),\n                    TextFormatting(TextFormat.none),\n                    Space,\n                    Word(\"example\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Word(\"Markdown\"),\n                    TextFormatting(TextFormat.none),\n                    Word(\".\"),\n                    Space,\n                    Word(\"This\"),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Bold, TextFormat.Italic)),\n                    Word(\"should\"),\n                    TextFormatting(TextFormat.none),\n                    Space,\n                    Word(\"work.\"),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse formatted text next to each other`() {\n        val paragraphs = parseParagraphs(\"*a* __b__\")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"a\"),\n                    TextFormatting(TextFormat.none),\n                    Space,\n                    TextFormatting(EnumSet.of(TextFormat.Bold)),\n                    Word(\"b\"),\n                    TextFormatting(TextFormat.none),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n    @Test\n    fun `parse formatting with spaces to trim`() {\n        val paragraphs = parseParagraphs(\" * a * \")\n\n        val expectedParagraphs = listOf(\n            RegularParagraph(\n                listOf(\n                    TextFormatting(EnumSet.of(TextFormat.Italic)),\n                    Word(\"a\"),\n                    TextFormatting(TextFormat.none),\n                )\n            )\n        )\n\n        assertEquals(expectedParagraphs, paragraphs)\n    }\n\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/minecraft/BlockPlacer.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.minecraft\n\nimport net.minecraft.block.Block\nimport net.minecraft.block.state.IBlockState\nimport net.minecraft.tileentity.TileEntity\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.world.WorldServer\n\nopen class BlockPlacer<T : Block>(\n    private val block: T,\n    private val state: IBlockState = block.defaultState,\n    private val blockPlacerConfigurator: suspend (BlockPlacer<T>) -> Unit = {},\n) : Placer {\n\n    private lateinit var world: WorldServer\n    private lateinit var pos: BlockPos\n    private var placed = false\n\n    override suspend fun place(world: WorldServer, pos: BlockPos): Configurator {\n        this.pos = pos\n        this.world = world\n        world.setBlockState(pos, state)\n        placed = true\n        return configurator(name = \"$block at $pos\") { blockPlacerConfigurator(this@BlockPlacer) }\n    }\n\n    @Suppress(\"UNCHECKED_CAST\")\n    fun <Y : TileEntity> getTileEntity(): Y =\n        if (placed) world.getTileEntity(pos) as Y else error(\"$block has not been placed yet\")\n\n}\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/minecraft/BlockPosSelector.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.minecraft\n\nimport network.rs485.logisticspipes.integration.ONE_VECTOR\nimport net.minecraft.block.BlockColored\nimport net.minecraft.init.Blocks\nimport net.minecraft.item.EnumDyeColor\nimport net.minecraft.util.EnumFacing\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.util.math.Vec3i\nimport net.minecraft.world.WorldServer\nimport kotlin.math.max\nimport kotlin.math.min\nimport kotlinx.coroutines.async\nimport kotlinx.coroutines.awaitAll\nimport kotlinx.coroutines.coroutineScope\n\nclass BlockPosSelector(val worldBuilder: WorldBuilder) {\n    private val placersToOffsets = ArrayList<Pair<Placer, Vec3i>>()\n    private val extraConfigurators = ArrayList<Configurator>()\n    private var finalized: BlockPos? = null\n    var localStart: Vec3i = BlockPos.NULL_VECTOR\n        private set\n    var localEnd: Vec3i = BlockPos.NULL_VECTOR\n        private set\n    var localOffset: Vec3i = BlockPos.NULL_VECTOR\n\n    fun <T> resetOffsetAfter(block: BlockPosSelector.() -> T) = localOffset.let { startOffset ->\n        block.invoke(this).also { localOffset = startOffset }\n    }\n\n    fun direction(direction: EnumFacing): BlockPosSelector = this.also {\n        localOffset += direction.directionVec\n    }\n\n    fun place(placer: Placer): BlockPosSelector = this.also {\n        localStart = BlockPos(\n            min(localStart.x, localOffset.x),\n            min(localStart.y, localOffset.y),\n            min(localStart.z, localOffset.z)\n        ).takeIf { finalized == null || it == localStart }\n            ?: error(\"Range $localStart to $localEnd has been finalized!\")\n        localEnd = BlockPos(\n            max(localEnd.x, localOffset.x),\n            max(localEnd.y, localOffset.y),\n            max(localEnd.z, localOffset.z)\n        ).takeIf { finalized == null || it == localEnd }\n            ?: error(\"Range $localStart to $localEnd has been finalized!\")\n        placersToOffsets += placer to localOffset\n    }\n\n    fun configure(configurator: Configurator): BlockPosSelector = this.also {\n        extraConfigurators.add(configurator)\n    }\n\n    suspend fun finalize() {\n        coroutineScope {\n            val translated = worldBuilder.finalPosition(this@BlockPosSelector)\n            val configurators = placersToOffsets.map {\n                (translated + it.second).let { pos ->\n                    worldBuilder.loadChunk(worldBuilder.world.getChunk(pos).pos)\n                    async {\n                        it.first.place(worldBuilder.world, pos)\n                    }\n                }\n            }.awaitAll()\n            finalized = translated\n            setVisibleState(TestState.RUNNING)\n            (configurators + extraConfigurators).map {\n                async {\n                    it.configure()\n                }\n            }.awaitAll()\n        }\n    }\n\n    fun setVisibleState(state: TestState) = finalized\n        ?.let { it + localStart - ONE_VECTOR }\n        ?.to(state.let {\n            when (it) {\n                TestState.RUNNING -> Blocks.GLOWSTONE.defaultState\n                TestState.FAILED -> Blocks.CONCRETE.defaultState.withProperty(BlockColored.COLOR, EnumDyeColor.RED)\n                TestState.PASSED -> Blocks.CONCRETE.defaultState.withProperty(BlockColored.COLOR, EnumDyeColor.GREEN)\n                TestState.SKIPPED -> Blocks.CONCRETE.defaultState.withProperty(BlockColored.COLOR, EnumDyeColor.YELLOW)\n            }\n        })\n        ?.also {\n            worldBuilder.world.setBlockState(it.first, it.second)\n        }\n}\n\nenum class TestState {\n    RUNNING,\n    FAILED,\n    PASSED,\n    SKIPPED;\n}\n\ninterface Placer {\n    suspend fun place(world: WorldServer, pos: BlockPos): Configurator\n}\n\ninterface Configurator {\n    suspend fun configure()\n}\n\nsuspend fun configurator(name: String? = null, block: suspend () -> Unit) = object : Configurator {\n    override suspend fun configure() = block.invoke()\n\n    override fun toString(): String {\n        return \"Configurator\" + (name?.let { \"($it)\" } ?: \"\")\n    }\n}\n\ninternal operator fun Vec3i.plus(other: Vec3i): Vec3i = Vec3i(x + other.x, y + other.y, z + other.z)\n\ninternal operator fun BlockPos.plus(other: Vec3i): BlockPos = add(other)\ninternal operator fun BlockPos.minus(other: Vec3i): BlockPos = subtract(other)\n"
  },
  {
    "path": "src/test/kotlin/network/rs485/minecraft/WorldBuilder.kt",
    "content": "/*\n * Copyright (c) 2021  RS485\n *\n * \"LogisticsPipes\" is distributed under the terms of the Minecraft Mod Public\n * License 1.0.1, or MMPL. Please check the contents of the license located in\n * https://github.com/RS485/LogisticsPipes/blob/dev/LICENSE.md\n *\n * This file can instead be distributed under the license terms of the\n * MIT license:\n *\n * Copyright (c) 2021  RS485\n *\n * This MIT license was reworded to only match this file. If you use the regular\n * MIT license in your project, replace this copyright notice (this line and any\n * lines below and NOT the copyright line above) with the lines from the original\n * MIT license located here: http://opensource.org/licenses/MIT\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of\n * this file and associated documentation files (the \"Source Code\"), to deal in\n * the Source Code without restriction, including without limitation the rights to\n * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n * of the Source Code, and to permit persons to whom the Source Code is furnished\n * to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Source Code, which also can be\n * distributed under the MIT.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage network.rs485.minecraft\n\nimport net.minecraft.util.math.BlockPos\nimport net.minecraft.util.math.ChunkPos\nimport net.minecraft.world.WorldServer\n\ninterface WorldBuilder {\n    fun finalPosition(selector: BlockPosSelector): BlockPos\n    fun loadChunk(pos: ChunkPos)\n\n    val world: WorldServer\n}\n"
  },
  {
    "path": "style/LP_Format_IntelliJ.xml",
    "content": "<code_scheme name=\"LP Format\">\n  <option name=\"LINE_SEPARATOR\" value=\"&#xA;\" />\n  <option name=\"LAYOUT_STATIC_IMPORTS_SEPARATELY\" value=\"false\" />\n  <option name=\"CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"999\" />\n  <option name=\"NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND\" value=\"999\" />\n  <option name=\"PACKAGES_TO_USE_IMPORT_ON_DEMAND\">\n    <value />\n  </option>\n  <option name=\"IMPORT_LAYOUT_TABLE\">\n    <value>\n      <package name=\"java\" withSubpackages=\"true\" static=\"false\" />\n      <package name=\"javax\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"net.minecraft\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"net.minecraftforge\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"\" withSubpackages=\"true\" static=\"false\" />\n      <emptyLine />\n      <package name=\"logisticspipes\" withSubpackages=\"true\" static=\"false\" />\n      <package name=\"network.rs485\" withSubpackages=\"true\" static=\"false\" />\n    </value>\n  </option>\n  <option name=\"RIGHT_MARGIN\" value=\"160\" />\n  <option name=\"JD_KEEP_EMPTY_LINES\" value=\"false\" />\n  <option name=\"FORMATTER_TAGS_ENABLED\" value=\"true\" />\n  <XML>\n    <option name=\"XML_LEGACY_SETTINGS_IMPORTED\" value=\"true\" />\n  </XML>\n  <codeStyleSettings language=\"JAVA\">\n    <option name=\"KEEP_FIRST_COLUMN_COMMENT\" value=\"false\" />\n    <option name=\"KEEP_BLANK_LINES_IN_DECLARATIONS\" value=\"1\" />\n    <option name=\"KEEP_BLANK_LINES_IN_CODE\" value=\"1\" />\n    <option name=\"KEEP_BLANK_LINES_BEFORE_RBRACE\" value=\"1\" />\n    <option name=\"BLANK_LINES_AFTER_CLASS_HEADER\" value=\"1\" />\n    <option name=\"BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER\" value=\"1\" />\n    <option name=\"ALIGN_MULTILINE_PARAMETERS\" value=\"false\" />\n    <option name=\"ALIGN_MULTILINE_RESOURCES\" value=\"false\" />\n    <option name=\"SPACE_WITHIN_ARRAY_INITIALIZER_BRACES\" value=\"true\" />\n    <option name=\"SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE\" value=\"true\" />\n    <option name=\"CALL_PARAMETERS_WRAP\" value=\"1\" />\n    <option name=\"METHOD_PARAMETERS_WRAP\" value=\"1\" />\n    <option name=\"RESOURCE_LIST_WRAP\" value=\"5\" />\n    <option name=\"EXTENDS_LIST_WRAP\" value=\"1\" />\n    <option name=\"THROWS_LIST_WRAP\" value=\"1\" />\n    <option name=\"EXTENDS_KEYWORD_WRAP\" value=\"1\" />\n    <option name=\"THROWS_KEYWORD_WRAP\" value=\"1\" />\n    <option name=\"METHOD_CALL_CHAIN_WRAP\" value=\"1\" />\n    <option name=\"BINARY_OPERATION_WRAP\" value=\"1\" />\n    <option name=\"BINARY_OPERATION_SIGN_ON_NEXT_LINE\" value=\"true\" />\n    <option name=\"TERNARY_OPERATION_WRAP\" value=\"5\" />\n    <option name=\"KEEP_SIMPLE_BLOCKS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_METHODS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"KEEP_SIMPLE_CLASSES_IN_ONE_LINE\" value=\"true\" />\n    <option name=\"ARRAY_INITIALIZER_WRAP\" value=\"1\" />\n    <option name=\"VARIABLE_ANNOTATION_WRAP\" value=\"2\" />\n    <indentOptions>\n      <option name=\"USE_TAB_CHARACTER\" value=\"true\" />\n    </indentOptions>\n  </codeStyleSettings>\n</code_scheme>\n"
  }
]