├── .github
└── workflows
│ └── gradle.yml
├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
└── main
├── java
└── io
│ └── github
│ └── nuclearfarts
│ └── cbt
│ ├── ColorCacheHack.java
│ ├── ConnectedBlockTextures.java
│ ├── ConnectionConditions.java
│ ├── config
│ ├── BaseCTMConfig.java
│ ├── CTMConfig.java
│ ├── ConnectingCTMConfig.java
│ ├── MainTextureConnectingCTMConfig.java
│ ├── RandomCTMConfig.java
│ └── RepeatingCTMConfig.java
│ ├── mixin
│ ├── ClientWorldMixin.java
│ ├── IdentifierMixin.java
│ ├── ModelLoaderMixin.java
│ ├── NativeImageAccessor.java
│ └── ReloadableResourceManagerImplMixin.java
│ ├── model
│ ├── CBTBakedModel.java
│ └── CBTUnbakedModel.java
│ ├── resource
│ └── CBTResourcePack.java
│ ├── sprite
│ ├── BaseSpriteProvider.java
│ ├── ConnectingSpriteProvider.java
│ ├── FullCTMSpriteProvider.java
│ ├── HorizontalCTMSpriteProvider.java
│ ├── HorizontalVerticalCTMSpriteProvider.java
│ ├── RandomSpriteProvider.java
│ ├── RepeatingCTMSpriteProvider.java
│ ├── SpriteProvider.java
│ ├── TopCTMSpriteProvider.java
│ ├── VerticalCTMSpriteProvider.java
│ └── VerticalHorizontalCTMSpriteProvider.java
│ ├── tile
│ ├── ImageBackedTile.java
│ ├── ResourceBackedTile.java
│ ├── Tile.java
│ ├── loader
│ │ ├── BasicTileLoader.java
│ │ ├── DynamicBookshelfTileLoader.java
│ │ ├── DynamicGlassTileLoader.java
│ │ ├── DynamicSandstoneTileLoader.java
│ │ └── TileLoader.java
│ └── provider
│ │ ├── BasicTileProvider.java
│ │ ├── CompactTileProvider.java
│ │ └── TileProvider.java
│ └── util
│ ├── CBTUtil.java
│ ├── CursedBiomeThing.java
│ ├── SimplePool.java
│ ├── VoidSet.java
│ └── function
│ ├── MutableCachingSupplier.java
│ └── ThrowingPredicate.java
└── resources
├── assets
├── connected_block_textures
│ └── icon.png
└── minecraft
│ ├── models
│ └── block
│ │ ├── template_glass_pane_post.json
│ │ ├── template_glass_pane_side.json
│ │ └── template_glass_pane_side_alt.json
│ └── optifine
│ └── ctm
│ ├── bookshelf
│ └── bookshelf.properties
│ ├── glass
│ ├── black_stained_glass.properties
│ ├── black_stained_glass_pane.properties
│ ├── blue_stained_glass.properties
│ ├── blue_stained_glass_pane.properties
│ ├── brown_stained_glass.properties
│ ├── brown_stained_glass_pane.properties
│ ├── cyan_stained_glass.properties
│ ├── cyan_stained_glass_pane.properties
│ ├── glass.properties
│ ├── glass_pane.properties
│ ├── gray_stained_glass.properties
│ ├── gray_stained_glass_pane.properties
│ ├── green_stained_glass.properties
│ ├── green_stained_glass_pane.properties
│ ├── light_blue_stained_glass.properties
│ ├── light_blue_stained_glass_pane.properties
│ ├── light_gray_stained_glass.properties
│ ├── light_gray_stained_glass_pane.properties
│ ├── lime_stained_glass.properties
│ ├── lime_stained_glass_pane.properties
│ ├── magenta_stained_glass.properties
│ ├── magenta_stained_glass_pane.properties
│ ├── orange_stained_glass.properties
│ ├── orange_stained_glass_pane.properties
│ ├── pink_stained_glass.properties
│ ├── pink_stained_glass_pane.properties
│ ├── purple_stained_glass.properties
│ ├── purple_stained_glass_pane.properties
│ ├── red_stained_glass.properties
│ ├── red_stained_glass_pane.properties
│ ├── tinted_glass.properties
│ ├── white_stained_glass.properties
│ ├── white_stained_glass_pane.properties
│ ├── yellow_stained_glass.properties
│ └── yellow_stained_glass_pane.properties
│ └── sandstone
│ ├── red_sandstone.properties
│ └── sandstone.properties
├── connected_block_textures.mixins.json
├── fabric.mod.json
└── programmer_art
└── assets
└── minecraft
└── optifine
└── ctm
└── glass
├── red_stained_glass_pane_programmer.properties
└── red_stained_glass_programmer.properties
/.github/workflows/gradle.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Gradle
2 |
3 | on: [ push, pull_request ]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - uses: actions/checkout@v2
11 | - name: Set up JDK 8
12 | uses: actions/setup-java@v1
13 | with:
14 | java-version: 16
15 | - name: Grant execute permission for gradlew
16 | run: chmod +x gradlew
17 | - name: Build with Gradle
18 | run: ./gradlew build
19 | - name: Upload build artifacts
20 | uses: actions/upload-artifact@v1
21 | with:
22 | name: build-artifacts
23 | path: build/libs
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # gradle
2 |
3 | .gradle/
4 | build/
5 | out/
6 | classes/
7 |
8 | # idea
9 |
10 | .idea/
11 | *.iml
12 | *.ipr
13 | *.iws
14 |
15 | # vscode
16 |
17 | .settings/
18 | .vscode/
19 | bin/
20 | .classpath
21 | .project
22 | *.launch
23 | # fabric
24 |
25 | run/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # connected-block-textures
2 | An implementation of the MCPatcher/Optifine connected textures format on the Fabric modloader.
3 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'fabric-loom' version '0.8-SNAPSHOT'
3 | id 'maven-publish'
4 | }
5 |
6 | sourceCompatibility = JavaVersion.VERSION_1_8
7 | targetCompatibility = JavaVersion.VERSION_1_8
8 |
9 | archivesBaseName = project.archives_base_name
10 | version = project.mod_version
11 | group = project.maven_group
12 |
13 | minecraft {
14 | }
15 |
16 | dependencies {
17 | //to change the versions see the gradle.properties file
18 | minecraft "com.mojang:minecraft:${project.minecraft_version}"
19 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
20 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
21 |
22 | modImplementation ("net.fabricmc.fabric-api:fabric-api:${project.fabric_version}") {
23 | exclude module: "fabric-loader"
24 | exclude group: "net.fabricmc"
25 | }
26 | }
27 |
28 | processResources {
29 | inputs.property "version", project.version
30 |
31 | filesMatching("fabric.mod.json") {
32 | expand "version": project.version
33 | }
34 | }
35 |
36 | tasks.withType(JavaCompile).configureEach {
37 | // ensure that the encoding is set to UTF-8, no matter what the system default is
38 | // this fixes some edge cases with special characters not displaying correctly
39 | // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
40 | // If Javadoc is generated, this must be specified in that task too.
41 | it.options.encoding = "UTF-8"
42 |
43 | // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
44 | // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
45 | // We'll use that if it's available, but otherwise we'll use the older option.
46 | def targetVersion = 8
47 | if (JavaVersion.current().isJava9Compatible()) {
48 | it.options.release = targetVersion
49 | }
50 | }
51 |
52 | java {
53 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
54 | // if it is present.
55 | // If you remove this line, sources will not be generated.
56 | withSourcesJar()
57 | }
58 |
59 | jar {
60 | from("LICENSE") {
61 | rename { "${it}_${project.archivesBaseName}"}
62 | }
63 | }
64 |
65 | // configure the maven publication
66 | publishing {
67 | publications {
68 | mavenJava(MavenPublication) {
69 | // add all the jars that should be included when publishing to maven
70 | artifact(jar) {
71 | builtBy remapJar
72 | }
73 | artifact(sourcesJar) {
74 | builtBy remapSourcesJar
75 | }
76 | }
77 | }
78 |
79 | // select the repositories you want to publish to
80 | repositories {
81 | // uncomment to publish to the local maven
82 | // mavenLocal()
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Done to increase the memory available to gradle.
2 | org.gradle.jvmargs=-Xmx1G
3 |
4 | # Fabric Properties
5 | # check these on https://fabricmc.net/use
6 | minecraft_version=1.17
7 | yarn_mappings=1.17+build.11
8 | loader_version=0.11.6
9 |
10 | #Fabric api
11 | fabric_version=0.35.2+1.17
12 |
13 | # Mod Properties
14 | mod_version = 0.1.5+1.17
15 | maven_group = io.github.nuclearfarts
16 | archives_base_name = connected-block-textures
17 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HyperCubeMC/connected-block-textures/5e06943fdf444456b54056bc197aef54f4863f30/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | maven {
4 | name = 'Fabric'
5 | url = 'https://maven.fabricmc.net/'
6 | }
7 | gradlePluginPortal()
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/ColorCacheHack.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt;
2 |
3 | import java.util.function.IntSupplier;
4 |
5 | import net.minecraft.client.world.BiomeColorCache;
6 | import net.minecraft.util.math.BlockPos;
7 |
8 | public class ColorCacheHack extends BiomeColorCache {
9 | public int getBiomeColor(BlockPos pos, IntSupplier colorFactory) {
10 | return colorFactory.getAsInt();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/ConnectedBlockTextures.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt;
2 |
3 | import org.apache.logging.log4j.LogManager;
4 | import org.apache.logging.log4j.Logger;
5 |
6 | import net.minecraft.util.Identifier;
7 |
8 | import net.fabricmc.api.ModInitializer;
9 | import io.github.nuclearfarts.cbt.config.CTMConfig;
10 | import io.github.nuclearfarts.cbt.config.MainTextureConnectingCTMConfig;
11 | import io.github.nuclearfarts.cbt.config.RandomCTMConfig;
12 | import io.github.nuclearfarts.cbt.config.RepeatingCTMConfig;
13 | import io.github.nuclearfarts.cbt.resource.CBTResourcePack;
14 | import io.github.nuclearfarts.cbt.sprite.FullCTMSpriteProvider;
15 | import io.github.nuclearfarts.cbt.sprite.HorizontalCTMSpriteProvider;
16 | import io.github.nuclearfarts.cbt.sprite.HorizontalVerticalCTMSpriteProvider;
17 | import io.github.nuclearfarts.cbt.sprite.RandomSpriteProvider;
18 | import io.github.nuclearfarts.cbt.sprite.RepeatingCTMSpriteProvider;
19 | import io.github.nuclearfarts.cbt.sprite.TopCTMSpriteProvider;
20 | import io.github.nuclearfarts.cbt.sprite.VerticalCTMSpriteProvider;
21 | import io.github.nuclearfarts.cbt.sprite.VerticalHorizontalCTMSpriteProvider;
22 | import io.github.nuclearfarts.cbt.tile.loader.DynamicBookshelfTileLoader;
23 | import io.github.nuclearfarts.cbt.tile.loader.DynamicGlassTileLoader;
24 | import io.github.nuclearfarts.cbt.tile.loader.DynamicSandstoneTileLoader;
25 | import io.github.nuclearfarts.cbt.tile.loader.TileLoader;
26 | import io.github.nuclearfarts.cbt.tile.provider.CompactTileProvider;
27 | import io.github.nuclearfarts.cbt.tile.provider.TileProvider;
28 | import it.unimi.dsi.fastutil.objects.Object2IntMap;
29 | import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
30 |
31 | public class ConnectedBlockTextures implements ModInitializer {
32 |
33 | public static final Logger LOGGER = LogManager.getLogger("ConnectedBlockTextures");
34 |
35 | public static CBTResourcePack resourcePack;
36 | public static boolean overrideIdentifierCharRestriction = false;
37 | public static Thread identifierOverrideThread = null;
38 | public static final Object2IntMap RESOURCE_PACK_PRIORITY_MAP = new Object2IntOpenHashMap<>();
39 |
40 | public static final short[] CTM_TO_IDEALIZED_BITHACK = {165, 173, 189, 181, 174, 179, 206, 186, 122, 91, 222, 250, 167, 175, 191, 183, 205, 117, 93, 115, 218, 94, 95, 123, 231, 239, 255, 247, 207, 190, 238, 187, 254, 251, 126, 219, 229, 237, 253, 245, 125, 243, 221, 119, 223, 127, 90};
41 |
42 | @Override
43 | public void onInitialize() {
44 | //connection modes
45 | CTMConfig.registerConfigLoader("ctm", MainTextureConnectingCTMConfig.loaderForFactory(FullCTMSpriteProvider::new));
46 | CTMConfig.registerConfigLoader("top", MainTextureConnectingCTMConfig.loaderForFactory(TopCTMSpriteProvider::new));
47 | CTMConfig.registerConfigLoader("horizontal", MainTextureConnectingCTMConfig.loaderForFactory(HorizontalCTMSpriteProvider::new));
48 | CTMConfig.registerConfigLoader("ctm_compact", MainTextureConnectingCTMConfig.loaderForFactory(FullCTMSpriteProvider::new));
49 | CTMConfig.registerConfigLoader("vertical", MainTextureConnectingCTMConfig.loaderForFactory(VerticalCTMSpriteProvider::new));
50 | CTMConfig.registerConfigLoader("horizontal+vertical", MainTextureConnectingCTMConfig.loaderForFactory(HorizontalVerticalCTMSpriteProvider::new));
51 | CTMConfig.registerConfigLoader("vertical+horizontal", MainTextureConnectingCTMConfig.loaderForFactory(VerticalHorizontalCTMSpriteProvider::new));
52 | //legacy random textures/texture replacement modes
53 | CTMConfig.registerConfigLoader("fixed", RandomCTMConfig.loaderForFactory(RandomSpriteProvider::new));
54 | CTMConfig.registerConfigLoader("random", RandomCTMConfig.loaderForFactory(RandomSpriteProvider::new));
55 | //repeating pattern
56 | CTMConfig.registerConfigLoader("repeat", RepeatingCTMConfig.loaderForFactory(RepeatingCTMSpriteProvider::new));
57 |
58 | TileProvider.registerTileProviderFactory("ctm_compact", CompactTileProvider::new);
59 |
60 | TileLoader.registerSpecialTileLoader("$CBT_SPECIAL_DYNAMIC_GLASS", DynamicGlassTileLoader::new);
61 | TileLoader.registerSpecialTileLoader("$CBT_SPECIAL_DYNAMIC_SANDSTONE", DynamicSandstoneTileLoader::new);
62 | TileLoader.registerSpecialTileLoader("$CBT_SPECIAL_DYNAMIC_BOOKSHELF", DynamicBookshelfTileLoader::new);
63 | }
64 |
65 | public static Identifier id(String string) {
66 | return new Identifier("connected_block_textures", string);
67 | }
68 |
69 | public static void breakpointHack() {
70 | System.out.println("bp");
71 | }
72 |
73 | static {
74 | RESOURCE_PACK_PRIORITY_MAP.defaultReturnValue(-1);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/ConnectionConditions.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt;
2 |
3 | import java.util.function.BiPredicate;
4 |
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.client.MinecraftClient;
7 | import net.minecraft.client.render.block.BlockModels;
8 |
9 | public enum ConnectionConditions implements BiPredicate {
10 | BLOCK((t, o) -> t.getBlock() == o.getBlock()),
11 | BLOCKS((t, o) -> t.getBlock() == o.getBlock()),
12 | STATE((t, o) -> t == o),
13 | MATERIAL((t, o) -> t.getMaterial() == o.getMaterial()),
14 | TILE((t, o) -> {
15 | BlockModels models = MinecraftClient.getInstance().getBakedModelManager().getBlockModels();
16 | return models.getSprite(t) == models.getSprite(o);
17 | });
18 |
19 | private final BiPredicate func;
20 |
21 | private ConnectionConditions(BiPredicate func) {
22 | this.func = func;
23 | }
24 |
25 | @Override
26 | public boolean test(BlockState myState, BlockState otherState) {
27 | return func.test(myState, otherState);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/config/BaseCTMConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.config;
2 |
3 | import io.github.nuclearfarts.cbt.ConnectedBlockTextures;
4 | import io.github.nuclearfarts.cbt.sprite.SpriteProvider;
5 | import io.github.nuclearfarts.cbt.tile.provider.TileProvider;
6 | import io.github.nuclearfarts.cbt.util.CBTUtil;
7 | import io.github.nuclearfarts.cbt.util.CursedBiomeThing;
8 | import net.minecraft.client.MinecraftClient;
9 | import net.minecraft.client.texture.Sprite;
10 | import net.minecraft.client.util.ModelIdentifier;
11 | import net.minecraft.client.util.SpriteIdentifier;
12 | import net.minecraft.resource.ResourceManager;
13 | import net.minecraft.util.Identifier;
14 | import net.minecraft.util.math.BlockPos;
15 | import net.minecraft.util.math.Direction;
16 | import net.minecraft.util.registry.Registry;
17 | import net.minecraft.world.BlockRenderView;
18 | import net.minecraft.world.biome.Biome;
19 |
20 | import java.io.IOException;
21 | import java.util.*;
22 | import java.util.function.BiPredicate;
23 | import java.util.function.IntPredicate;
24 | import java.util.function.Predicate;
25 | import java.util.function.Supplier;
26 | import java.util.stream.Collectors;
27 |
28 | //Java generics are awful.
29 | public abstract class BaseCTMConfig> implements CTMConfig {
30 |
31 | protected final TileProvider tileProvider;
32 | protected final Predicate tileMatcher;
33 | protected final Predicate blockMatcher;
34 | protected final Predicate faceMatcher;
35 | protected final BiPredicate worldConditions;
36 | protected final int packPriority;
37 | protected final int weight;
38 | protected final String fileName;
39 | protected final SpriteProviderFactory spriteProviderFactory;
40 |
41 | public BaseCTMConfig(Properties properties, Identifier location, ResourceManager manager, SpriteProviderFactory bakedModelFactory, String packName) throws IOException {
42 | if(properties.containsKey("matchTiles")) {
43 | tileMatcher = Arrays.stream(properties.getProperty("matchTiles").split(" ")).map(s -> CBTUtil.prependId(new Identifier(s), "block/")).collect(Collectors.toCollection(HashSet::new))::contains;
44 | } else {
45 | tileMatcher = null;
46 | }
47 |
48 | if(properties.containsKey("matchBlocks")) {
49 | blockMatcher = Arrays.stream(properties.getProperty("matchBlocks").split(" ")).map(Identifier::new).collect(Collectors.toCollection(HashSet::new))::contains;
50 | } else {
51 | blockMatcher = identifier -> true;
52 | }
53 |
54 | Predicate biomeMatcher;
55 | if(properties.containsKey("biomes") && MinecraftClient.getInstance().world != null) {
56 | Registry biomes = MinecraftClient.getInstance().world.getRegistryManager().get(Registry.BIOME_KEY);
57 | biomeMatcher = Arrays.stream(properties.getProperty("biomes").split(" ")).map(Identifier::new).map(biomes::get).collect(Collectors.toCollection(HashSet::new))::contains;
58 | } else {
59 | biomeMatcher = null;
60 | }
61 |
62 | IntPredicate heightMatcher;
63 | if(properties.containsKey("heights")) {
64 | List heightTests = new ArrayList<>();
65 | for(String range : properties.getProperty("heights").split(" ")) {
66 | String[] split = range.split("-");
67 | int min = Integer.parseInt(split[0]);
68 | int max = Integer.parseInt(split[1]);
69 | heightTests.add(i -> min <= i && i <= max);
70 | }
71 | if(heightTests.size() == 1) {
72 | heightMatcher = heightTests.get(0);
73 | } else {
74 | heightMatcher = i -> CBTUtil.satisfiesAny(heightTests, i);
75 | }
76 | } else {
77 | heightMatcher = i -> true;
78 | }
79 |
80 | if(biomeMatcher != null) {
81 | worldConditions = (w, p) -> biomeMatcher.test(CursedBiomeThing.getBiome(w, p)) && heightMatcher.test(p.getY());
82 | } else {
83 | worldConditions = (w, p) -> heightMatcher.test(p.getY());
84 | }
85 |
86 | if(properties.containsKey("faces")) {
87 | Set faces = EnumSet.noneOf(Direction.class);
88 | for(String face : properties.getProperty("faces").split(" ")) {
89 | switch(face) {
90 | case "sides":
91 | faces.add(Direction.NORTH);
92 | faces.add(Direction.EAST);
93 | faces.add(Direction.SOUTH);
94 | faces.add(Direction.WEST);
95 | break;
96 | case "top":
97 | faces.add(Direction.UP);
98 | break;
99 | case "bottom":
100 | faces.add(Direction.DOWN);
101 | break;
102 | case "all":
103 | Collections.addAll(faces, Direction.values());
104 | break;
105 | default:
106 | faces.add(Direction.valueOf(face.toUpperCase(Locale.ENGLISH))); //avoid the turkish bug
107 | break;
108 | }
109 | }
110 | faceMatcher = faces::contains;
111 | } else {
112 | faceMatcher = direction -> true;
113 | }
114 |
115 | weight = Integer.parseInt(properties.getProperty("weight", "0"));
116 |
117 | if(properties.containsKey("cbt_special_change_pack_if_loaded")) {
118 | String packOverride = properties.getProperty("cbt_special_change_pack_if_loaded");
119 | if(ConnectedBlockTextures.RESOURCE_PACK_PRIORITY_MAP.containsKey(packOverride)) {
120 | packName = packOverride;
121 | }
122 | }
123 |
124 | this.packPriority = ConnectedBlockTextures.RESOURCE_PACK_PRIORITY_MAP.getInt(packName);
125 | this.spriteProviderFactory = bakedModelFactory;
126 | this.tileProvider = TileProvider.load(properties, CBTUtil.directoryOf(location), manager);
127 | this.fileName = CBTUtil.fileNameOf(location);
128 | }
129 |
130 | public int compareTo(CTMConfig other) {
131 | if(getResourcePackPriority() != other.getResourcePackPriority()) {
132 | return getResourcePackPriority() - other.getResourcePackPriority();
133 | }
134 |
135 | if(getWeight() != other.getWeight()) {
136 | return getWeight() - other.getWeight();
137 | }
138 |
139 | if(!getFileName().equals(other.getFileName())) {
140 | return getFileName().compareTo(other.getFileName());
141 | }
142 |
143 | return 0;
144 | }
145 |
146 | @Override
147 | public TileProvider getTileProvider() {
148 | return tileProvider;
149 | }
150 |
151 | @Override
152 | public Predicate getTileMatcher() {
153 | return tileMatcher;
154 | }
155 |
156 | @Override
157 | public Predicate getFaceMatcher() {
158 | return faceMatcher;
159 | }
160 |
161 | @Override
162 | public BiPredicate getWorldConditions() {
163 | return worldConditions;
164 | }
165 |
166 | @Override
167 | public SpriteProvider createSpriteProvider(Sprite[] sprites) {
168 | return spriteProviderFactory.create(sprites, getSelf());
169 | }
170 |
171 | @Override
172 | public boolean affectsModel(ModelIdentifier id, Supplier> textureDeps) {
173 | return (blockMatcher.test(id) || blockMatcher.test(CBTUtil.stripVariants(id))) && (tileMatcher == null || CBTUtil.mapAnyMatch(textureDeps.get(), SpriteIdentifier::getTextureId, tileMatcher));
174 | }
175 |
176 | @Override
177 | public int getResourcePackPriority() {
178 | return packPriority;
179 | }
180 |
181 | @Override
182 | public int getWeight() {
183 | return weight;
184 | }
185 |
186 | @Override
187 | public String getFileName() {
188 | return fileName;
189 | }
190 |
191 | @FunctionalInterface
192 | public interface SpriteProviderFactory> {
193 | SpriteProvider create(Sprite[] sprites, C config);
194 | }
195 |
196 | protected abstract Self getSelf(); //java pls
197 | }
198 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/config/CTMConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.config;
2 |
3 | import java.io.IOException;
4 | import java.util.Collection;
5 | import java.util.HashMap;
6 | import java.util.Map;
7 | import java.util.Properties;
8 | import java.util.function.BiPredicate;
9 | import java.util.function.Predicate;
10 | import java.util.function.Supplier;
11 |
12 | import net.minecraft.client.texture.Sprite;
13 | import net.minecraft.client.util.ModelIdentifier;
14 | import net.minecraft.client.util.SpriteIdentifier;
15 | import net.minecraft.resource.Resource;
16 | import net.minecraft.resource.ResourceManager;
17 | import net.minecraft.util.Identifier;
18 | import net.minecraft.util.math.BlockPos;
19 | import net.minecraft.util.math.Direction;
20 | import net.minecraft.world.BlockRenderView;
21 |
22 | import io.github.nuclearfarts.cbt.sprite.SpriteProvider;
23 | import io.github.nuclearfarts.cbt.tile.provider.TileProvider;
24 |
25 | public interface CTMConfig extends Comparable {
26 | TileProvider getTileProvider();
27 | Predicate getTileMatcher();
28 | Predicate getFaceMatcher();
29 | BiPredicate getWorldConditions();
30 | SpriteProvider createSpriteProvider(Sprite[] sprites);
31 | boolean affectsModel(ModelIdentifier id, Supplier> textureDeps);
32 | int getResourcePackPriority();
33 | int getWeight();
34 | String getFileName();
35 |
36 | static void registerConfigLoader(String formatName, Loader> loader) {
37 | PrivateConstants.CTM_CONFIG_LOADERS.put(formatName, loader);
38 | }
39 |
40 | static CTMConfig load(Properties properties, Identifier location, ResourceManager manager, String packName) throws IOException {
41 | Loader> loader;
42 | if((loader = PrivateConstants.CTM_CONFIG_LOADERS.get(properties.getProperty("method"))) != null) {
43 | return loader.load(properties, location, manager, packName);
44 | }
45 | throw new IllegalArgumentException("Invalid or unsupported CTM method " + properties.getProperty("method"));
46 | }
47 |
48 | static CTMConfig load(Identifier propertiesLocation, ResourceManager manager) throws IOException {
49 | Properties properties = new Properties();
50 | Resource resource = manager.getResource(propertiesLocation);
51 | properties.load(resource.getInputStream());
52 | return CTMConfig.load(properties, propertiesLocation, manager, resource.getResourcePackName());
53 | }
54 |
55 | @FunctionalInterface
56 | public interface Loader {
57 | T load(Properties properties, Identifier location, ResourceManager manager, String packName) throws IOException;
58 | }
59 |
60 | public static final class PrivateConstants {
61 | private PrivateConstants() { }
62 | private static final Map> CTM_CONFIG_LOADERS = new HashMap<>();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/config/ConnectingCTMConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.config;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 | import java.util.function.BiPredicate;
6 | import net.minecraft.block.BlockState;
7 | import net.minecraft.resource.ResourceManager;
8 | import net.minecraft.util.Identifier;
9 |
10 | public abstract class ConnectingCTMConfig> extends BaseCTMConfig {
11 | public ConnectingCTMConfig(Properties properties, Identifier location, ResourceManager manager, SpriteProviderFactory bakedModelFactory, String packName) throws IOException {
12 | super(properties, location, manager, bakedModelFactory, packName);
13 | }
14 |
15 | public abstract BiPredicate getConnectionMatcher();
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/config/MainTextureConnectingCTMConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.config;
2 |
3 | import java.io.IOException;
4 | import java.util.Locale;
5 | import java.util.Properties;
6 | import java.util.function.BiPredicate;
7 | import net.minecraft.block.BlockState;
8 | import net.minecraft.resource.ResourceManager;
9 | import net.minecraft.util.Identifier;
10 | import io.github.nuclearfarts.cbt.ConnectionConditions;
11 |
12 | public class MainTextureConnectingCTMConfig extends ConnectingCTMConfig {
13 | private final BiPredicate connectionMatcher;
14 |
15 | public static CTMConfig.Loader loaderForFactory(SpriteProviderFactory factory) {
16 | return (p, l, m, n) -> new MainTextureConnectingCTMConfig(p, l, m, factory, n);
17 | }
18 |
19 | public MainTextureConnectingCTMConfig(Properties properties, Identifier location, ResourceManager manager, SpriteProviderFactory bakedModelFactory, String packName) throws IOException {
20 | super(properties, location, manager, bakedModelFactory, packName);
21 | String connect = properties.getProperty("connect", properties.containsKey("matchBlocks") ? "blocks" : "tiles");
22 | connectionMatcher = ConnectionConditions.valueOf(connect.toUpperCase(Locale.ENGLISH));
23 | }
24 |
25 | @Override
26 | public BiPredicate getConnectionMatcher() {
27 | return connectionMatcher;
28 | }
29 |
30 | @Override
31 | protected MainTextureConnectingCTMConfig getSelf() {
32 | return this;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/config/RandomCTMConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.config;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 | import net.minecraft.resource.ResourceManager;
6 | import net.minecraft.util.Identifier;
7 |
8 | public class RandomCTMConfig extends BaseCTMConfig {
9 |
10 | public static CTMConfig.Loader loaderForFactory(SpriteProviderFactory factory) {
11 | return (p, l, m, n) -> new RandomCTMConfig(p, l, m, factory, n);
12 | }
13 |
14 | public RandomCTMConfig(Properties properties, Identifier location, ResourceManager manager, SpriteProviderFactory bakedModelFactory, String packName) throws IOException {
15 | super(properties, location, manager, bakedModelFactory, packName);
16 | }
17 |
18 | @Override
19 | protected RandomCTMConfig getSelf() {
20 | return this;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/config/RepeatingCTMConfig.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.config;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 | import net.minecraft.resource.ResourceManager;
6 | import net.minecraft.util.Identifier;
7 |
8 | public class RepeatingCTMConfig extends BaseCTMConfig {
9 | private final int width;
10 | private final int height;
11 |
12 | public static CTMConfig.Loader loaderForFactory(SpriteProviderFactory factory) {
13 | return (p, l, m, n) -> new RepeatingCTMConfig(p, l, m, factory, n);
14 | }
15 |
16 | public RepeatingCTMConfig(Properties properties, Identifier location, ResourceManager manager, SpriteProviderFactory bakedModelFactory, String packName) throws IOException {
17 | super(properties, location, manager, bakedModelFactory, packName);
18 | width = Integer.parseInt(properties.getProperty("width"));
19 | height = Integer.parseInt(properties.getProperty("height"));
20 | }
21 |
22 | @Override
23 | protected RepeatingCTMConfig getSelf() {
24 | return this;
25 | }
26 |
27 | public int getWidth() {
28 | return width;
29 | }
30 |
31 | public int getHeight() {
32 | return height;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/mixin/ClientWorldMixin.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.mixin;
2 |
3 | import org.spongepowered.asm.mixin.Final;
4 | import org.spongepowered.asm.mixin.Mixin;
5 | import org.spongepowered.asm.mixin.Shadow;
6 | import org.spongepowered.asm.mixin.injection.At;
7 | import org.spongepowered.asm.mixin.injection.Inject;
8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
9 |
10 | import net.minecraft.client.world.BiomeColorCache;
11 | import net.minecraft.client.world.ClientWorld;
12 | import net.minecraft.world.level.ColorResolver;
13 |
14 | import io.github.nuclearfarts.cbt.ColorCacheHack;
15 | import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
16 |
17 | @Mixin(ClientWorld.class)
18 | public class ClientWorldMixin {
19 | @Shadow
20 | private @Final Object2ObjectArrayMap colorCache;
21 |
22 | @Inject(method = "", at = @At("RETURN"))
23 | private void cachePls(CallbackInfo callback) {
24 | colorCache.defaultReturnValue(new ColorCacheHack());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/mixin/IdentifierMixin.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.mixin;
2 |
3 | import org.spongepowered.asm.mixin.Mixin;
4 | import org.spongepowered.asm.mixin.injection.At;
5 | import org.spongepowered.asm.mixin.injection.Inject;
6 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
7 |
8 | import net.minecraft.util.Identifier;
9 |
10 | import io.github.nuclearfarts.cbt.ConnectedBlockTextures;
11 |
12 | @Mixin(Identifier.class)
13 | public class IdentifierMixin {
14 | @Inject(method = "isPathValid(Ljava/lang/String;)Z", at = @At("HEAD"), cancellable = true)
15 | private static void overrideIdentifierRestrictions(CallbackInfoReturnable callback) {
16 | if(ConnectedBlockTextures.overrideIdentifierCharRestriction && Thread.currentThread() == ConnectedBlockTextures.identifierOverrideThread) {
17 | callback.setReturnValue(true);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/mixin/ModelLoaderMixin.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.mixin;
2 |
3 | import net.minecraft.client.render.model.ModelLoader;
4 | import net.minecraft.client.render.model.UnbakedModel;
5 | import net.minecraft.client.util.ModelIdentifier;
6 | import net.minecraft.client.util.SpriteIdentifier;
7 | import net.minecraft.resource.ResourceManager;
8 | import net.minecraft.util.Identifier;
9 | import net.minecraft.util.profiler.Profiler;
10 |
11 | import io.github.nuclearfarts.cbt.ConnectedBlockTextures;
12 | import io.github.nuclearfarts.cbt.config.CTMConfig;
13 | import io.github.nuclearfarts.cbt.model.CBTUnbakedModel;
14 | import io.github.nuclearfarts.cbt.util.CBTUtil;
15 | import io.github.nuclearfarts.cbt.util.VoidSet;
16 | import io.github.nuclearfarts.cbt.util.function.MutableCachingSupplier;
17 |
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.Collection;
21 | import java.util.HashSet;
22 | import java.util.List;
23 | import java.util.Map;
24 | import java.util.Set;
25 | import java.util.SortedSet;
26 | import java.util.TreeSet;
27 | import org.spongepowered.asm.mixin.Final;
28 | import org.spongepowered.asm.mixin.Mixin;
29 | import org.spongepowered.asm.mixin.Shadow;
30 | import org.spongepowered.asm.mixin.Unique;
31 | import org.spongepowered.asm.mixin.injection.At;
32 | import org.spongepowered.asm.mixin.injection.Redirect;
33 |
34 | @Mixin(ModelLoader.class)
35 | public abstract class ModelLoaderMixin {
36 | @Shadow
37 | private @Final Map unbakedModels;
38 | @Shadow
39 | private @Final Map modelsToBake;
40 | @Shadow
41 | private @Final ResourceManager resourceManager;
42 |
43 | @Redirect(method = "", at = @At(value = "INVOKE_STRING", target = "net/minecraft/util/profiler/Profiler.swap(Ljava/lang/String;)V", args = "ldc=textures"))
44 | private void injectCbtModels(Profiler on, String str) {
45 | on.swap("ctm");
46 | ConnectedBlockTextures.overrideIdentifierCharRestriction = true;
47 | ConnectedBlockTextures.identifierOverrideThread = Thread.currentThread();
48 | List data = new ArrayList<>();
49 | Collection propertiesIds = resourceManager.findResources("optifine/ctm", s -> s.endsWith(".properties"));
50 | for(Identifier id : propertiesIds) {
51 | try {
52 | data.add(CTMConfig.load(id, resourceManager));
53 | } catch(Exception e) {
54 | ConnectedBlockTextures.LOGGER.error("Error loading connected textures config at " + id, e);
55 | }
56 | }
57 |
58 | Set priorityFails = new HashSet<>();
59 | MutableCachingSupplier> textureCached = new MutableCachingSupplier<>();
60 | unbakedModels.forEach((id, model) -> {
61 | if(id instanceof ModelIdentifier) {
62 | ModelIdentifier modelId = (ModelIdentifier) id;
63 | if(!modelId.getVariant().equals("inventory")) {
64 | UnbakedModel newModel = checkCtmConfigs(modelId, model, textureCached, data, priorityFails);
65 | if(newModel != model) {
66 | unbakedModels.put(id, newModel);
67 | modelsToBake.put(id, newModel);
68 | }
69 | }
70 | }
71 | });
72 | ConnectedBlockTextures.overrideIdentifierCharRestriction = false;
73 | on.swap(str);
74 | }
75 |
76 | @Unique
77 | private UnbakedModel checkCtmConfigs(ModelIdentifier id, UnbakedModel model, MutableCachingSupplier> textureCached, List data, Set priorityFails) {
78 | Set configs = new TreeSet<>();
79 | boolean foundNewConfigs = false;
80 | do {
81 | SortedSet newConfigs = new TreeSet<>();
82 | UnbakedModel javaPls = model;
83 | textureCached.set(() -> javaPls.getTextureDependencies(((ModelLoader) (Object) this)::getOrLoadModel, VoidSet.get()));
84 | for(CTMConfig c : data) {
85 | if(c.affectsModel(id, textureCached) && CBTUtil.allMatchThrowable(textureCached.get(), s -> checkPack(s, c.getResourcePackPriority(), priorityFails))) {
86 | if(configs.add(c)) {
87 | newConfigs.add(c);
88 | }
89 | }
90 | }
91 | foundNewConfigs = !newConfigs.isEmpty();
92 | if(foundNewConfigs) {
93 | model = new CBTUnbakedModel(model, newConfigs.toArray(new CTMConfig[newConfigs.size()]));
94 | }
95 | } while(foundNewConfigs);
96 | return model;
97 | }
98 |
99 | @Unique
100 | private boolean checkPack(SpriteIdentifier spriteId, int ctmPackPriority, Set fails) {
101 | Identifier texId = spriteId.getTextureId();
102 | String spritePack;
103 | try {
104 | spritePack = resourceManager.getResource(new Identifier(texId.getNamespace(), "textures/" + texId.getPath() + ".png")).getResourcePackName();
105 | } catch(IOException e) {
106 | if(fails.add(texId)) {
107 | ConnectedBlockTextures.LOGGER.error("Error checking resource pack priority", e);
108 | }
109 | return true;
110 | }
111 | return ConnectedBlockTextures.RESOURCE_PACK_PRIORITY_MAP.getInt(spritePack) <= ctmPackPriority;
112 | }
113 | }
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/mixin/NativeImageAccessor.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.mixin;
2 |
3 | import java.nio.channels.WritableByteChannel;
4 |
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Invoker;
7 |
8 | import net.minecraft.client.texture.NativeImage;
9 |
10 | @Mixin(NativeImage.class)
11 | public interface NativeImageAccessor {
12 | @Invoker
13 | boolean invokeWrite(WritableByteChannel channel);
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/mixin/ReloadableResourceManagerImplMixin.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.mixin;
2 |
3 | import java.util.List;
4 | import java.util.concurrent.CompletableFuture;
5 | import java.util.concurrent.Executor;
6 |
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.Shadow;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Inject;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
12 |
13 | import net.minecraft.resource.ReloadableResourceManager;
14 | import net.minecraft.resource.ReloadableResourceManagerImpl;
15 | import net.minecraft.resource.ResourcePack;
16 | import net.minecraft.resource.ResourceReload;
17 | import net.minecraft.util.Unit;
18 |
19 | import io.github.nuclearfarts.cbt.ConnectedBlockTextures;
20 | import io.github.nuclearfarts.cbt.resource.CBTResourcePack;
21 |
22 | @Mixin(ReloadableResourceManagerImpl.class)
23 | public abstract class ReloadableResourceManagerImplMixin implements ReloadableResourceManager {
24 | @Shadow
25 | public abstract void addPack(ResourcePack resourcePack);
26 |
27 | @Inject(method = "reload", at = @At(value = "RETURN", shift = At.Shift.BEFORE))
28 | private void injectCBTPack(Executor prepareExecutor, Executor applyExecutor, CompletableFuture initialStage, List packs, CallbackInfoReturnable cir) {
29 | ConnectedBlockTextures.RESOURCE_PACK_PRIORITY_MAP.clear();
30 | for(int i = 0; i < packs.size(); i++) {
31 | ConnectedBlockTextures.RESOURCE_PACK_PRIORITY_MAP.put(packs.get(i).getName(), i);
32 | }
33 | this.addPack(ConnectedBlockTextures.resourcePack = new CBTResourcePack(this));
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/model/CBTBakedModel.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.model;
2 |
3 | import java.util.Random;
4 | import java.util.function.Supplier;
5 |
6 | import net.minecraft.block.BlockState;
7 | import net.minecraft.client.MinecraftClient;
8 | import net.minecraft.client.render.model.BakedModel;
9 | import net.minecraft.client.texture.Sprite;
10 | import net.minecraft.client.texture.SpriteAtlasTexture;
11 | import net.minecraft.util.math.Vec3f;
12 | import net.minecraft.item.ItemStack;
13 | import net.minecraft.util.math.BlockPos;
14 | import net.minecraft.util.math.Direction;
15 | import net.minecraft.world.BlockRenderView;
16 |
17 | import net.fabricmc.fabric.api.renderer.v1.mesh.MutableQuadView;
18 | import net.fabricmc.fabric.api.renderer.v1.model.ForwardingBakedModel;
19 | import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
20 | import net.fabricmc.fabric.api.renderer.v1.render.RenderContext;
21 |
22 | import io.github.nuclearfarts.cbt.sprite.SpriteProvider;
23 |
24 | public class CBTBakedModel extends ForwardingBakedModel {
25 | protected final SpriteProvider[] spriteProviders;
26 |
27 | public CBTBakedModel(BakedModel baseModel, SpriteProvider[] spriteProviders) {
28 | wrapped = baseModel;
29 | this.spriteProviders = spriteProviders;
30 | }
31 |
32 | @Override
33 | public boolean isVanillaAdapter() {
34 | return false;
35 | }
36 |
37 | @Override
38 | public void emitBlockQuads(BlockRenderView blockView, BlockState state, BlockPos pos, Supplier randomSupplier, RenderContext context) {
39 | SpriteFinder spriteFinder = SpriteFinder.get(MinecraftClient.getInstance().getBakedModelManager().getAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE));
40 | context.pushTransform(quad -> {
41 | for(SpriteProvider provider : spriteProviders) {
42 | //use short-circuiting to our advantage to save the more expensive ones for last
43 | if(provider.affectsDirection(quad.nominalFace()) && provider.affectsBlock(blockView, state, pos) && provider.affectsSprite(quad, spriteFinder)) {
44 | //which way is up relative to the texture?
45 | Vec3f lowV1 = new Vec3f();
46 | int lowV1I = -1;
47 | Vec3f lowV2 = new Vec3f();
48 | Vec3f lowU1 = new Vec3f();
49 | int lowU1I = -1;
50 | Vec3f lowU2 = new Vec3f();
51 |
52 | Vec3f current = new Vec3f();
53 | Vec3f center = new Vec3f();
54 |
55 | float lastLowV = Float.MAX_VALUE;
56 | float lastLowU = Float.MAX_VALUE;
57 | for(int i = 0; i < 4; i++) {
58 | float v = quad.spriteV(i, 0);
59 | float u = quad.spriteU(i, 0);
60 | quad.copyPos(i, current);
61 | center.add(current);
62 | if(v < lastLowV) {
63 | lowV1I = i;
64 | lastLowV = v;
65 | quad.copyPos(i, lowV1);
66 | }
67 | if(u < lastLowU) {
68 | lowU1I = i;
69 | lastLowU = u;
70 | quad.copyPos(i, lowU1);
71 | }
72 | }
73 | // find center
74 | center.scale(1f/4f);
75 | // 2nd lowest
76 | lastLowV = Float.MAX_VALUE;
77 | lastLowU = Float.MAX_VALUE;
78 | for(int i = 0; i < 4; i++) {
79 | float v = quad.spriteV(i, 0);
80 | float u = quad.spriteU(i, 0);
81 | if(lowV1I != i && v < lastLowV) {
82 | lastLowV = v;
83 | quad.copyPos(i, lowV2);
84 | }
85 | if(lowU1I != i && u < lastLowU) {
86 | lastLowU = u;
87 | quad.copyPos(i, lowU2);
88 | }
89 | }
90 |
91 | // find center of low-v edge
92 | lowV1.add(lowV2);
93 | lowV1.scale(0.5f);
94 | // find center of low-u edge
95 | lowU1.add(lowU2);
96 | lowU1.scale(0.5f);
97 | // find vector between center of quad and center of edge
98 | lowV1.subtract(center);
99 | lowU1.subtract(center);
100 |
101 | Direction upDir = Direction.getFacing(lowV1.getX(), lowV1.getY(), lowV1.getZ());
102 | Direction leftDir = Direction.getFacing(lowU1.getX(), lowU1.getY(), lowU1.getZ());
103 |
104 | Sprite newSpr;
105 | if((newSpr = provider.getSpriteForSide(quad.nominalFace(), upDir, leftDir, blockView, state, pos, randomSupplier.get())) != null) {
106 | quad.spriteBake(0, newSpr, MutableQuadView.BAKE_LOCK_UV);
107 | }
108 | }
109 | }
110 | return true;
111 | });
112 | super.emitBlockQuads(blockView, state, pos, randomSupplier, context);
113 | context.popTransform();
114 | }
115 |
116 | @Override
117 | public void emitItemQuads(ItemStack stack, Supplier randomSupplier, RenderContext context) {
118 | throw new UnsupportedOperationException("CBT models should never try to render as an item! THIS IS A PROBLEM!");
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/model/CBTUnbakedModel.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.model;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.Collections;
6 | import java.util.List;
7 | import java.util.Set;
8 | import java.util.function.Function;
9 | import com.mojang.datafixers.util.Pair;
10 |
11 | import net.minecraft.client.render.model.BakedModel;
12 | import net.minecraft.client.render.model.ModelBakeSettings;
13 | import net.minecraft.client.render.model.ModelLoader;
14 | import net.minecraft.client.render.model.UnbakedModel;
15 | import net.minecraft.client.texture.Sprite;
16 | import net.minecraft.client.util.SpriteIdentifier;
17 | import net.minecraft.util.Identifier;
18 |
19 | import io.github.nuclearfarts.cbt.config.CTMConfig;
20 | import io.github.nuclearfarts.cbt.sprite.SpriteProvider;
21 |
22 | public class CBTUnbakedModel implements UnbakedModel {
23 |
24 | private final UnbakedModel baseModel;
25 | private final CTMConfig[] configs;
26 |
27 | public CBTUnbakedModel(UnbakedModel baseModel, CTMConfig[] configs) {
28 | this.baseModel = baseModel;
29 | this.configs = configs;
30 | }
31 |
32 | @Override
33 | public Collection getModelDependencies() {
34 | return Collections.emptySet();
35 | }
36 |
37 | @Override
38 | public Collection getTextureDependencies(Function unbakedModelGetter, Set> unresolvedTextureReferences) {
39 | Collection baseDeps = baseModel.getTextureDependencies(unbakedModelGetter, unresolvedTextureReferences);
40 | Collection allDeps = new ArrayList(baseDeps);
41 | for(CTMConfig config : configs) {
42 | allDeps.addAll(config.getTileProvider().getIdsToLoad());
43 | }
44 | return allDeps;
45 | }
46 |
47 | @Override
48 | public BakedModel bake(ModelLoader loader, Function textureGetter, ModelBakeSettings rotationContainer, Identifier modelId) {
49 | try {
50 | List spriteProviders = new ArrayList<>();
51 | for(CTMConfig config : configs) {
52 | spriteProviders.add(config.createSpriteProvider(config.getTileProvider().load(textureGetter)));
53 | }
54 | return new CBTBakedModel(baseModel.bake(loader, textureGetter, rotationContainer, modelId), spriteProviders.toArray(new SpriteProvider[spriteProviders.size()]));
55 | } catch (Exception e) {
56 | e.printStackTrace();
57 | return null;
58 | }
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/resource/CBTResourcePack.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.resource;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.nio.channels.Channels;
8 | import java.util.Collection;
9 | import java.util.Collections;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Set;
13 | import java.util.function.Predicate;
14 | import java.util.stream.Collectors;
15 |
16 | import com.google.common.collect.ImmutableSet;
17 |
18 | import net.minecraft.client.texture.NativeImage;
19 | import net.minecraft.resource.ResourceManager;
20 | import net.minecraft.resource.ResourcePack;
21 | import net.minecraft.resource.ResourceType;
22 | import net.minecraft.resource.metadata.ResourceMetadataReader;
23 | import net.minecraft.util.Identifier;
24 |
25 | import io.github.nuclearfarts.cbt.mixin.NativeImageAccessor;
26 | import io.github.nuclearfarts.cbt.tile.Tile;
27 |
28 | public class CBTResourcePack implements ResourcePack {
29 |
30 | private static final Set NAMESPACES = ImmutableSet.of("connectedblocktextures");
31 |
32 | private final Map aliases = new HashMap<>();
33 | private final Map resources = new HashMap<>();
34 | private final ResourceManager manager;
35 |
36 | private int genCounter = 0;
37 |
38 | public CBTResourcePack(ResourceManager manager) {
39 | this.manager = manager;
40 | }
41 |
42 | public void putResource(String resource, byte[] data) {
43 | resources.put(resource, data);
44 | }
45 |
46 | public void alias(String location, Identifier to) {
47 | aliases.put(location, to);
48 | }
49 |
50 | public void putImage(String location, NativeImage image) {
51 | ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
52 | ((NativeImageAccessor) (Object) image).invokeWrite(Channels.newChannel(byteOut));
53 | image.close();
54 | putResource(location, byteOut.toByteArray());
55 | }
56 |
57 | public Identifier dynamicallyPutImage(NativeImage image) {
58 | String texPath = "gen/" + genCounter++;
59 | putImage("assets/connectedblocktextures/textures/" + texPath + ".png", image);
60 | return new Identifier("connectedblocktextures", texPath);
61 | }
62 |
63 | public Identifier dynamicallyPutTile(Tile tile) {
64 | String texPath = "gen/" + genCounter++;
65 | putTile("assets/connectedblocktextures/textures/" + texPath + ".png", tile);
66 | return new Identifier("connectedblocktextures", texPath);
67 | }
68 |
69 | public void putTile(String location, Tile tile) {
70 | if(tile.hasResource()) {
71 | alias(location, tile.getResource());
72 | } else {
73 | try {
74 | putImage(location, tile.getImage());
75 | } catch (IOException e) {
76 | //should be unreachable
77 | e.printStackTrace();
78 | }
79 | }
80 | }
81 |
82 | @Override
83 | public void close() {}
84 |
85 | @Override
86 | public InputStream openRoot(String fileName) throws IOException {
87 | byte[] data;
88 | Identifier aliasOf;
89 | if((data = resources.get(fileName)) != null) {
90 | return new ByteArrayInputStream(data);
91 | } else if((aliasOf = aliases.get(fileName)) != null) {
92 | return manager.getResource(aliasOf).getInputStream();
93 | }
94 | throw new IOException("generated resources pack has no data or alias for " + fileName);
95 | }
96 |
97 | @Override
98 | public InputStream open(ResourceType type, Identifier id) throws IOException {
99 | if(type == ResourceType.SERVER_DATA) throw new IOException("reading server data from connectedblocktextures client resource pack");
100 | return openRoot(type.getDirectory() + "/" + id.getNamespace() + "/" + id.getPath());
101 | }
102 |
103 | @Override
104 | public Collection findResources(ResourceType type, String namespace, String prefix, int maxDepth, Predicate pathFilter) {
105 | //maxdepth not implemented.
106 | if(type == ResourceType.SERVER_DATA) return Collections.emptyList();
107 | String start = "assets/" + namespace + "/" + prefix;
108 | return resources.keySet().stream().filter(s -> s.startsWith(start) && pathFilter.test(s)).map(CBTResourcePack::fromPath).collect(Collectors.toList());
109 | }
110 |
111 | @Override
112 | public boolean contains(ResourceType type, Identifier id) {
113 | String path = type.getDirectory() + "/" + id.getNamespace() + "/" + id.getPath();
114 | return resources.containsKey(path) || aliases.containsKey(path);
115 | }
116 |
117 | @Override
118 | public Set getNamespaces(ResourceType type) {
119 | return NAMESPACES;
120 | }
121 |
122 | @Override
123 | public T parseMetadata(ResourceMetadataReader metaReader) throws IOException {
124 | return null;
125 | }
126 |
127 | @Override
128 | public String getName() {
129 | return "Connected Block Textures generated resources";
130 | }
131 |
132 | private static Identifier fromPath(String path) {
133 | String[] split = path.split("/", 2);
134 | return new Identifier(split[0], split[1]);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/BaseSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.function.BiPredicate;
4 | import java.util.function.Predicate;
5 |
6 | import net.minecraft.block.BlockState;
7 | import net.minecraft.client.texture.Sprite;
8 | import net.minecraft.util.Identifier;
9 | import net.minecraft.util.math.BlockPos;
10 | import net.minecraft.util.math.Direction;
11 | import net.minecraft.world.BlockRenderView;
12 |
13 | import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
14 | import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
15 |
16 | import io.github.nuclearfarts.cbt.config.CTMConfig;
17 |
18 | public abstract class BaseSpriteProvider implements SpriteProvider {
19 | protected final Sprite[] connects; //different subclasses use this different ways
20 | protected final Predicate tileMatcher;
21 | protected final Predicate faceMatcher;
22 | protected final BiPredicate worldConditions;
23 |
24 | public BaseSpriteProvider(Sprite[] connects, CTMConfig config) {
25 | this.connects = connects;
26 | Predicate tileMatcher = config.getTileMatcher();
27 | this.tileMatcher = tileMatcher == null ? null : s -> tileMatcher.test(s.getId());
28 | faceMatcher = config.getFaceMatcher();
29 | worldConditions = config.getWorldConditions();
30 | }
31 |
32 | @Override
33 | public boolean affectsBlock(BlockRenderView view, BlockState state, BlockPos pos) {
34 | return worldConditions.test(view, pos);
35 | }
36 |
37 | @Override
38 | public boolean affectsDirection(Direction side) {
39 | return faceMatcher.test(side);
40 | }
41 |
42 | @Override
43 | public boolean affectsSprite(QuadView quad, SpriteFinder finder) {
44 | return tileMatcher == null ? true : tileMatcher.test(finder.find(quad, 0));
45 | }
46 |
47 | protected BlockState[][] getAll(BlockRenderView view, Direction upD, Direction leftD, BlockPos pos) {
48 | BlockState[][] result = new BlockState[3][3];
49 | BlockPos left = pos.offset(leftD);
50 | BlockPos right = pos.offset(leftD.getOpposite());
51 | result[0][0] = view.getBlockState(left.offset(upD));
52 | result[0][1] = view.getBlockState(left);
53 | result[0][2] = view.getBlockState(left.offset(upD.getOpposite()));
54 | result[1][0] = view.getBlockState(pos.offset(upD));
55 | result[1][1] = null;
56 | result[1][2] = view.getBlockState(pos.offset(upD.getOpposite()));
57 | result[2][0] = view.getBlockState(right.offset(upD));
58 | result[2][1] = view.getBlockState(right);
59 | result[2][2] = view.getBlockState(right.offset(upD.getOpposite()));
60 | return result;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/ConnectingSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.function.BiPredicate;
4 |
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.client.texture.Sprite;
7 | import net.minecraft.util.math.BlockPos;
8 | import net.minecraft.util.math.Direction;
9 | import net.minecraft.world.BlockRenderView;
10 |
11 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
12 |
13 | public abstract class ConnectingSpriteProvider extends BaseSpriteProvider {
14 | protected final BiPredicate connectionMatcher;
15 |
16 | public ConnectingSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
17 | super(connects, config);
18 | this.connectionMatcher = config.getConnectionMatcher();
19 | }
20 |
21 | protected boolean testUp(BlockRenderView view, Direction upD, BlockPos pos, BlockState thisState) {
22 | return connectionMatcher.test(thisState, view.getBlockState(pos.offset(upD)));
23 | }
24 |
25 | protected boolean testLeft(BlockRenderView view, Direction leftD, BlockPos pos, BlockState thisState) {
26 | return connectionMatcher.test(thisState, view.getBlockState(pos.offset(leftD)));
27 | }
28 |
29 | protected boolean testRight(BlockRenderView view, Direction leftD, BlockPos pos, BlockState thisState) {
30 | return connectionMatcher.test(thisState, view.getBlockState(pos.offset(leftD.getOpposite())));
31 | }
32 |
33 | protected boolean testDown(BlockRenderView view, Direction upD, BlockPos pos, BlockState thisState) {
34 | return connectionMatcher.test(thisState, view.getBlockState(pos.offset(upD.getOpposite())));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/FullCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
11 |
12 | public class FullCTMSpriteProvider extends ConnectingSpriteProvider {
13 |
14 | //i did not write this manually, i generated it. do not ask how. it's evil and involved Swing.
15 | public static final byte[] BITHACK_TO_CTM = {0, 0, 12, 12, 0, 0, 12, 12, 1, 1, 4, 13, 1, 1, 4, 13, 3, 3, 5, 5, 3, 3, 15, 15, 2, 2, 7, 31, 2, 2, 29, 14, 0, 0, 12, 12, 0, 0, 12, 12, 1, 1, 4, 13, 1, 1, 4, 13, 3, 3, 5, 5, 3, 3, 15, 15, 2, 2, 7, 31, 2, 2, 29, 14, 36, 36, 24, 24, 36, 36, 24, 24, 16, 16, 6, 28, 16, 16, 6, 28, 17, 17, 19, 19, 17, 17, 43, 43, 18, 18, 46, 9, 18, 18, 21, 22, 36, 36, 24, 24, 36, 36, 24, 24, 37, 37, 30, 25, 37, 37, 30, 25, 17, 17, 19, 19, 17, 17, 43, 43, 40, 40, 8, 23, 40, 40, 34, 45, 0, 0, 12, 12, 0, 0, 12, 12, 1, 1, 4, 13, 1, 1, 4, 13, 3, 3, 5, 5, 3, 3, 15, 15, 2, 2, 7, 31, 2, 2, 29, 14, 0, 0, 12, 12, 0, 0, 12, 12, 1, 1, 4, 13, 1, 1, 4, 13, 3, 3, 5, 5, 3, 3, 15, 15, 2, 2, 7, 31, 2, 2, 29, 14, 36, 36, 24, 24, 36, 36, 24, 24, 16, 16, 6, 28, 16, 16, 6, 28, 39, 39, 41, 41, 39, 39, 27, 27, 42, 42, 20, 35, 42, 42, 10, 44, 36, 36, 24, 24, 36, 36, 24, 24, 37, 37, 30, 25, 37, 37, 30, 25, 39, 39, 41, 41, 39, 39, 27, 27, 38, 38, 11, 33, 38, 38, 32, 26};
16 |
17 | public FullCTMSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
18 | super(connects, config);
19 | }
20 |
21 | @Override
22 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
23 | BlockState[][] blocks = getAll(view, upD, leftD, pos);
24 | return this.connects[BITHACK_TO_CTM[awfulBitHack(blocks, state)]];
25 | }
26 |
27 | private int awfulBitHack(BlockState[][] blocks, BlockState state) {
28 | blocks[1][1] = state;
29 | //System.out.println(Arrays.deepToString(blocks));
30 | int result = 0;
31 | int i = 0;
32 | for(int j = 0; j < blocks.length; j++) {
33 | for(int k = 0; k < blocks.length; k++) {
34 | if(j == 1 && k == 1) {
35 | continue;
36 | }
37 | if(connectionMatcher.test(state, blocks[blocks.length - (k + 1)][blocks.length - (j + 1)])) {
38 | result |= (1 << i);
39 | }
40 | i++;
41 | }
42 | }
43 | return result;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/HorizontalCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
11 |
12 | public class HorizontalCTMSpriteProvider extends ConnectingSpriteProvider {
13 |
14 | public HorizontalCTMSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
15 | super(connects, config);
16 | }
17 |
18 | @Override
19 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
20 | boolean left = testLeft(view, leftD, pos, state);
21 | boolean right = testRight(view, leftD, pos, state);
22 | if(left && right) {
23 | return connects[1];
24 | } else if(left && !right) {
25 | return connects[2];
26 | } else if(!left && right) {
27 | return connects[0];
28 | } else {
29 | return connects[3];
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/HorizontalVerticalCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
11 |
12 | public class HorizontalVerticalCTMSpriteProvider extends ConnectingSpriteProvider {
13 |
14 | public HorizontalVerticalCTMSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
15 | super(connects, config);
16 | }
17 |
18 | @Override
19 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
20 | boolean left = testLeft(view, leftD, pos, state);
21 | boolean right = testRight(view, leftD, pos, state);
22 | boolean down = testDown(view, upD, pos, state);
23 | boolean up = testUp(view, upD, pos, state);
24 | if(left && right) {
25 | return connects[1];
26 | } else if(left && !right) {
27 | return connects[2];
28 | } else if(!left && right) {
29 | return connects[0];
30 | } else if(down && up) {
31 | return connects[5];
32 | } else if(down && !up) {
33 | return connects[6];
34 | } else if(!down && up) {
35 | return connects[4];
36 | } else {
37 | return connects[3];
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/RandomSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.RandomCTMConfig;
11 |
12 | public class RandomSpriteProvider extends BaseSpriteProvider {
13 |
14 | public RandomSpriteProvider(Sprite[] connects, RandomCTMConfig config) {
15 | super(connects, config);
16 | }
17 |
18 | @Override
19 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
20 | return connects[random.nextInt(connects.length)];
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/RepeatingCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 |
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.client.texture.Sprite;
7 | import net.minecraft.util.math.BlockPos;
8 | import net.minecraft.util.math.Direction;
9 | import net.minecraft.world.BlockRenderView;
10 |
11 | import io.github.nuclearfarts.cbt.config.RepeatingCTMConfig;
12 | import io.github.nuclearfarts.cbt.util.CBTUtil;
13 |
14 | public class RepeatingCTMSpriteProvider extends BaseSpriteProvider {
15 | private final int width;
16 | private final int height;
17 |
18 | public RepeatingCTMSpriteProvider(Sprite[] connects, RepeatingCTMConfig config) {
19 | super(connects, config);
20 | width = config.getWidth();
21 | height = config.getHeight();
22 | }
23 |
24 | @Override
25 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
26 | int wPos = 0;
27 | int hPos = 0;
28 | switch(side.getAxis()) {
29 | case X:
30 | if(side.getOffsetX() < 0) {
31 | wPos = CBTUtil.actualMod(pos.getZ(), width);
32 | } else {
33 | wPos = CBTUtil.actualMod(pos.getZ() - 1, width);
34 | }
35 | hPos = CBTUtil.actualMod(-pos.getY(), height);
36 | break;
37 | case Z:
38 | if(side.getOffsetZ() < 0) {
39 | wPos = CBTUtil.actualMod(pos.getX() - 1, width);
40 | } else {
41 | wPos = CBTUtil.actualMod(pos.getX(), width);
42 | }
43 | hPos = CBTUtil.actualMod(-pos.getY(), height);
44 | break;
45 | case Y:
46 | wPos = CBTUtil.actualMod(pos.getX(), width);
47 | if(side.getOffsetY() < 0) {
48 | hPos = CBTUtil.actualMod(-pos.getZ() - 1, height);
49 | } else {
50 | hPos = CBTUtil.actualMod(pos.getZ(), height);
51 | }
52 | }
53 | return connects[wPos + hPos * width];
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/SpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 |
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.client.texture.Sprite;
7 | import net.minecraft.util.math.BlockPos;
8 | import net.minecraft.util.math.Direction;
9 | import net.minecraft.world.BlockRenderView;
10 |
11 | import net.fabricmc.fabric.api.renderer.v1.mesh.QuadView;
12 | import net.fabricmc.fabric.api.renderer.v1.model.SpriteFinder;
13 |
14 | public interface SpriteProvider {
15 | boolean affectsBlock(BlockRenderView view, BlockState state, BlockPos pos);
16 | boolean affectsDirection(Direction side);
17 | boolean affectsSprite(QuadView quad, SpriteFinder finder);
18 | Sprite getSpriteForSide(Direction side, Direction up, Direction left, BlockRenderView view, BlockState state, BlockPos pos, Random random);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/TopCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
11 |
12 | public class TopCTMSpriteProvider extends ConnectingSpriteProvider {
13 |
14 | public TopCTMSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
15 | super(connects, config);
16 | }
17 |
18 | @Override
19 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
20 | return testUp(view, upD, pos, state) ? connects[0] : null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/VerticalCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
11 |
12 | public class VerticalCTMSpriteProvider extends ConnectingSpriteProvider {
13 |
14 | public VerticalCTMSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
15 | super(connects, config);
16 | }
17 |
18 | @Override
19 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
20 | boolean down = testDown(view, upD, pos, state);
21 | boolean up = testUp(view, upD, pos, state);
22 | if(down && up) {
23 | return connects[1];
24 | } else if(down && !up) {
25 | return connects[2];
26 | } else if(!down && up) {
27 | return connects[0];
28 | } else {
29 | return connects[3];
30 | }
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/sprite/VerticalHorizontalCTMSpriteProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.sprite;
2 |
3 | import java.util.Random;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.client.texture.Sprite;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.Direction;
8 | import net.minecraft.world.BlockRenderView;
9 |
10 | import io.github.nuclearfarts.cbt.config.ConnectingCTMConfig;
11 |
12 | public class VerticalHorizontalCTMSpriteProvider extends ConnectingSpriteProvider {
13 |
14 | public VerticalHorizontalCTMSpriteProvider(Sprite[] connects, ConnectingCTMConfig> config) {
15 | super(connects, config);
16 | }
17 |
18 | @Override
19 | public Sprite getSpriteForSide(Direction side, Direction upD, Direction leftD, BlockRenderView view, BlockState state, BlockPos pos, Random random) {
20 | boolean left = testLeft(view, leftD, pos, state);
21 | boolean right = testRight(view, leftD, pos, state);
22 | boolean down = testDown(view, upD, pos, state);
23 | boolean up = testUp(view, upD, pos, state);
24 | if(down && up) {
25 | return connects[1];
26 | } else if(down && !up) {
27 | return connects[2];
28 | } else if(!down && up) {
29 | return connects[0];
30 | } else if(left && right) {
31 | return connects[5];
32 | } else if(left && !right) {
33 | return connects[6];
34 | } else if(!left && right) {
35 | return connects[4];
36 | } else {
37 | return connects[3];
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/ImageBackedTile.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile;
2 |
3 | import net.minecraft.client.texture.NativeImage;
4 | import net.minecraft.util.Identifier;
5 |
6 | public class ImageBackedTile implements Tile {
7 | private final NativeImage image;
8 |
9 | public ImageBackedTile(NativeImage image) {
10 | this.image = image;
11 | }
12 |
13 | @Override
14 | public boolean hasResource() {
15 | return false;
16 | }
17 |
18 | @Override
19 | public Identifier getResource() {
20 | throw new UnsupportedOperationException("Tile has no underlying resource!");
21 | }
22 |
23 | @Override
24 | public NativeImage getImage() {
25 | return image;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/ResourceBackedTile.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile;
2 |
3 | import java.io.IOException;
4 |
5 | import net.minecraft.client.texture.NativeImage;
6 | import net.minecraft.resource.ResourceManager;
7 | import net.minecraft.util.Identifier;
8 |
9 | public class ResourceBackedTile implements Tile {
10 | private final Identifier resource;
11 | private final ResourceManager resourceManager;
12 |
13 | public ResourceBackedTile(Identifier resource, ResourceManager resourceManager) {
14 | this.resource = resource;
15 | this.resourceManager = resourceManager;
16 | }
17 |
18 | @Override
19 | public boolean hasResource() {
20 | return true;
21 | }
22 |
23 | @Override
24 | public Identifier getResource() {
25 | return resource;
26 | }
27 |
28 | @Override
29 | public NativeImage getImage() throws IOException {
30 | return NativeImage.read(resourceManager.getResource(resource).getInputStream());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/Tile.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile;
2 |
3 | import java.io.IOException;
4 |
5 | import net.minecraft.client.texture.NativeImage;
6 | import net.minecraft.util.Identifier;
7 |
8 | public interface Tile {
9 | boolean hasResource();
10 | /**
11 | * @throws UnsupportedOperationException if this is a dynamically generated tile.
12 | * */
13 | Identifier getResource();
14 | NativeImage getImage() throws IOException;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/loader/BasicTileLoader.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.loader;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Properties;
6 | import java.util.regex.Pattern;
7 |
8 | import net.minecraft.resource.ResourceManager;
9 | import net.minecraft.util.Identifier;
10 |
11 | import io.github.nuclearfarts.cbt.tile.ResourceBackedTile;
12 | import io.github.nuclearfarts.cbt.tile.Tile;
13 | import io.github.nuclearfarts.cbt.util.CBTUtil;
14 |
15 | public class BasicTileLoader implements TileLoader {
16 | private static final Pattern RANGE_PATTERN = Pattern.compile("^\\d+-\\d+$");
17 |
18 | private final Tile[] tiles;
19 |
20 | public BasicTileLoader(Properties properties, Identifier location, ResourceManager manager) {
21 | this(properties.getProperty("tiles").split(" "), location, manager);
22 | }
23 |
24 | public BasicTileLoader(String[] tileDefs, Identifier location, ResourceManager manager) {
25 | List loadedTiles = new ArrayList<>();
26 | for(String tileDef : tileDefs) {
27 | if(RANGE_PATTERN.matcher(tileDef).find()) {
28 | String[] defSplit = tileDef.split("-");
29 | int min = Integer.parseInt(defSplit[0]);
30 | int max = Integer.parseInt(defSplit[1]);
31 | for(int i = min; i <= max; i++) {
32 | loadedTiles.add(new ResourceBackedTile(CBTUtil.appendId(location, "/" + i + ".png"), manager));
33 | }
34 | } else {
35 | if(tileDef.contains("/")) {
36 | if(tileDef.startsWith("~")) {
37 | tileDef = "optifine" + tileDef.substring(1);
38 | }
39 | loadedTiles.add(new ResourceBackedTile(new Identifier(CBTUtil.ensurePngExtension(tileDef)), manager));
40 | } else {
41 | loadedTiles.add(new ResourceBackedTile(CBTUtil.appendId(location, "/" + CBTUtil.ensurePngExtension(tileDef)), manager));
42 | }
43 | }
44 | }
45 | this.tiles = loadedTiles.toArray(new Tile[loadedTiles.size()]);
46 | }
47 |
48 | @Override
49 | public Tile[] getTiles() {
50 | return tiles;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/loader/DynamicBookshelfTileLoader.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.loader;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import net.minecraft.client.texture.NativeImage;
7 | import net.minecraft.resource.ResourceManager;
8 | import net.minecraft.util.Identifier;
9 |
10 | import io.github.nuclearfarts.cbt.tile.ImageBackedTile;
11 | import io.github.nuclearfarts.cbt.tile.ResourceBackedTile;
12 | import io.github.nuclearfarts.cbt.tile.Tile;
13 | import io.github.nuclearfarts.cbt.util.CBTUtil;
14 |
15 | public class DynamicBookshelfTileLoader implements TileLoader {
16 | Tile[] tiles = new Tile[4];
17 |
18 | public DynamicBookshelfTileLoader(Properties properties, Identifier location, ResourceManager manager) throws IOException {
19 | Identifier textureLocation = new Identifier(properties.getProperty("cbt_special_bookshelf_texture"));
20 | try(NativeImage bookshelf = NativeImage.read(manager.getResource(textureLocation).getInputStream())) {
21 | tiles[3] = new ResourceBackedTile(textureLocation, manager);
22 | NativeImage work;
23 | work = CBTUtil.copy(bookshelf);
24 | copyVLine(work, 4, 1, 6, 15, 9);
25 | copyVLine(work, 8, 9, 6, 15, 1);
26 | tiles[0] = new ImageBackedTile(work);
27 | work = CBTUtil.copy(work);
28 | copyVLine(work, 5, 1, 6, 0, 9);
29 | copyVLine(work, 9, 9, 6, 0, 1);
30 | tiles[1] = new ImageBackedTile(work);
31 | work = CBTUtil.copy(bookshelf);
32 | copyVLine(work, 5, 1, 6, 0, 9);
33 | copyVLine(work, 9, 9, 6, 0, 1);
34 | tiles[2] = new ImageBackedTile(work);
35 | }
36 | }
37 |
38 | @Override
39 | public Tile[] getTiles() {
40 | return tiles;
41 | }
42 |
43 | private void copyVLine(NativeImage on, int srcX, int srcY, int height, int dstX, int dstY) {
44 | for(int i = 0; i < height; i++) {
45 | on.setPixelColor(dstX, dstY + i, on.getPixelColor(srcX, srcY + i));
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/loader/DynamicGlassTileLoader.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.loader;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import net.minecraft.client.texture.NativeImage;
7 | import net.minecraft.resource.ResourceManager;
8 | import net.minecraft.util.Identifier;
9 |
10 | import io.github.nuclearfarts.cbt.tile.ImageBackedTile;
11 | import io.github.nuclearfarts.cbt.tile.Tile;
12 | import io.github.nuclearfarts.cbt.util.CBTUtil;
13 |
14 | public class DynamicGlassTileLoader implements TileLoader {
15 | private final Tile[] tiles = new Tile[5];
16 |
17 | public DynamicGlassTileLoader(Properties properties, Identifier location, ResourceManager manager) throws IOException {
18 | NativeImage glass = NativeImage.read(manager.getResource(new Identifier(properties.getProperty("cbt_special_glass_texture"))).getInputStream());
19 | int background = CBTUtil.toABGR(Integer.parseUnsignedInt(properties.getProperty("cbt_special_glass_background"), 16));
20 | tiles[0] = new ImageBackedTile(glass); //all-borders
21 |
22 | NativeImage work;
23 | work = CBTUtil.copy(glass);
24 | hLine(work, 0, 0, 16, background);
25 | hLine(work, 0, 15, 16, background);
26 | vLine(work, 0, 1, 14, background);
27 | vLine(work, 15, 1, 14, background);
28 | tiles[1] = new ImageBackedTile(work);
29 |
30 | work = CBTUtil.copy(glass);
31 | hLine(work, 1, 0, 14, background);
32 | hLine(work, 1, 15, 14, background);
33 | tiles[2] = new ImageBackedTile(work);
34 |
35 | work = CBTUtil.copy(glass);
36 | vLine(work, 0, 1, 14, background);
37 | vLine(work, 15, 1, 14, background);
38 | tiles[3] = new ImageBackedTile(work);
39 |
40 | work = CBTUtil.copy(glass);
41 | hLine(work, 1, 0, 14, background);
42 | hLine(work, 1, 15, 14, background);
43 | vLine(work, 0, 1, 14, background);
44 | vLine(work, 15, 1, 14, background);
45 | tiles[4] = new ImageBackedTile(work);
46 | }
47 |
48 | @Override
49 | public Tile[] getTiles() {
50 | return tiles;
51 | }
52 |
53 | private static void hLine(NativeImage image, int xStart, int y, int length, int color) {
54 | for(int x = 0; x < length; x++) {
55 | image.setPixelColor(x + xStart, y, color);
56 | }
57 | }
58 |
59 | private static void vLine(NativeImage image, int x, int yStart, int length, int color) {
60 | for(int y = 0; y < length; y++) {
61 | image.setPixelColor(x, y + yStart, color);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/loader/DynamicSandstoneTileLoader.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.loader;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import net.minecraft.client.texture.NativeImage;
7 | import net.minecraft.resource.ResourceManager;
8 | import net.minecraft.util.Identifier;
9 |
10 | import io.github.nuclearfarts.cbt.tile.ImageBackedTile;
11 | import io.github.nuclearfarts.cbt.tile.Tile;
12 |
13 | public class DynamicSandstoneTileLoader implements TileLoader {
14 | private Tile[] tiles = new Tile[1];
15 |
16 | public DynamicSandstoneTileLoader(Properties properties, Identifier location, ResourceManager manager) throws IOException {
17 | NativeImage sandstone = NativeImage.read(manager.getResource(new Identifier(properties.getProperty("cbt_special_sandstone_texture"))).getInputStream());
18 | for(int x = 0; x < 16; x++) {
19 | for(int y = 0; y < 3; y++) {
20 | sandstone.setPixelColor(15 - x, y, sandstone.getPixelColor(x, y + 12));
21 | }
22 | }
23 | tiles[0] = new ImageBackedTile(sandstone);
24 | }
25 |
26 | @Override
27 | public Tile[] getTiles() {
28 | return tiles;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/loader/TileLoader.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.loader;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import net.minecraft.resource.ResourceManager;
7 | import net.minecraft.util.Identifier;
8 |
9 | import io.github.nuclearfarts.cbt.tile.Tile;
10 | import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
11 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
12 |
13 | public interface TileLoader {
14 | Tile[] getTiles();
15 |
16 | static void registerSpecialTileLoader(String name, Loader> loader) {
17 | PrivateConstants.SPECIAL_TILE_LOADERS.put(name, loader);
18 | }
19 |
20 | static TileLoader load(Properties properties, Identifier location, ResourceManager manager) throws IOException {
21 | return PrivateConstants.SPECIAL_TILE_LOADERS.get(properties.getProperty("tiles")).load(properties, location, manager);
22 | }
23 |
24 | public interface Loader {
25 | T load(Properties properties, Identifier location, ResourceManager manager) throws IOException;
26 | }
27 |
28 | public static final class PrivateConstants {
29 | private PrivateConstants() { }
30 | private static final Object2ObjectMap> SPECIAL_TILE_LOADERS = new Object2ObjectOpenHashMap<>();
31 |
32 | static {
33 | SPECIAL_TILE_LOADERS.defaultReturnValue(BasicTileLoader::new);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/provider/BasicTileProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.provider;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.function.Function;
6 |
7 | import net.minecraft.client.texture.Sprite;
8 | import net.minecraft.client.texture.SpriteAtlasTexture;
9 | import net.minecraft.client.util.SpriteIdentifier;
10 |
11 | import io.github.nuclearfarts.cbt.ConnectedBlockTextures;
12 | import io.github.nuclearfarts.cbt.tile.Tile;
13 |
14 | public class BasicTileProvider implements TileProvider {
15 | private final List ids = new ArrayList<>();
16 |
17 | public BasicTileProvider(Tile[] tiles) {
18 | for(Tile tile : tiles) {
19 | ids.add(new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, ConnectedBlockTextures.resourcePack.dynamicallyPutTile(tile)));
20 | }
21 | }
22 |
23 | @Override
24 | public List getIdsToLoad() {
25 | //System.out.println(ids);
26 | return ids;
27 | }
28 |
29 | @Override
30 | public Sprite[] load(Function textureGetter) {
31 | Sprite[] sprites = new Sprite[ids.size()];
32 | for(int i = 0; i < ids.size(); i++) {
33 | sprites[i] = textureGetter.apply(ids.get(i));
34 | }
35 | return sprites;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/provider/CompactTileProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.provider;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.function.Function;
7 |
8 | import net.minecraft.client.texture.NativeImage;
9 | import net.minecraft.client.texture.Sprite;
10 | import net.minecraft.client.texture.SpriteAtlasTexture;
11 | import net.minecraft.client.util.SpriteIdentifier;
12 | import io.github.nuclearfarts.cbt.ConnectedBlockTextures;
13 | import io.github.nuclearfarts.cbt.tile.Tile;
14 |
15 | public class CompactTileProvider implements TileProvider {
16 | private final List spriteIds = new ArrayList<>();
17 |
18 | public CompactTileProvider(Tile[] origTiles) throws IOException {
19 | NativeImage[] origImages = new NativeImage[5];
20 | for(int i = 0; i < 5; i++) {
21 | origImages[i] = origTiles[i].getImage();
22 | }
23 | for(int i = 0; i <= 46; i++) {
24 | NativeImage tile = new NativeImage(origImages[0].getWidth(), origImages[0].getHeight(), true);
25 | short bithack = ConnectedBlockTextures.CTM_TO_IDEALIZED_BITHACK[i];
26 | //Up-left. up-left-upleft
27 |
28 | if((bithack & 0b1010000) == 0) {
29 | //draw both.
30 | blitQuarter(0, 0, origImages[0], tile);
31 | } else if((bithack & 0b10000) == 0) {
32 | //draw left
33 | blitQuarter(0, 0, origImages[2], tile);
34 | } else if((bithack & 0b1000000) == 0) {
35 | //draw up
36 | blitQuarter(0, 0, origImages[3], tile);
37 | } else if((bithack & 0b10000000) == 0) {
38 | //draw corner
39 | blitQuarter(0, 0, origImages[4], tile);
40 | } else {
41 | //empty
42 | blitQuarter(0, 0, origImages[1], tile);
43 | }
44 |
45 | //up-right.
46 | if((bithack & 0b1001000) == 0) {
47 | //draw both.
48 | blitQuarter(1, 0, origImages[0], tile);
49 | } else if((bithack & 0b1000) == 0) {
50 | //draw right
51 | blitQuarter(1, 0, origImages[2], tile);
52 | } else if((bithack & 0b1000000) == 0) {
53 | //draw up
54 | blitQuarter(1, 0, origImages[3], tile);
55 | } else if((bithack & 0b100000) == 0) {
56 | //draw corner
57 | blitQuarter(1, 0, origImages[4], tile);
58 | } else {
59 | //empty
60 | blitQuarter(1, 0, origImages[1], tile);
61 | }
62 |
63 | //down-left
64 | if((bithack & 0b10010) == 0) {
65 | //draw both.
66 | blitQuarter(0, 1, origImages[0], tile);
67 | } else if((bithack & 0b10000) == 0) {
68 | //draw left
69 | blitQuarter(0, 1, origImages[2], tile);
70 | } else if((bithack & 0b10) == 0) {
71 | //draw down
72 | blitQuarter(0, 1, origImages[3], tile);
73 | } else if((bithack & 0b100) == 0) {
74 | //draw corner
75 | blitQuarter(0, 1, origImages[4], tile);
76 | } else {
77 | //empty
78 | blitQuarter(0, 1, origImages[1], tile);
79 | }
80 |
81 | //down-right
82 | if((bithack & 0b1010) == 0) {
83 | //draw both.
84 | blitQuarter(1, 1, origImages[0], tile);
85 | } else if((bithack & 0b1000) == 0) {
86 | //draw right
87 | blitQuarter(1, 1, origImages[2], tile);
88 | } else if((bithack & 0b10) == 0) {
89 | //draw down
90 | blitQuarter(1, 1, origImages[3], tile);
91 | } else if((bithack & 0b1) == 0) {
92 | //draw corner
93 | blitQuarter(1, 1, origImages[4], tile);
94 | } else {
95 | //empty
96 | blitQuarter(1, 1, origImages[1], tile);
97 | }
98 |
99 | spriteIds.add(new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, ConnectedBlockTextures.resourcePack.dynamicallyPutImage(tile)));
100 | }
101 | }
102 |
103 | private static void blitQuarter(int offsetX, int offsetY, NativeImage src, NativeImage dst) {
104 | int w = src.getWidth() / 2;
105 | int h = src.getHeight() / 2;
106 | int x = w * offsetX;
107 | int y = h * offsetY;
108 | for(int i = x; i < w + x; i++) {
109 | for(int j = y; j < h + y; j++) {
110 | dst.setPixelColor(i, j, src.getPixelColor(i, j));
111 | }
112 | }
113 | }
114 |
115 | @Override
116 | public List getIdsToLoad() {
117 | return spriteIds;
118 | }
119 |
120 | @Override
121 | public Sprite[] load(Function textureGetter) {
122 | Sprite[] sprites = new Sprite[spriteIds.size()];
123 | for(int i = 0; i < sprites.length; i++) {
124 | sprites[i] = textureGetter.apply(spriteIds.get(i));
125 | }
126 | return sprites;
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/tile/provider/TileProvider.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.tile.provider;
2 |
3 | import java.io.IOException;
4 | import java.util.List;
5 | import java.util.Properties;
6 | import java.util.function.Function;
7 |
8 | import net.minecraft.client.texture.Sprite;
9 | import net.minecraft.client.util.SpriteIdentifier;
10 | import net.minecraft.resource.ResourceManager;
11 | import net.minecraft.util.Identifier;
12 |
13 | import io.github.nuclearfarts.cbt.tile.Tile;
14 | import io.github.nuclearfarts.cbt.tile.loader.TileLoader;
15 | import io.github.nuclearfarts.cbt.util.CBTUtil;
16 | import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
17 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
18 |
19 | public interface TileProvider {
20 | List getIdsToLoad();
21 | Sprite[] load(Function textureGetter);
22 |
23 | static TileProvider load(Properties properties, Identifier location, ResourceManager manager) throws IOException {
24 | return PrivateConstants.TILE_PROVIDERS.get(properties.getProperty("method")).create(TileLoader.load(properties, location, manager).getTiles());
25 | }
26 |
27 | static TileProvider load(Identifier propertiesLocation, ResourceManager manager) throws IOException {
28 | Properties properties = new Properties();
29 | properties.load(manager.getResource(propertiesLocation).getInputStream());
30 | return load(properties, CBTUtil.directoryOf(propertiesLocation), manager);
31 | }
32 |
33 | static void registerTileProviderFactory(String method, Factory> loader) {
34 | PrivateConstants.TILE_PROVIDERS.put(method, loader);
35 | }
36 |
37 | @FunctionalInterface
38 | public interface Factory {
39 | T create(Tile[] tiles) throws IOException;
40 | }
41 |
42 | public static final class PrivateConstants {
43 | private PrivateConstants() { }
44 | private static final Object2ObjectMap> TILE_PROVIDERS = new Object2ObjectOpenHashMap<>();
45 |
46 | static {
47 | TILE_PROVIDERS.defaultReturnValue(BasicTileProvider::new);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/util/CBTUtil.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.util;
2 |
3 | import java.util.Collection;
4 | import java.util.function.Function;
5 | import java.util.function.IntPredicate;
6 | import java.util.function.Predicate;
7 |
8 | import net.minecraft.client.texture.NativeImage;
9 | import net.minecraft.client.util.ModelIdentifier;
10 | import net.minecraft.util.Identifier;
11 |
12 | import io.github.nuclearfarts.cbt.util.function.ThrowingPredicate;
13 |
14 | public class CBTUtil {
15 |
16 | public static Identifier appendId(Identifier path, String str) {
17 | return new Identifier(path.getNamespace(), path.getPath() + str);
18 | }
19 |
20 | public static Identifier prependId(Identifier path, String str) {
21 | return new Identifier(path.getNamespace(), str + path.getPath());
22 | }
23 |
24 | public static String ensurePngExtension(String string) {
25 | if(!string.endsWith(".png")) {
26 | return string + ".png";
27 | }
28 | return string;
29 | }
30 |
31 | //time to avoid streams!
32 | public static boolean mapAnyMatch(Collection extends T> collection, Function super T, ? extends U> mapper, Predicate predicate) {
33 | for(T t : collection) {
34 | if(predicate.test(mapper.apply(t))) {
35 | return true;
36 | }
37 | }
38 | return false;
39 | }
40 |
41 | public static boolean allMatchThrowable(Collection extends T> collection, ThrowingPredicate predicate) throws U {
42 | for(T t : collection) {
43 | if(!predicate.test(t)) {
44 | return false;
45 | }
46 | }
47 | return true;
48 | }
49 |
50 | public static boolean satisfiesAny(Collection predicates, int i) {
51 | for(IntPredicate p : predicates) {
52 | if(p.test(i)) {
53 | return true;
54 | }
55 | }
56 | return false;
57 | }
58 |
59 | public static Identifier directoryOf(Identifier id) {
60 | String path = id.getPath();
61 | return new Identifier(id.getNamespace(), path.substring(0, path.lastIndexOf('/')));
62 | }
63 |
64 | public static String fileNameOf(Identifier id) {
65 | String path = id.getPath();
66 | return path.substring(path.lastIndexOf('/'), path.length());
67 | }
68 |
69 | public static Identifier stripBlankVariants(ModelIdentifier modelId) {
70 | if(modelId.getVariant().equals("")) {
71 | return new Identifier(modelId.getNamespace(), modelId.getPath());
72 | }
73 | return modelId;
74 | }
75 |
76 | public static Identifier stripVariants(ModelIdentifier modelId) {
77 | return new Identifier(modelId.getNamespace(), modelId.getPath());
78 | }
79 |
80 | public static NativeImage copy(NativeImage image) {
81 | NativeImage newImage = new NativeImage(image.getFormat(), image.getWidth(), image.getHeight(), true);
82 | newImage.copyFrom(image);
83 | return newImage;
84 | }
85 |
86 | public static int actualMod(int in, int modulo) {
87 | int mod = in % modulo;
88 | if(mod < 0) {
89 | mod += modulo;
90 | }
91 | return mod;
92 | }
93 |
94 | public static int toABGR(int argb) {
95 | return ((argb >> 24) << 24) | // Alpha
96 | ((argb >> 16) & 0xFF) | // Red -> Blue
97 | ((argb >> 8) & 0xFF) << 8 | // Green
98 | ((argb) & 0xFF) << 16; // Blue -> Red
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/util/CursedBiomeThing.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.util;
2 |
3 | import net.minecraft.util.math.BlockPos;
4 | import net.minecraft.world.BlockRenderView;
5 | import net.minecraft.world.biome.Biome;
6 | import net.minecraft.world.level.ColorResolver;
7 |
8 | public class CursedBiomeThing implements ColorResolver {
9 | private static final SimplePool POOL = new SimplePool(CursedBiomeThing::new);
10 |
11 | Biome result;
12 |
13 | private CursedBiomeThing() { }
14 |
15 | public static Biome getBiome(BlockRenderView view, BlockPos pos) {
16 | CursedBiomeThing cursed = POOL.get();
17 | view.getColor(pos, cursed);
18 | Biome result = cursed.result;
19 | POOL.readd(cursed);
20 | return result;
21 | }
22 |
23 | @Override
24 | public int getColor(Biome biome, double d, double e) {
25 | result = biome;
26 | return 0;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/util/SimplePool.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.util;
2 |
3 | import java.util.Queue;
4 | import java.util.concurrent.ConcurrentLinkedQueue;
5 | import java.util.function.Consumer;
6 | import java.util.function.Supplier;
7 |
8 | public class SimplePool {
9 | private final Queue queue = new ConcurrentLinkedQueue<>();
10 | private final Supplier supplier;
11 | private final Consumer resetter;
12 |
13 | public SimplePool(Supplier supplier, Consumer resetter) {
14 | this.supplier = supplier;
15 | this.resetter = resetter;
16 | }
17 |
18 | public SimplePool(Supplier supplier) {
19 | this(supplier, t -> {});
20 | }
21 |
22 | public T get() {
23 | T obj;
24 | if((obj = queue.poll()) == null) {
25 | return supplier.get();
26 | } else {
27 | resetter.accept(obj);
28 | return obj;
29 | }
30 | }
31 |
32 | public void readd(T t) {
33 | queue.add(t);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/util/VoidSet.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.util;
2 |
3 | import java.util.Collection;
4 | import java.util.Iterator;
5 | import java.util.Set;
6 |
7 | public class VoidSet implements Set {
8 | private static final VoidSet> INSTANCE = new VoidSet<>();
9 |
10 | @SuppressWarnings("unchecked")
11 | public static VoidSet get() {
12 | return (VoidSet) INSTANCE;
13 | }
14 |
15 | private VoidSet() { }
16 |
17 | @Override
18 | public int size() {
19 | return 0;
20 | }
21 |
22 | @Override
23 | public boolean isEmpty() {
24 | return true;
25 | }
26 |
27 | @Override
28 | public boolean contains(Object o) {
29 | return false;
30 | }
31 |
32 | @Override
33 | public Iterator iterator() {
34 | return VoidIterator.get();
35 | }
36 |
37 | @Override
38 | public Object[] toArray() {
39 | return new Object[0];
40 | }
41 |
42 | @Override
43 | public T[] toArray(T[] a) {
44 | return a;
45 | }
46 |
47 | @Override
48 | public boolean add(E e) {
49 | return false;
50 | }
51 |
52 | @Override
53 | public boolean remove(Object o) {
54 | return false;
55 | }
56 |
57 | @Override
58 | public boolean containsAll(Collection> c) {
59 | return false;
60 | }
61 |
62 | @Override
63 | public boolean addAll(Collection extends E> c) {
64 | return false;
65 | }
66 |
67 | @Override
68 | public boolean retainAll(Collection> c) {
69 | return false;
70 | }
71 |
72 | @Override
73 | public boolean removeAll(Collection> c) {
74 | return false;
75 | }
76 |
77 | @Override
78 | public void clear() { }
79 |
80 | private static class VoidIterator implements Iterator {
81 | private static final VoidIterator> INSTANCE = new VoidIterator<>();
82 |
83 | @SuppressWarnings("unchecked")
84 | public static VoidIterator get() {
85 | return (VoidIterator) INSTANCE;
86 | }
87 |
88 | @Override
89 | public boolean hasNext() {
90 | return false;
91 | }
92 |
93 | @Override
94 | public E next() {
95 | return null;
96 | }
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/util/function/MutableCachingSupplier.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.util.function;
2 |
3 | import java.util.function.Supplier;
4 |
5 | public class MutableCachingSupplier implements Supplier {
6 | private Supplier supplier;
7 | private T cache;
8 |
9 | public void set(Supplier newSupplier) {
10 | supplier = newSupplier;
11 | cache = null;
12 | }
13 |
14 | @Override
15 | public T get() {
16 | return cache == null ? cache = supplier.get() : cache;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/io/github/nuclearfarts/cbt/util/function/ThrowingPredicate.java:
--------------------------------------------------------------------------------
1 | package io.github.nuclearfarts.cbt.util.function;
2 |
3 | public interface ThrowingPredicate {
4 | boolean test(T t) throws U;
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/resources/assets/connected_block_textures/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HyperCubeMC/connected-block-textures/5e06943fdf444456b54056bc197aef54f4863f30/src/main/resources/assets/connected_block_textures/icon.png
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/models/block/template_glass_pane_post.json:
--------------------------------------------------------------------------------
1 | {
2 | "ambientocclusion": false,
3 | "textures": {
4 | "particle": "#pane"
5 | },
6 | "elements": [
7 | { "from": [ 7, 0, 7 ],
8 | "to": [ 9, 16, 9 ],
9 | "faces": {
10 | "down": { "uv": [ 7, 7, 9, 9 ], "texture": "#edge", "cullface": "down" },
11 | "up": { "uv": [ 7, 7, 9, 9 ], "texture": "#edge", "cullface": "up" }
12 | }
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/models/block/template_glass_pane_side.json:
--------------------------------------------------------------------------------
1 | {
2 | "ambientocclusion": false,
3 | "textures": {
4 | "particle": "#pane"
5 | },
6 | "elements": [
7 | { "from": [ 7, 0, 0 ],
8 | "to": [ 9, 16, 7 ],
9 | "faces": {
10 | "down": { "uv": [ 7, 0, 9, 7 ], "texture": "#edge", "cullface": "down" },
11 | "up": { "uv": [ 7, 0, 9, 7 ], "texture": "#edge", "cullface": "up" },
12 | "north": { "uv": [ 7, 0, 9, 16 ], "texture": "#edge", "cullface": "north" },
13 | "west": { "uv": [ 0, 0, 7, 16 ], "texture": "#pane" },
14 | "east": { "uv": [ 9, 0, 16, 16 ], "texture": "#pane" }
15 | }
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/models/block/template_glass_pane_side_alt.json:
--------------------------------------------------------------------------------
1 | {
2 | "ambientocclusion": false,
3 | "textures": {
4 | "particle": "#pane"
5 | },
6 | "elements": [
7 | { "from": [ 7, 0, 9 ],
8 | "to": [ 9, 16, 16 ],
9 | "faces": {
10 | "down": { "uv": [ 7, 0, 9, 7 ], "texture": "#edge", "cullface": "down" },
11 | "up": { "uv": [ 7, 0, 9, 7 ], "texture": "#edge", "cullface": "up" },
12 | "south": { "uv": [ 7, 0, 9, 16 ], "texture": "#edge", "cullface": "south" },
13 | "west": { "uv": [ 9, 0, 16, 16 ], "texture": "#pane" },
14 | "east": { "uv": [ 0, 0, 7, 16 ], "texture": "#pane" }
15 | }
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/bookshelf/bookshelf.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=bookshelf
2 | connect=block
3 | faces=sides
4 | method=horizontal
5 | tiles=$CBT_SPECIAL_DYNAMIC_BOOKSHELF
6 | cbt_special_bookshelf_texture=minecraft:textures/block/bookshelf.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/black_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=black_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66191919
6 | cbt_special_glass_texture=minecraft:textures/block/black_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/black_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=black_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66191919
7 | cbt_special_glass_texture=minecraft:textures/block/black_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/blue_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=blue_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66334CB2
6 | cbt_special_glass_texture=minecraft:textures/block/blue_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/blue_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=blue_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66334CB2
7 | cbt_special_glass_texture=minecraft:textures/block/blue_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/brown_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=brown_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66664C33
6 | cbt_special_glass_texture=minecraft:textures/block/brown_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/brown_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=brown_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66664C33
7 | cbt_special_glass_texture=minecraft:textures/block/brown_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/cyan_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=cyan_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=664C7F99
6 | cbt_special_glass_texture=minecraft:textures/block/cyan_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/cyan_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=cyan_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=664C7F99
7 | cbt_special_glass_texture=minecraft:textures/block/cyan_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=00000000
6 | cbt_special_glass_texture=minecraft:textures/block/glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=00000000
7 | cbt_special_glass_texture=minecraft:textures/block/glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/gray_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=gray_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=664C4C4C
6 | cbt_special_glass_texture=minecraft:textures/block/gray_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/gray_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=gray_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=664C4C4C
7 | cbt_special_glass_texture=minecraft:textures/block/gray_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/green_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=green_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66667F33
6 | cbt_special_glass_texture=minecraft:textures/block/green_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/green_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=green_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66667F33
7 | cbt_special_glass_texture=minecraft:textures/block/green_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/light_blue_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=light_blue_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=666699D8
6 | cbt_special_glass_texture=minecraft:textures/block/light_blue_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/light_blue_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=light_blue_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=666699D8
7 | cbt_special_glass_texture=minecraft:textures/block/light_blue_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/light_gray_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=light_gray_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66999999
6 | cbt_special_glass_texture=minecraft:textures/block/light_gray_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/light_gray_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=light_gray_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66999999
7 | cbt_special_glass_texture=minecraft:textures/block/light_gray_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/lime_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=lime_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=667FCC19
6 | cbt_special_glass_texture=minecraft:textures/block/lime_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/lime_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=lime_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=667FCC19
7 | cbt_special_glass_texture=minecraft:textures/block/lime_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/magenta_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=magenta_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66B24CD8
6 | cbt_special_glass_texture=minecraft:textures/block/magenta_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/magenta_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=magenta_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66B24CD8
7 | cbt_special_glass_texture=minecraft:textures/block/magenta_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/orange_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=orange_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66D87F33
6 | cbt_special_glass_texture=minecraft:textures/block/orange_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/orange_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=orange_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66D87F33
7 | cbt_special_glass_texture=minecraft:textures/block/orange_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/pink_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=pink_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66F27FA5
6 | cbt_special_glass_texture=minecraft:textures/block/pink_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/pink_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=pink_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66F27FA5
7 | cbt_special_glass_texture=minecraft:textures/block/pink_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/purple_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=purple_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=667F3FB2
6 | cbt_special_glass_texture=minecraft:textures/block/purple_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/purple_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=purple_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=667F3FB2
7 | cbt_special_glass_texture=minecraft:textures/block/purple_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/red_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=red_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=80993333
6 | cbt_special_glass_texture=minecraft:textures/block/red_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Default
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/red_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=red_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=80993333
7 | cbt_special_glass_texture=minecraft:textures/block/red_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Default
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/tinted_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=tinted_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=6E272527
6 | cbt_special_glass_texture=minecraft:textures/block/tinted_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/white_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=white_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66FFFFFF
6 | cbt_special_glass_texture=minecraft:textures/block/white_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/white_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=white_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66FFFFFF
7 | cbt_special_glass_texture=minecraft:textures/block/white_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/yellow_stained_glass.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=yellow_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66E5E533
6 | cbt_special_glass_texture=minecraft:textures/block/yellow_stained_glass.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/glass/yellow_stained_glass_pane.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=yellow_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66E5E533
7 | cbt_special_glass_texture=minecraft:textures/block/yellow_stained_glass.png
8 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/sandstone/red_sandstone.properties:
--------------------------------------------------------------------------------
1 | matchTiles=red_sandstone
2 | connect=tile
3 | method=top
4 | faces=sides
5 | tiles=$CBT_SPECIAL_DYNAMIC_SANDSTONE
6 | cbt_special_sandstone_texture=minecraft:textures/block/red_sandstone.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/assets/minecraft/optifine/ctm/sandstone/sandstone.properties:
--------------------------------------------------------------------------------
1 | matchTiles=sandstone
2 | connect=tile
3 | method=top
4 | faces=sides
5 | tiles=$CBT_SPECIAL_DYNAMIC_SANDSTONE
6 | cbt_special_sandstone_texture=minecraft:textures/block/sandstone.png
7 | cbt_special_change_pack_if_loaded=Programmer Art
--------------------------------------------------------------------------------
/src/main/resources/connected_block_textures.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "package": "io.github.nuclearfarts.cbt.mixin",
4 | "compatibilityLevel": "JAVA_8",
5 | "client": [
6 | "ModelLoaderMixin",
7 | "ReloadableResourceManagerImplMixin",
8 | "ClientWorldMixin",
9 | "IdentifierMixin",
10 | "NativeImageAccessor"
11 | ],
12 | "injectors": {
13 | "defaultRequire": 1
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "connected_block_textures",
4 | "version": "${version}",
5 |
6 | "name": "Connected Block Textures",
7 | "description": "Support for MCPatcher/Optifine-format connected textures.",
8 | "authors": [
9 | "NuclearFarts"
10 | ],
11 | "contact": {
12 | "sources": "https://github.com/Nuclearfarts/connected-block-textures"
13 | },
14 |
15 | "license": "LGPLv3",
16 | "icon": "assets/connected_block_textures/icon.png",
17 | "environment": "client",
18 | "entrypoints": {
19 | "main": [
20 | "io.github.nuclearfarts.cbt.ConnectedBlockTextures"
21 | ]
22 | },
23 | "mixins": [
24 | "connected_block_textures.mixins.json"
25 | ],
26 |
27 | "depends": {
28 | "fabricloader": ">=0.4.0",
29 | "fabric": "*"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/resources/programmer_art/assets/minecraft/optifine/ctm/glass/red_stained_glass_pane_programmer.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=red_stained_glass_pane
2 | faces=sides
3 | connect=block
4 | method=ctm_compact
5 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
6 | cbt_special_glass_background=66993333
7 | cbt_special_glass_texture=minecraft:textures/block/red_stained_glass.png
--------------------------------------------------------------------------------
/src/main/resources/programmer_art/assets/minecraft/optifine/ctm/glass/red_stained_glass_programmer.properties:
--------------------------------------------------------------------------------
1 | matchBlocks=red_stained_glass
2 | connect=block
3 | method=ctm_compact
4 | tiles=$CBT_SPECIAL_DYNAMIC_GLASS
5 | cbt_special_glass_background=66993333
6 | cbt_special_glass_texture=minecraft:textures/block/red_stained_glass.png
--------------------------------------------------------------------------------