Showing preview only (351K chars total). Download the full file or copy to clipboard to get everything.
Repository: FoundationGames/EnhancedBlockEntities
Branch: 1.21.4
Commit: b0b202a18a1a
Files: 145
Total size: 300.9 KB
Directory structure:
gitextract_2wd5jt0b/
├── .github/
│ └── workflows/
│ └── build.yml
├── .gitignore
├── LICENSE.txt
├── README.md
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src/
└── main/
├── java/
│ └── foundationgames/
│ └── enhancedblockentities/
│ ├── EBESetup.java
│ ├── EnhancedBlockEntities.java
│ ├── EnhancedBlockEntityRegistry.java
│ ├── ReloadType.java
│ ├── client/
│ │ ├── model/
│ │ │ ├── DynamicBakedModel.java
│ │ │ ├── DynamicModelEffects.java
│ │ │ ├── DynamicModelProvidingPlugin.java
│ │ │ ├── DynamicUnbakedModel.java
│ │ │ ├── ModelIdentifiers.java
│ │ │ ├── ModelSelector.java
│ │ │ ├── item/
│ │ │ │ └── EBEIsChristmasProperty.java
│ │ │ └── misc/
│ │ │ └── DecoratedPotModelSelector.java
│ │ ├── render/
│ │ │ ├── BlockEntityRenderCondition.java
│ │ │ ├── BlockEntityRendererOverride.java
│ │ │ ├── SignRenderManager.java
│ │ │ └── entity/
│ │ │ ├── BellBlockEntityRendererOverride.java
│ │ │ ├── ChestBlockEntityRendererOverride.java
│ │ │ ├── DecoratedPotBlockEntityRendererOverride.java
│ │ │ ├── ShulkerBoxBlockEntityRendererOverride.java
│ │ │ └── SignBlockEntityRendererOverride.java
│ │ └── resource/
│ │ ├── AtlasResourceBuilder.java
│ │ ├── EBEPack.java
│ │ └── template/
│ │ ├── TemplateDefinitions.java
│ │ ├── TemplateLoader.java
│ │ └── TemplateProvider.java
│ ├── config/
│ │ ├── EBEConfig.java
│ │ └── gui/
│ │ ├── EBEModMenuPlugin.java
│ │ ├── option/
│ │ │ ├── ConfigButtonOption.java
│ │ │ ├── EBEOption.java
│ │ │ └── TextPalette.java
│ │ ├── screen/
│ │ │ └── EBEConfigScreen.java
│ │ └── widget/
│ │ ├── SectionTextWidget.java
│ │ └── WidgetRowListWidget.java
│ ├── event/
│ │ └── EBEEvents.java
│ ├── mixin/
│ │ ├── AbstractBlockStateMixin.java
│ │ ├── AbstractSignBlockEntityRenderAccessor.java
│ │ ├── BellBlockEntityMixin.java
│ │ ├── BlockEntityRenderDispatcherMixin.java
│ │ ├── BuiltChunkMixin.java
│ │ ├── ChestBlockEntityMixin.java
│ │ ├── DecoratedPotBlockEntityMixin.java
│ │ ├── EnderChestBlockEntityMixin.java
│ │ ├── LifecycledResourceManagerImplMixin.java
│ │ ├── MinecraftClientMixin.java
│ │ ├── ShulkerBoxBlockEntityMixin.java
│ │ ├── SignEditScreenMixin.java
│ │ ├── VideoOptionsScreenMixin.java
│ │ ├── WorldRendererMixin.java
│ │ └── compat/
│ │ └── sodium/
│ │ ├── RenderSectionManagerMixin.java
│ │ └── RenderSectionMixin.java
│ └── util/
│ ├── ConvUtil.java
│ ├── DateUtil.java
│ ├── EBEUtil.java
│ ├── ExecutableRunnableHashSet.java
│ ├── GuiUtil.java
│ ├── ResourceUtil.java
│ ├── WorldUtil.java
│ ├── duck/
│ │ ├── AppearanceStateHolder.java
│ │ └── ChunkRebuildTaskAccess.java
│ └── hacks/
│ ├── ExperimentalSetup.java
│ ├── ResourceHacks.java
│ └── TextureHacks.java
└── resources/
├── assets/
│ ├── enhancedblockentities/
│ │ └── lang/
│ │ ├── en_us.json
│ │ ├── ru_ru.json
│ │ └── zh_cn.json
│ └── minecraft/
│ └── models/
│ ├── block/
│ │ ├── bell_between_walls_with_bell.json
│ │ ├── bell_body.json
│ │ ├── bell_ceiling_with_bell.json
│ │ ├── bell_floor_with_bell.json
│ │ ├── bell_wall_with_bell.json
│ │ ├── decorated_pot_base.json
│ │ ├── decorated_pot_shaking.json
│ │ ├── template_bed_foot.json
│ │ ├── template_bed_foot_ao.json
│ │ ├── template_bed_foot_offset.json
│ │ ├── template_bed_head.json
│ │ ├── template_bed_head_ao.json
│ │ ├── template_chest_center.json
│ │ ├── template_chest_center_lid.json
│ │ ├── template_chest_center_trunk.json
│ │ ├── template_chest_left.json
│ │ ├── template_chest_left_lid.json
│ │ ├── template_chest_left_trunk.json
│ │ ├── template_chest_right.json
│ │ ├── template_chest_right_lid.json
│ │ ├── template_chest_right_trunk.json
│ │ ├── template_hanging_sign_0.json
│ │ ├── template_hanging_sign_0_ao.json
│ │ ├── template_hanging_sign_22_5.json
│ │ ├── template_hanging_sign_22_5_ao.json
│ │ ├── template_hanging_sign_45.json
│ │ ├── template_hanging_sign_45_ao.json
│ │ ├── template_hanging_sign_67_5.json
│ │ ├── template_hanging_sign_67_5_ao.json
│ │ ├── template_hanging_sign_attached_0.json
│ │ ├── template_hanging_sign_attached_0_ao.json
│ │ ├── template_hanging_sign_attached_22_5.json
│ │ ├── template_hanging_sign_attached_22_5_ao.json
│ │ ├── template_hanging_sign_attached_45.json
│ │ ├── template_hanging_sign_attached_45_ao.json
│ │ ├── template_hanging_sign_attached_67_5.json
│ │ ├── template_hanging_sign_attached_67_5_ao.json
│ │ ├── template_pottery_pattern_east.json
│ │ ├── template_pottery_pattern_north.json
│ │ ├── template_pottery_pattern_south.json
│ │ ├── template_pottery_pattern_west.json
│ │ ├── template_shulker_box.json
│ │ ├── template_shulker_box_bottom.json
│ │ ├── template_shulker_box_lid.json
│ │ ├── template_sign_0.json
│ │ ├── template_sign_0_ao.json
│ │ ├── template_sign_22_5.json
│ │ ├── template_sign_22_5_ao.json
│ │ ├── template_sign_45.json
│ │ ├── template_sign_45_ao.json
│ │ ├── template_sign_67_5.json
│ │ ├── template_sign_67_5_ao.json
│ │ ├── template_wall_hanging_sign.json
│ │ ├── template_wall_hanging_sign_ao.json
│ │ ├── template_wall_sign.json
│ │ └── template_wall_sign_ao.json
│ └── item/
│ └── christmas_chest.json
├── enhancedblockentities.accesswidener
├── enhancedblockentities.mixins.json
├── fabric.mod.json
└── templates/
├── blockstate/
│ ├── base.json
│ └── var.json
├── item/
│ ├── bed.json
│ ├── chest_item.json
│ └── chest_item_no_christmas.json
└── model/
├── bed_foot_item.json
├── bed_head_item.json
├── chest_like.json
└── parent_and_tex.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/build.yml
================================================
name: build
on: [pull_request, push]
jobs:
build:
strategy:
matrix:
java: [21]
runs-on: ubuntu-22.04
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v2
- name: setup jdk ${{ matrix.java }}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: 'temurin'
- name: make gradle wrapper executable
run: chmod +x ./gradlew
- name: build
run: ./gradlew build
- name: capture build artifacts
if: ${{ matrix.java == '21' }}
uses: actions/upload-artifact@v4
with:
name: Artifacts
path: build/libs/
================================================
FILE: .gitignore
================================================
# gradle
.gradle/
build/
out/
classes/
# eclipse
*.launch
# idea
.idea/
*.iml
*.ipr
*.iws
# vscode
.settings/
.vscode/
bin/
.classpath
.project
# macos
*.DS_Store
# fabric
run/
================================================
FILE: LICENSE.txt
================================================
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
Copyright 2021 FoundationGames, LGPLv3
================================================
FILE: README.md
================================================
## Enhanced Block Entities
EBE is a **100% client side** Minecraft mod for the **[Fabric](https://fabricmc.net/use/)** mod loader which aims to increase the performance of block entity rendering, as well as offer customizability via resource packs. <br/><br/>
**How does it work?** EBE Makes some block entities use baked block models rather than laggy entity models. <br/><br/>
**Is it just an optimization mod?** EBE isn't *just* an optimization mod, some side effects of its optimizations are many visual improvements. <br/>
These may include:
- Smooth lighting on block entities
- Being able to remodel block entities with block models
- Toggling features like christmas chests
- Being able to see block entities from as far away as possible
<br/><br/>
**What about animations?** The best part about EBE is that you still get to keep animations, while gaining the performance boost of baked models! Most animated block entity models will only render when absolutely necessary. <br/><br/>
**Can I use it with Sodium?** Yes.<br/><br/>
- EBE 0.10.2 and above are **fully compatible with Sodium 0.6+**
- Earlier EBE versions require installing [Indium](https://modrinth.com/mod/indium) along with Sodium 0.5.11 or below.
## Downloading the mod
For stable releases, you can check out the [CurseForge](https://www.curseforge.com/minecraft/mc-mods/enhanced-block-entities) or [Modrinth](https://modrinth.com/mod/OVuFYfre) page. If you want the newest bleeding edge build, you can use GitHub Actions (or alternatively, you can build yourself). This mod requires [Fabric API](https://modrinth.com/mod/fabric-api) <br/><br/>
## FAQ and Help
**Q: I need help with the mod/need to report a bug!** <br/>
**A:** If you're having trouble setting up the mod or using it alongside other mods, I'd recommend you join our [Discord Server](https://discord.gg/7Aw3y4RtY9) and ask for help there. *If the issue is a BUG* please report it on our issue tracker ("Issues" tab at the top of the page)<br/><br/>
**Q: Does this mod glitch the chest animation or turn chests invisible?**
**A:** This bug has been completely eradicated in EBE versions 0.5 and above. If the issue still persists (it shouldn't), leave an issue on GitHub or join the [Discord Server](https://discord.gg/7Aw3y4RtY9). The chest lid may flash when using with Sodium. <br/><br/>
**Q: My chests are still invisible!** <br/>
**A:** You're likely using a Sodium version lower than 0.4, which doesn't support certain Fabric Rendering features by default. If you need to use a Sodium version lower than 0.4 with EBE, you should install [Indium](https://modrinth.com/mod/indium). <br/><br/>
<br/><br/>
## FPS Boost
Rendering 1700 chests:
### Vanilla

### With EBE
 <br/>
A 155% frame rate increase!
## Is your mod incompatible with EBE?
If you are the developer of a mod that makes changes to block entity rendering, your mod will be broken by EBE. Fortunately, EBE provides an API that allows you to force-disable its features, allowing your mod to function instead.
<br/>
**You don't need to add EBE as a dependency in your development environment either!**
### Add the Entrypoint
`fabric.mod.json`:
```json
{
"entrypoints": {
"main": [...],
"client": [...],
"ebe_v1": [
"my.mod.compat.EBECompatibility"
]
}
}
```
### Need to modify config values? Implement `BiConsumer<Properties, Map<String, Text>>`
`my.mod.compat.EBECompatibility`:
```java
public class EBECompatibility implements BiConsumer<Properties, Map<String, Text>>, ... {
@Override
public void accept(Properties overrideConfigValues, Map<String, Text> overrideReasons) {
overrideConfigValues.setProperty("render_enhanced_chests", "false");
overrideReasons.put("render_enhanced_chests",
Text.literal("EBE Enhanced Chests are not compatible with my mod!")
.formatted(Formatting.YELLOW));
}
...
}
```
The `accept(Properties, Map<String, Text>)` function is called when EBE loads config values. You can override a desired config value by setting the corresponding property of `overrideConfigValues`. This will also gray out the option in the config menu.
<br/>
To explain to users why your mod made that change, you can add a text component to the `overrideReasons` map corresponding to the key of the option you changed.
<br/>
`Text` is `net.minecraft.text.Text` when using Yarn mappings.
### Need to manually reload EBE? Implement `Consumer<Runnable>`
`my.mod.compat.EBECompatibility`:
```java
public class EBECompatibility implements Consumer<Runnable>, ... {
private static Runnable ebeReloader = () -> {};
...
@Override
public void accept(Runnable ebeConfigReloader) {
ebeReloader = ebeConfigReloader;
}
}
```
If your mod needs to modify EBE's config values depending on loaded resources, it may encounter load order problems. This can be somewhat fixed by manually reloading EBE.
<br/>
The `accept(Runnable)` function is called when EBE is first loaded. The `Runnable` executes `EnhancedBlockEntities.load()`. Store this in a field so you can execute it whenever necessary.
```java
void onMyModResourceReload() {
EBECompatibility.someParameter = true;
EBECompatibility.ebeReloader.run();
// Your config modification handler in EBECompatibility can change
// its behavior based on EBECompatibility.someParameter.
}
```
================================================
FILE: build.gradle
================================================
plugins {
id 'fabric-loom' version '1.8-SNAPSHOT'
id 'maven-publish'
}
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
repositories {
maven { url = 'https://maven.terraformersmc.com/' }
maven { url = 'https://api.modrinth.com/maven/' }
}
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// Mod Menu because config screen access from another place
modApi "com.terraformersmc:modmenu:${project.modmenu_version}"
// Sodium for compatibility
modCompileOnlyApi "maven.modrinth:sodium:${project.sodium_version}"
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach {
// ensure that the encoding is set to UTF-8, no matter what the system default is
// this fixes some edge cases with special characters not displaying correctly
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
// If Javadoc is generated, this must be specified in that task too.
it.options.encoding = "UTF-8"
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}
loom {
accessWidenerPath = file("src/main/resources/enhancedblockentities.accesswidener")
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
// Select the repositories you want to publish to
// To publish to maven local, no extra repositories are necessary. Just use the task `publishToMavenLocal`.
repositories {
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: gradle.properties
================================================
org.gradle.jvmargs=-Xmx2G
minecraft_version=1.21.4
yarn_mappings=1.21.4+build.8
loader_version=0.16.10
fabric_version=0.114.3+1.21.4
mod_version = 0.11.4+1.21.4
maven_group = foundationgames
archives_base_name = enhancedblockentities
modmenu_version=13.0.0
sodium_version=mc1.21.4-0.6.6-fabric
================================================
FILE: gradlew
================================================
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
pluginManagement {
repositories {
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/EBESetup.java
================================================
package foundationgames.enhancedblockentities;
import foundationgames.enhancedblockentities.client.model.DynamicModelEffects;
import foundationgames.enhancedblockentities.client.model.DynamicModelProvidingPlugin;
import foundationgames.enhancedblockentities.client.model.DynamicUnbakedModel;
import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.model.ModelSelector;
import foundationgames.enhancedblockentities.client.model.misc.DecoratedPotModelSelector;
import foundationgames.enhancedblockentities.client.render.BlockEntityRenderCondition;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.BellBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.DecoratedPotBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.ShulkerBoxBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.render.entity.SignBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.client.resource.EBEPack;
import foundationgames.enhancedblockentities.util.DateUtil;
import foundationgames.enhancedblockentities.util.EBEUtil;
import foundationgames.enhancedblockentities.util.ResourceUtil;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.model.loading.v1.FabricBakedModelManager;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.enums.ChestType;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.registry.Registries;
import net.minecraft.state.property.Properties;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Identifier;
import java.util.function.Function;
public enum EBESetup {;
public static void setupRRPChests() {
EBEPack p = ResourceUtil.getPackForCompat();
ResourceUtil.addChestBlockStates("chest", p);
ResourceUtil.addChestBlockStates("trapped_chest", p);
ResourceUtil.addChestBlockStates("christmas_chest", p);
ResourceUtil.addSingleChestOnlyBlockStates("ender_chest", p);
p = ResourceUtil.getBasePack();
ResourceUtil.addSingleChestModels("normal", "chest", p);
ResourceUtil.addDoubleChestModels("normal_left", "normal_right","chest", p);
ResourceUtil.addSingleChestModels("trapped", "trapped_chest", p);
ResourceUtil.addDoubleChestModels("trapped_left", "trapped_right","trapped_chest", p);
ResourceUtil.addSingleChestModels("christmas", "christmas_chest", p);
ResourceUtil.addDoubleChestModels("christmas_left", "christmas_right","christmas_chest", p);
ResourceUtil.addSingleChestModels("ender", "ender_chest", p);
ResourceUtil.addChestItemDefinition("chest", "chest_center", true, p);
ResourceUtil.addChestItemDefinition("trapped_chest", "trapped_chest_center", true, p);
ResourceUtil.addChestItemDefinition("ender_chest", "ender_chest_center", false, p);
p.addDirBlockSprites("entity/chest", "entity/chest/");
}
public static void setupRRPSigns() {
EBEPack p = ResourceUtil.getPackForCompat();
ResourceUtil.addSignBlockStates("oak_sign", "oak_wall_sign", p);
ResourceUtil.addSignBlockStates("birch_sign", "birch_wall_sign", p);
ResourceUtil.addSignBlockStates("spruce_sign", "spruce_wall_sign", p);
ResourceUtil.addSignBlockStates("jungle_sign", "jungle_wall_sign", p);
ResourceUtil.addSignBlockStates("acacia_sign", "acacia_wall_sign", p);
ResourceUtil.addSignBlockStates("dark_oak_sign", "dark_oak_wall_sign", p);
ResourceUtil.addSignBlockStates("mangrove_sign", "mangrove_wall_sign", p);
ResourceUtil.addSignBlockStates("cherry_sign", "cherry_wall_sign", p);
ResourceUtil.addSignBlockStates("crimson_sign", "crimson_wall_sign", p);
ResourceUtil.addSignBlockStates("warped_sign", "warped_wall_sign", p);
ResourceUtil.addSignBlockStates("bamboo_sign", "bamboo_wall_sign", p);
ResourceUtil.addSignBlockStates("pale_oak_sign", "pale_oak_wall_sign", p);
ResourceUtil.addHangingSignBlockStates("oak_hanging_sign", "oak_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("birch_hanging_sign", "birch_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("spruce_hanging_sign", "spruce_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("jungle_hanging_sign", "jungle_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("acacia_hanging_sign", "acacia_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("dark_oak_hanging_sign", "dark_oak_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("mangrove_hanging_sign", "mangrove_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("cherry_hanging_sign", "cherry_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("crimson_hanging_sign", "crimson_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("warped_hanging_sign", "warped_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("bamboo_hanging_sign", "bamboo_wall_hanging_sign", p);
ResourceUtil.addHangingSignBlockStates("pale_oak_hanging_sign", "pale_oak_wall_hanging_sign", p);
p = ResourceUtil.getBasePack();
ResourceUtil.addSignTypeModels("oak", p);
ResourceUtil.addSignTypeModels("birch", p);
ResourceUtil.addSignTypeModels("spruce", p);
ResourceUtil.addSignTypeModels("jungle", p);
ResourceUtil.addSignTypeModels("acacia", p);
ResourceUtil.addSignTypeModels("dark_oak", p);
ResourceUtil.addSignTypeModels("mangrove", p);
ResourceUtil.addSignTypeModels("cherry", p);
ResourceUtil.addSignTypeModels("crimson", p);
ResourceUtil.addSignTypeModels("warped", p);
ResourceUtil.addSignTypeModels("bamboo", p);
ResourceUtil.addSignTypeModels("pale_oak", p);
p.addDirBlockSprites("entity/signs", "entity/signs/");
p.addDirBlockSprites("entity/signs/hanging", "entity/signs/hanging/");
p.addDirBlockSprites("gui/hanging_signs", "block/particle_hanging_sign_");
}
public static void setupRRPBells() {
ResourceUtil.addBellBlockState(ResourceUtil.getPackForCompat());
ResourceUtil.getBasePack().addSingleBlockSprite(Identifier.of("entity/bell/bell_body"));
}
public static void setupRRPBeds() {
EBEPack p = ResourceUtil.getBasePack();
EBEPack pCompat = ResourceUtil.getPackForCompat();
for (DyeColor color : DyeColor.values()) {
ResourceUtil.addBedBlockState(color, pCompat);
ResourceUtil.addBedModels(color, p);
}
p.addDirBlockSprites("entity/bed", "entity/bed/");
}
public static void setupRRPShulkerBoxes() {
EBEPack p = ResourceUtil.getBasePack();
EBEPack pCompat = ResourceUtil.getPackForCompat();
for (DyeColor color : EBEUtil.DEFAULTED_DYE_COLORS) {
var id = color != null ? color.getName()+"_shulker_box" : "shulker_box";
ResourceUtil.addShulkerBoxBlockStates(color, pCompat);
ResourceUtil.addShulkerBoxModels(color, p);
ResourceUtil.addParentModel("block/"+id, Identifier.of("item/"+id), p);
}
p.addDirBlockSprites("entity/shulker", "entity/shulker/");
}
public static void setupRRPDecoratedPots() {
EBEPack p = ResourceUtil.getBasePack();
EBEPack pCompat = ResourceUtil.getPackForCompat();
ResourceUtil.addDecoratedPotBlockState(pCompat);
for (var patternKey : Registries.DECORATED_POT_PATTERN.getKeys()) {
ResourceUtil.addDecoratedPotPatternModels(patternKey, p);
}
p.addDirBlockSprites("entity/decorated_pot", "entity/decorated_pot/");
}
public static void setupResourceProviders() {
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "chest_center"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.CHEST_CENTER,
ModelIdentifiers.CHEST_CENTER_TRUNK,
ModelIdentifiers.CHRISTMAS_CHEST_CENTER,
ModelIdentifiers.CHRISTMAS_CHEST_CENTER_TRUNK
},
ModelSelector.CHEST_WITH_CHRISTMAS,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "chest_left"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.CHEST_LEFT,
ModelIdentifiers.CHEST_LEFT_TRUNK,
ModelIdentifiers.CHRISTMAS_CHEST_LEFT,
ModelIdentifiers.CHRISTMAS_CHEST_LEFT_TRUNK
},
ModelSelector.CHEST_WITH_CHRISTMAS,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "chest_right"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.CHEST_RIGHT,
ModelIdentifiers.CHEST_RIGHT_TRUNK,
ModelIdentifiers.CHRISTMAS_CHEST_RIGHT,
ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_TRUNK
},
ModelSelector.CHEST_WITH_CHRISTMAS,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "trapped_chest_center"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.TRAPPED_CHEST_CENTER,
ModelIdentifiers.TRAPPED_CHEST_CENTER_TRUNK,
ModelIdentifiers.CHRISTMAS_CHEST_CENTER,
ModelIdentifiers.CHRISTMAS_CHEST_CENTER_TRUNK
},
ModelSelector.CHEST_WITH_CHRISTMAS,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "trapped_chest_left"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.TRAPPED_CHEST_LEFT,
ModelIdentifiers.TRAPPED_CHEST_LEFT_TRUNK,
ModelIdentifiers.CHRISTMAS_CHEST_LEFT,
ModelIdentifiers.CHRISTMAS_CHEST_LEFT_TRUNK
},
ModelSelector.CHEST_WITH_CHRISTMAS,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "trapped_chest_right"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.TRAPPED_CHEST_RIGHT,
ModelIdentifiers.TRAPPED_CHEST_RIGHT_TRUNK,
ModelIdentifiers.CHRISTMAS_CHEST_RIGHT,
ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_TRUNK
},
ModelSelector.CHEST_WITH_CHRISTMAS,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "ender_chest_center"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.ENDER_CHEST_CENTER,
ModelIdentifiers.ENDER_CHEST_CENTER_TRUNK
},
ModelSelector.CHEST,
DynamicModelEffects.CHEST
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "bell_between_walls"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.BELL_BETWEEN_WALLS_WITH_BELL,
ModelIdentifiers.BELL_BETWEEN_WALLS
},
ModelSelector.BELL,
DynamicModelEffects.BELL
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "bell_ceiling"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.BELL_CEILING_WITH_BELL,
ModelIdentifiers.BELL_CEILING
},
ModelSelector.BELL,
DynamicModelEffects.BELL
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "bell_floor"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.BELL_FLOOR_WITH_BELL,
ModelIdentifiers.BELL_FLOOR
},
ModelSelector.BELL,
DynamicModelEffects.BELL
)
));
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "bell_wall"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.BELL_WALL_WITH_BELL,
ModelIdentifiers.BELL_WALL
},
ModelSelector.BELL,
DynamicModelEffects.BELL
)
));
for (DyeColor color : EBEUtil.DEFAULTED_DYE_COLORS) {
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", color != null ? color.getName()+"_shulker_box" : "shulker_box"),
() -> new DynamicUnbakedModel(
new Identifier[] {
ModelIdentifiers.SHULKER_BOXES.get(color),
ModelIdentifiers.SHULKER_BOX_BOTTOMS.get(color)
},
ModelSelector.SHULKER_BOX,
DynamicModelEffects.SHULKER_BOX
)
));
}
DecoratedPotModelSelector decoratedPotSelector = new DecoratedPotModelSelector();
ModelLoadingPlugin.register(new DynamicModelProvidingPlugin(
Identifier.of("builtin", "decorated_pot"),
() -> new DynamicUnbakedModel(
decoratedPotSelector.createModelIDs(),
decoratedPotSelector,
DynamicModelEffects.DECORATED_POT
)
));
}
public static void setupChests() {
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.CHEST, RenderLayer.getCutoutMipped());
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.TRAPPED_CHEST, RenderLayer.getCutoutMipped());
BlockRenderLayerMap.INSTANCE.putBlock(Blocks.ENDER_CHEST, RenderLayer.getCutoutMipped());
Function<BlockEntity, Integer> christmasChestSelector = entity -> {
int os = DateUtil.isChristmas() ? 3 : 0;
ChestType type = entity.getCachedState().get(Properties.CHEST_TYPE);
return type == ChestType.RIGHT ? 2 + os : type == ChestType.LEFT ? 1 + os : os;
};
EnhancedBlockEntityRegistry.register(Blocks.CHEST, BlockEntityType.CHEST, BlockEntityRenderCondition.CHEST,
new ChestBlockEntityRendererOverride(() -> {
FabricBakedModelManager manager = MinecraftClient.getInstance().getBakedModelManager();
return new BakedModel[] {
manager.getModel(ModelIdentifiers.CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.CHEST_RIGHT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_LID)
};
}, christmasChestSelector)
);
EnhancedBlockEntityRegistry.register(Blocks.TRAPPED_CHEST, BlockEntityType.TRAPPED_CHEST, BlockEntityRenderCondition.CHEST,
new ChestBlockEntityRendererOverride(() -> {
FabricBakedModelManager manager = MinecraftClient.getInstance().getBakedModelManager();
return new BakedModel[] {
manager.getModel(ModelIdentifiers.TRAPPED_CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.TRAPPED_CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.TRAPPED_CHEST_RIGHT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_CENTER_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_LEFT_LID),
manager.getModel(ModelIdentifiers.CHRISTMAS_CHEST_RIGHT_LID)
};
}, christmasChestSelector)
);
EnhancedBlockEntityRegistry.register(Blocks.ENDER_CHEST, BlockEntityType.ENDER_CHEST, BlockEntityRenderCondition.CHEST,
new ChestBlockEntityRendererOverride(() -> {
FabricBakedModelManager manager = MinecraftClient.getInstance().getBakedModelManager();
return new BakedModel[] { manager.getModel(ModelIdentifiers.ENDER_CHEST_CENTER_LID) };
}, entity -> 0)
);
}
public static void setupSigns() {
for (var sign : new Block[] {
Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN,
Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN,
Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN,
Blocks.JUNGLE_SIGN, Blocks.JUNGLE_WALL_SIGN,
Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN,
Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN,
Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN,
Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN,
Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN,
Blocks.WARPED_SIGN, Blocks.WARPED_WALL_SIGN,
Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN,
Blocks.PALE_OAK_SIGN, Blocks.PALE_OAK_WALL_SIGN
}) {
EnhancedBlockEntityRegistry.register(sign, BlockEntityType.SIGN, BlockEntityRenderCondition.SIGN,
new SignBlockEntityRendererOverride()
);
}
for (var sign : new Block[] {
Blocks.OAK_HANGING_SIGN, Blocks.OAK_WALL_HANGING_SIGN,
Blocks.BIRCH_HANGING_SIGN, Blocks.BIRCH_WALL_HANGING_SIGN,
Blocks.SPRUCE_HANGING_SIGN, Blocks.SPRUCE_WALL_HANGING_SIGN,
Blocks.JUNGLE_HANGING_SIGN, Blocks.JUNGLE_WALL_HANGING_SIGN,
Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN,
Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN,
Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN,
Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN,
Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN,
Blocks.WARPED_HANGING_SIGN, Blocks.WARPED_WALL_HANGING_SIGN,
Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN,
Blocks.PALE_OAK_HANGING_SIGN, Blocks.PALE_OAK_WALL_HANGING_SIGN
}) {
EnhancedBlockEntityRegistry.register(sign, BlockEntityType.HANGING_SIGN, BlockEntityRenderCondition.SIGN,
new SignBlockEntityRendererOverride()
);
BlockRenderLayerMap.INSTANCE.putBlock(sign, RenderLayer.getCutout());
}
}
public static void setupBells() {
EnhancedBlockEntityRegistry.register(Blocks.BELL, BlockEntityType.BELL, BlockEntityRenderCondition.BELL,
new BellBlockEntityRendererOverride()
);
}
public static void setupBeds() {
EnhancedBlockEntityRegistry.register(Blocks.BLACK_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.BLUE_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.BROWN_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.CYAN_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.GRAY_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.GREEN_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.LIGHT_BLUE_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.LIGHT_GRAY_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.LIME_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.MAGENTA_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.ORANGE_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.PINK_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.PURPLE_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.RED_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.WHITE_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
EnhancedBlockEntityRegistry.register(Blocks.YELLOW_BED, BlockEntityType.BED, BlockEntityRenderCondition.NEVER, BlockEntityRendererOverride.NO_OP);
}
public static void setupShulkerBoxes() {
for (DyeColor color : EBEUtil.DEFAULTED_DYE_COLORS) {
var block = ShulkerBoxBlock.get(color);
BlockRenderLayerMap.INSTANCE.putBlock(block, RenderLayer.getCutoutMipped());
EnhancedBlockEntityRegistry.register(block, BlockEntityType.SHULKER_BOX, BlockEntityRenderCondition.SHULKER_BOX,
new ShulkerBoxBlockEntityRendererOverride((map) -> {
var models = MinecraftClient.getInstance().getBakedModelManager();
for (DyeColor dc : EBEUtil.DEFAULTED_DYE_COLORS) {
map.put(dc, models.getModel(ModelIdentifiers.SHULKER_BOX_LIDS.get(dc)));
}
})
);
}
}
public static void setupDecoratedPots() {
EnhancedBlockEntityRegistry.register(Blocks.DECORATED_POT, BlockEntityType.DECORATED_POT,
BlockEntityRenderCondition.DECORATED_POT, new DecoratedPotBlockEntityRendererOverride());
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java
================================================
package foundationgames.enhancedblockentities;
import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.model.item.EBEIsChristmasProperty;
import foundationgames.enhancedblockentities.client.render.SignRenderManager;
import foundationgames.enhancedblockentities.client.resource.template.TemplateLoader;
import foundationgames.enhancedblockentities.config.EBEConfig;
import foundationgames.enhancedblockentities.util.EBEUtil;
import foundationgames.enhancedblockentities.util.ResourceUtil;
import foundationgames.enhancedblockentities.util.WorldUtil;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.item.property.bool.BooleanProperties;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.function.Consumer;
public final class EnhancedBlockEntities implements ClientModInitializer {
public static final String ID = "enhancedblockentities";
public static final String NAMESPACE = "ebe";
public static final Logger LOG = LogManager.getLogger("Enhanced Block Entities");
public static final EBEConfig CONFIG = new EBEConfig();
public static final TemplateLoader TEMPLATE_LOADER = new TemplateLoader();
public static final String API_V1 = "ebe_v1";
@Override
@SuppressWarnings("unchecked")
public void onInitializeClient() {
FabricLoader.getInstance().getModContainer(ID).ifPresent(mod -> {
var roots = mod.getRootPaths();
if (!roots.isEmpty()) {
TEMPLATE_LOADER.setRoot(roots.getFirst().resolve("templates"));
}
});
var ebeCompatInitializers = FabricLoader.getInstance().getEntrypointContainers(API_V1, Consumer.class);
for (var init : ebeCompatInitializers) {
init.getEntrypoint().accept((Runnable) EnhancedBlockEntities::load);
}
BooleanProperties.ID_MAPPER.put(EBEUtil.id("ebe_is_christmas"), EBEIsChristmasProperty.CODEC);
WorldRenderEvents.END.register(SignRenderManager::endFrame);
ClientTickEvents.END_WORLD_TICK.register(WorldUtil.EVENT_LISTENER);
ModelIdentifiers.init();
EBESetup.setupResourceProviders();
load();
}
public static void reload(ReloadType type) {
load();
if (type == ReloadType.WORLD) {
MinecraftClient.getInstance().worldRenderer.reload();
} else if (type == ReloadType.RESOURCES) {
MinecraftClient.getInstance().reloadResources();
}
}
public static void load() {
CONFIG.load();
EnhancedBlockEntityRegistry.clear();
ResourceUtil.resetBasePack();
ResourceUtil.resetTopLevelPack();
if (CONFIG.renderEnhancedChests) {
EBESetup.setupChests();
EBESetup.setupRRPChests();
}
if (CONFIG.renderEnhancedSigns) {
EBESetup.setupSigns();
EBESetup.setupRRPSigns();
}
if (CONFIG.renderEnhancedBells) {
EBESetup.setupBells();
EBESetup.setupRRPBells();
}
if (CONFIG.renderEnhancedBeds) {
EBESetup.setupBeds();
EBESetup.setupRRPBeds();
}
if (CONFIG.renderEnhancedShulkerBoxes) {
EBESetup.setupShulkerBoxes();
EBESetup.setupRRPShulkerBoxes();
}
if (CONFIG.renderEnhancedDecoratedPots) {
EBESetup.setupDecoratedPots();
EBESetup.setupRRPDecoratedPots();
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntityRegistry.java
================================================
package foundationgames.enhancedblockentities;
import foundationgames.enhancedblockentities.client.render.BlockEntityRenderCondition;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import net.minecraft.block.Block;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.Pair;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public final class EnhancedBlockEntityRegistry {
public static final Map<BlockEntityType<?>, Pair<BlockEntityRenderCondition, BlockEntityRendererOverride>> ENTITIES = new HashMap<>();
public static final Set<Block> BLOCKS = new HashSet<>();
private EnhancedBlockEntityRegistry() {}
public static void register(Block block, BlockEntityType<?> type, BlockEntityRenderCondition condition, BlockEntityRendererOverride renderer) {
ENTITIES.put(type, new Pair<>(condition, renderer));
BLOCKS.add(block);
}
public static void clear() {
ENTITIES.clear();
BLOCKS.clear();
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/ReloadType.java
================================================
package foundationgames.enhancedblockentities;
public enum ReloadType {
NONE(0),
WORLD(1),
RESOURCES(2);
private final int pertinence;
ReloadType(int pertinence) {
this.pertinence = pertinence;
}
public ReloadType or(ReloadType type) {
return type.pertinence > this.pertinence ? type : this;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicBakedModel.java
================================================
package foundationgames.enhancedblockentities.client.model;
import net.fabricmc.fabric.api.renderer.v1.Renderer;
import net.fabricmc.fabric.api.renderer.v1.material.RenderMaterial;
import net.fabricmc.fabric.api.renderer.v1.mesh.QuadEmitter;
import net.fabricmc.fabric.api.renderer.v1.model.FabricBakedModel;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class DynamicBakedModel implements BakedModel, FabricBakedModel {
private final BakedModel[] models;
private final ModelSelector selector;
private final DynamicModelEffects effects;
private final ThreadLocal<int[]> activeModelIndices;
private final ThreadLocal<BakedModel[]> displayedModels;
public DynamicBakedModel(BakedModel[] models, ModelSelector selector, DynamicModelEffects effects) {
this.models = models;
this.selector = selector;
this.effects = effects;
this.activeModelIndices = ThreadLocal.withInitial(() -> new int[selector.displayedModelCount]);
this.displayedModels = ThreadLocal.withInitial(() -> new BakedModel[selector.displayedModelCount]);
}
@Override
public boolean isVanillaAdapter() {
return false;
}
@Override
public void emitBlockQuads(QuadEmitter emitter, BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rng, Predicate<@Nullable Direction> cullTest) {
RenderMaterial mat = null;
var indices = this.activeModelIndices.get();
var models = this.displayedModels.get();
getSelector().writeModelIndices(view, state, pos, rng, indices);
for (int i = 0; i < indices.length; i++) {
int modelIndex = indices[i];
if (modelIndex >= 0) {
models[i] = this.models[modelIndex];
} else {
models[i] = null;
}
}
var renderer = Renderer.get();
if (renderer != null) {
mat = renderer.materialById(RenderMaterial.STANDARD_ID);
}
for (int i = 0; i <= 6; i++) {
Direction dir = ModelHelper.faceFromIndex(i);
for (BakedModel model : models) if (model != null) {
for (BakedQuad quad : model.getQuads(state, dir, rng.get())) {
emitter.fromVanilla(quad, mat, dir);
emitter.emit();
}
}
}
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction face, Random random) {
return models[0].getQuads(state, face, random);
}
@Override
public boolean useAmbientOcclusion() {
return getEffects().ambientOcclusion();
}
@Override
public boolean hasDepth() {
return false;
}
@Override
public boolean isSideLit() {
return false;
}
@Override
public Sprite getParticleSprite() {
return models[getSelector().getParticleModelIndex()].getParticleSprite();
}
@Override
public ModelTransformation getTransformation() {
return null;
}
public BakedModel[] getModels() {
return models;
}
public ModelSelector getSelector() {
return selector;
}
public DynamicModelEffects getEffects() {
return effects;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelEffects.java
================================================
package foundationgames.enhancedblockentities.client.model;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import java.util.ArrayList;
import java.util.List;
public abstract class DynamicModelEffects {
private static final List<DynamicModelEffects> REGISTRY = new ArrayList<>();
public static final DynamicModelEffects DEFAULT = new DynamicModelEffects() {};
public static final DynamicModelEffects CHEST = new DynamicModelEffects() {
@Override
public boolean ambientOcclusion() {
return EnhancedBlockEntities.CONFIG.chestAO;
}
};
public static final DynamicModelEffects BELL = new DynamicModelEffects() {
@Override
public boolean ambientOcclusion() {
return EnhancedBlockEntities.CONFIG.bellAO;
}
};
public static final DynamicModelEffects SHULKER_BOX = new DynamicModelEffects() {
@Override
public boolean ambientOcclusion() {
return EnhancedBlockEntities.CONFIG.shulkerBoxAO;
}
};
public static final DynamicModelEffects DECORATED_POT = new DynamicModelEffects() {
@Override
public boolean ambientOcclusion() {
return EnhancedBlockEntities.CONFIG.decoratedPotAO;
}
};
public final int id;
public DynamicModelEffects() {
this.id = REGISTRY.size();
REGISTRY.add(this);
}
public boolean ambientOcclusion() {
return true;
}
public static DynamicModelEffects fromId(int id) {
return REGISTRY.get(id);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvidingPlugin.java
================================================
package foundationgames.enhancedblockentities.client.model;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelModifier;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.util.function.Supplier;
public class DynamicModelProvidingPlugin implements ModelLoadingPlugin, ModelModifier.OnLoad {
private final Supplier<DynamicUnbakedModel> model;
private final Identifier id;
public DynamicModelProvidingPlugin(Identifier id, Supplier<DynamicUnbakedModel> model) {
this.model = model;
this.id = id;
}
@Override
public void initialize(ModelLoadingPlugin.Context ctx) {
ctx.modifyModelOnLoad().register(this);
}
@Override
public @Nullable UnbakedModel modifyModelOnLoad(@Nullable UnbakedModel model, ModelModifier.OnLoad.Context context) {
if (context.id().equals(this.id)) return this.model.get();
return model;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicUnbakedModel.java
================================================
package foundationgames.enhancedblockentities.client.model;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.Baker;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelTextures;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
public class DynamicUnbakedModel implements UnbakedModel {
private final Identifier[] models;
private final ModelSelector selector;
private final DynamicModelEffects effects;
public DynamicUnbakedModel(Identifier[] models, ModelSelector selector, DynamicModelEffects effects) {
this.models = models;
this.selector = selector;
this.effects = effects;
}
@Override
public void resolve(Resolver resolver) {
for (Identifier modelId : models) {
if(modelId == null) continue;
resolver.resolve(modelId);
}
}
@Override
public @Nullable BakedModel bake(ModelTextures textures, Baker baker, ModelBakeSettings settings, boolean ambientOcclusion, boolean isSideLit, ModelTransformation transformation) {
BakedModel[] baked = new BakedModel[models.length];
for (int i = 0; i < models.length; i++) {
baked[i] = baker.bake(models[i], settings);
}
return new DynamicBakedModel(baked, selector, effects);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java
================================================
package foundationgames.enhancedblockentities.client.model;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.config.EBEConfig;
import foundationgames.enhancedblockentities.util.EBEUtil;
import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin;
import net.minecraft.block.DecoratedPotPattern;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
public final class ModelIdentifiers implements ModelLoadingPlugin {
private static final Map<Predicate<EBEConfig>, Set<Identifier>> modelLoaders = new HashMap<>();
public static final Predicate<EBEConfig> CHEST_PREDICATE = c -> c.renderEnhancedChests;
public static final Predicate<EBEConfig> BELL_PREDICATE = c -> c.renderEnhancedBells;
public static final Predicate<EBEConfig> SHULKER_BOX_PREDICATE = c -> c.renderEnhancedShulkerBoxes;
public static final Predicate<EBEConfig> DECORATED_POT_PREDICATE = c -> c.renderEnhancedDecoratedPots;
public static final Identifier CHEST_CENTER = of("block/chest_center", CHEST_PREDICATE);
public static final Identifier CHEST_CENTER_TRUNK = of("block/chest_center_trunk", CHEST_PREDICATE);
public static final Identifier CHEST_CENTER_LID = of("block/chest_center_lid", CHEST_PREDICATE);
public static final Identifier CHEST_LEFT = of("block/chest_left", CHEST_PREDICATE);
public static final Identifier CHEST_LEFT_TRUNK = of("block/chest_left_trunk", CHEST_PREDICATE);
public static final Identifier CHEST_LEFT_LID = of("block/chest_left_lid", CHEST_PREDICATE);
public static final Identifier CHEST_RIGHT = of("block/chest_right", CHEST_PREDICATE);
public static final Identifier CHEST_RIGHT_TRUNK = of("block/chest_right_trunk", CHEST_PREDICATE);
public static final Identifier CHEST_RIGHT_LID = of("block/chest_right_lid", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_CENTER = of("block/trapped_chest_center", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_CENTER_TRUNK = of("block/trapped_chest_center_trunk", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_CENTER_LID = of("block/trapped_chest_center_lid", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_LEFT = of("block/trapped_chest_left", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_LEFT_TRUNK = of("block/trapped_chest_left_trunk", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_LEFT_LID = of("block/trapped_chest_left_lid", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_RIGHT = of("block/trapped_chest_right", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_RIGHT_TRUNK = of("block/trapped_chest_right_trunk", CHEST_PREDICATE);
public static final Identifier TRAPPED_CHEST_RIGHT_LID = of("block/trapped_chest_right_lid", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_CENTER = of("block/christmas_chest_center", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_CENTER_TRUNK = of("block/christmas_chest_center_trunk", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_CENTER_LID = of("block/christmas_chest_center_lid", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_LEFT = of("block/christmas_chest_left", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_LEFT_TRUNK = of("block/christmas_chest_left_trunk", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_LEFT_LID = of("block/christmas_chest_left_lid", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_RIGHT = of("block/christmas_chest_right", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_RIGHT_TRUNK = of("block/christmas_chest_right_trunk", CHEST_PREDICATE);
public static final Identifier CHRISTMAS_CHEST_RIGHT_LID = of("block/christmas_chest_right_lid", CHEST_PREDICATE);
public static final Identifier ENDER_CHEST_CENTER = of("block/ender_chest_center", CHEST_PREDICATE);
public static final Identifier ENDER_CHEST_CENTER_TRUNK = of("block/ender_chest_center_trunk", CHEST_PREDICATE);
public static final Identifier ENDER_CHEST_CENTER_LID = of("block/ender_chest_center_lid", CHEST_PREDICATE);
public static final Identifier BELL_BETWEEN_WALLS = of("block/bell_between_walls", BELL_PREDICATE);
public static final Identifier BELL_CEILING = of("block/bell_ceiling", BELL_PREDICATE);
public static final Identifier BELL_FLOOR = of("block/bell_floor", BELL_PREDICATE);
public static final Identifier BELL_WALL = of("block/bell_wall", BELL_PREDICATE);
public static final Identifier BELL_BETWEEN_WALLS_WITH_BELL = of("block/bell_between_walls_with_bell", BELL_PREDICATE);
public static final Identifier BELL_CEILING_WITH_BELL = of("block/bell_ceiling_with_bell", BELL_PREDICATE);
public static final Identifier BELL_FLOOR_WITH_BELL = of("block/bell_floor_with_bell", BELL_PREDICATE);
public static final Identifier BELL_WALL_WITH_BELL = of("block/bell_wall_with_bell", BELL_PREDICATE);
public static final Identifier BELL_BODY = of("block/bell_body", BELL_PREDICATE);
public static final Identifier DECORATED_POT_BASE = of("block/decorated_pot_base", DECORATED_POT_PREDICATE);
public static final Identifier DECORATED_POT_SHAKING = of("block/decorated_pot_shaking", DECORATED_POT_PREDICATE);
public static final Map<DyeColor, Identifier> SHULKER_BOXES = new HashMap<>();
public static final Map<DyeColor, Identifier> SHULKER_BOX_BOTTOMS = new HashMap<>();
public static final Map<DyeColor, Identifier> SHULKER_BOX_LIDS = new HashMap<>();
public static final Map<RegistryKey<DecoratedPotPattern>, Identifier[]> POTTERY_PATTERNS = new HashMap<>();
static {
for (DyeColor color : EBEUtil.DEFAULTED_DYE_COLORS) {
var id = color != null ? "block/"+color.getName()+"_shulker_box" : "block/shulker_box";
SHULKER_BOXES.put(color, of(id, SHULKER_BOX_PREDICATE));
SHULKER_BOX_BOTTOMS.put(color, of(id+"_bottom", SHULKER_BOX_PREDICATE));
SHULKER_BOX_LIDS.put(color, of(id+"_lid", SHULKER_BOX_PREDICATE));
}
refreshPotteryPatterns();
}
public static void init() {
ModelLoadingPlugin.register(new ModelIdentifiers());
}
public static void refreshPotteryPatterns() {
POTTERY_PATTERNS.clear();
// The order decorated pots store patterns per face
Direction[] orderedHorizontalDirs = new Direction[] {Direction.NORTH, Direction.WEST, Direction.EAST, Direction.SOUTH};
for (var patternKey : Registries.DECORATED_POT_PATTERN.getKeys()) {
var pattern = patternKey.getValue().getPath();
var ids = new Identifier[orderedHorizontalDirs.length];;
for (int i = 0; i < 4; i++) {
ids[i] = of("block/" + pattern + "_" + orderedHorizontalDirs[i].getName(),
DECORATED_POT_PREDICATE);
}
POTTERY_PATTERNS.put(patternKey, ids);
}
}
private static Identifier of(String id, Predicate<EBEConfig> condition) {
Identifier idf = Identifier.of(id);
modelLoaders.computeIfAbsent(condition, k -> new HashSet<>()).add(idf);
return idf;
}
@Override
public void initialize(Context ctx) {
var config = EnhancedBlockEntities.CONFIG;
for (var entry : modelLoaders.entrySet()) {
if (entry.getKey().test(config)) {
ctx.addModels(entry.getValue());
}
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java
================================================
package foundationgames.enhancedblockentities.client.model;
import foundationgames.enhancedblockentities.util.DateUtil;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public abstract class ModelSelector {
private static final List<ModelSelector> REGISTRY = new ArrayList<>();
public static final ModelSelector STATE_HOLDER_SELECTOR = new ModelSelector() {
@Override
public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, int[] indices) {
if (view.getBlockEntity(pos) instanceof AppearanceStateHolder stateHolder) {
indices[0] = stateHolder.getModelState();
return;
}
indices[0] = 0;
}
};
public static final ModelSelector CHEST = STATE_HOLDER_SELECTOR;
public static final ModelSelector CHEST_WITH_CHRISTMAS = new ModelSelector() {
@Override
public int getParticleModelIndex() {
return DateUtil.isChristmas() ? 2 : 0;
}
@Override
public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, int[] indices) {
if (view.getBlockEntity(pos) instanceof AppearanceStateHolder stateHolder) {
indices[0] = stateHolder.getModelState() + this.getParticleModelIndex();
return;
}
indices[0] = this.getParticleModelIndex();
}
};
public static final ModelSelector BELL = STATE_HOLDER_SELECTOR;
public static final ModelSelector SHULKER_BOX = STATE_HOLDER_SELECTOR;
public int getParticleModelIndex() {
return 0;
}
public abstract void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, int[] indices);
public final int id;
public final int displayedModelCount;
public ModelSelector(int displayedModelCount) {
this.id = REGISTRY.size();
this.displayedModelCount = displayedModelCount;
REGISTRY.add(this);
}
public ModelSelector() {
this(1);
}
public static ModelSelector fromId(int id) {
return REGISTRY.get(id);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/item/EBEIsChristmasProperty.java
================================================
package foundationgames.enhancedblockentities.client.model.item;
import com.mojang.serialization.MapCodec;
import foundationgames.enhancedblockentities.util.DateUtil;
import net.minecraft.client.render.item.property.bool.BooleanProperty;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ModelTransformationMode;
import org.jetbrains.annotations.Nullable;
public record EBEIsChristmasProperty() implements BooleanProperty {
public static final MapCodec<EBEIsChristmasProperty> CODEC = MapCodec.unit(new EBEIsChristmasProperty());
@Override
public boolean getValue(ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity user, int seed, ModelTransformationMode modelTransformationMode) {
return DateUtil.isChristmas();
}
@Override
public MapCodec<EBEIsChristmasProperty> getCodec() {
return CODEC;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java
================================================
package foundationgames.enhancedblockentities.client.model.misc;
import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.model.ModelSelector;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.DecoratedPotPattern;
import net.minecraft.block.DecoratedPotPatterns;
import net.minecraft.block.entity.DecoratedPotBlockEntity;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockRenderView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
public class DecoratedPotModelSelector extends ModelSelector {
public static final int BUILTIN_MODEL_COUNT = 2;
public static final int IDX_EMPTY = 0;
public static final int IDX_BASE_POT = 1;
private final List<RegistryKey<DecoratedPotPattern>> potteryPatterns;
public DecoratedPotModelSelector() {
super(5);
this.potteryPatterns = new ArrayList<>(Registries.DECORATED_POT_PATTERN.getKeys());
}
public Identifier[] createModelIDs() {
ModelIdentifiers.refreshPotteryPatterns();
var ids = new Identifier[BUILTIN_MODEL_COUNT + potteryPatterns.size() * 4];
ids[IDX_EMPTY] = ModelIdentifiers.DECORATED_POT_SHAKING;
ids[IDX_BASE_POT] = ModelIdentifiers.DECORATED_POT_BASE;
int idIndex = BUILTIN_MODEL_COUNT;
for (int dirIndex = 0; dirIndex < 4; dirIndex++) {
for (var pattern : this.potteryPatterns) {
ids[idIndex] = ModelIdentifiers.POTTERY_PATTERNS.get(pattern)[dirIndex];
idIndex++;
}
}
return ids;
}
@Override
public void writeModelIndices(BlockRenderView view, BlockState state, BlockPos pos, Supplier<Random> rand, int[] indices) {
final int patternCount = potteryPatterns.size();
indices[0] = IDX_BASE_POT;
if (view.getBlockEntity(pos) instanceof DecoratedPotBlockEntity pot) {
if (pot instanceof AppearanceStateHolder ms && ms.getModelState() > 0) {
Arrays.fill(indices, IDX_EMPTY);
return;
}
var sherds = pot.getSherds();
indices[1] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.back(), patternCount);
indices[2] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.left(), patternCount) + patternCount;
indices[3] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.right(), patternCount) + patternCount * 2;
indices[4] = BUILTIN_MODEL_COUNT + getPatternIndex(sherds.front(), patternCount) + patternCount * 3;
return;
}
for (int i = 0; i < 4; i++) {
indices[1 + i] = BUILTIN_MODEL_COUNT + patternCount * i;
}
}
private int getPatternIndex(Optional<Item> sherd, int max) {
return MathHelper.clamp(this.potteryPatterns.indexOf(sherd.map(DecoratedPotPatterns::fromSherd).orElse(DecoratedPotPatterns.BLANK)), 0, max - 1);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java
================================================
package foundationgames.enhancedblockentities.client.render;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.config.EBEConfig;
import foundationgames.enhancedblockentities.mixin.AbstractSignBlockEntityRenderAccessor;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.Vec3d;
@FunctionalInterface
public interface BlockEntityRenderCondition {
BlockEntityRenderCondition NON_ZERO_STATE = entity -> {
if (entity instanceof AppearanceStateHolder stateHolder) {
return stateHolder.getRenderState() > 0;
}
return false;
};
BlockEntityRenderCondition CHEST = NON_ZERO_STATE;
BlockEntityRenderCondition BELL = NON_ZERO_STATE;
BlockEntityRenderCondition SHULKER_BOX = NON_ZERO_STATE;
BlockEntityRenderCondition SIGN = entity -> {
EBEConfig config = EnhancedBlockEntities.CONFIG;
if (config.signTextRendering.equals("all")) {
return true;
}
double playerDistance = MinecraftClient.getInstance().player.getBlockPos().getSquaredDistance(entity.getPos());
if (config.signTextRendering.equals("smart")) {
SignRenderManager.renderedSigns++;
return playerDistance < 80 + Math.max(0, 580 - (SignRenderManager.getRenderedSignAmount() * 0.7));
}
double dist = AbstractSignBlockEntityRenderAccessor.enhanced_bes$getRenderDistance();
Vec3d blockPos = Vec3d.ofCenter(entity.getPos());
Vec3d playerPos = MinecraftClient.getInstance().player.getPos();
if (config.signTextRendering.equals("most")) {
return blockPos.isInRange(playerPos, dist * 0.6);
}
if (config.signTextRendering.equals("some")) {
return blockPos.isInRange(playerPos, dist * 0.3);
}
if (config.signTextRendering.equals("few")) {
return blockPos.isInRange(playerPos, dist * 0.15);
}
return false;
};
BlockEntityRenderCondition DECORATED_POT = NON_ZERO_STATE;
BlockEntityRenderCondition NEVER = entity -> false;
BlockEntityRenderCondition ALWAYS = entity -> true;
boolean shouldRender(BlockEntity entity);
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java
================================================
package foundationgames.enhancedblockentities.client.render;
import foundationgames.enhancedblockentities.event.EBEEvents;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
public abstract class BlockEntityRendererOverride {
public static final BlockEntityRendererOverride NO_OP = new BlockEntityRendererOverride() {
@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {}
};
public BlockEntityRendererOverride() {
EBEEvents.RESOURCE_RELOAD.register(this::onModelsReload);
}
public abstract void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay);
public void onModelsReload() {}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/SignRenderManager.java
================================================
package foundationgames.enhancedblockentities.client.render;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
public class SignRenderManager {
private static int lastRenderedSigns = 0;
public static int renderedSigns = 0;
public static int getRenderedSignAmount() {
return lastRenderedSigns;
}
public static void endFrame(WorldRenderContext ctx) {
lastRenderedSigns = renderedSigns;
renderedSigns = 0;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java
================================================
package foundationgames.enhancedblockentities.client.render.entity;
import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.EBEUtil;
import net.minecraft.block.entity.BellBlockEntity;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
public class BellBlockEntityRendererOverride extends BlockEntityRendererOverride {
private BakedModel bellModel = null;
@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
if (bellModel == null) bellModel = getBellModel();
if (bellModel != null && blockEntity instanceof BellBlockEntity self) {
float ringTicks = (float)self.ringTicks + tickDelta;
float bellPitch = 0.0F;
float bellRoll = 0.0F;
if (self.ringing) {
float swingAngle = MathHelper.sin(ringTicks / (float)Math.PI) / (4.0F + ringTicks / 3.0F);
if (self.lastSideHit == Direction.NORTH) {
bellPitch = -swingAngle;
} else if (self.lastSideHit == Direction.SOUTH) {
bellPitch = swingAngle;
} else if (self.lastSideHit == Direction.EAST) {
bellRoll = -swingAngle;
} else if (self.lastSideHit == Direction.WEST) {
bellRoll = swingAngle;
}
}
matrices.push();
matrices.translate(8f/16, 12f/16, 8f/16);
matrices.multiply(RotationAxis.POSITIVE_X.rotation(bellPitch));
matrices.multiply(RotationAxis.POSITIVE_Z.rotation(bellRoll));
matrices.translate(-8f/16, -12f/16, -8f/16);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices, bellModel, light, overlay);
matrices.pop();
}
}
private BakedModel getBellModel() {
return MinecraftClient.getInstance().getBakedModelManager().getModel(ModelIdentifiers.BELL_BODY);
}
@Override
public void onModelsReload() {
bellModel = null;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java
================================================
package foundationgames.enhancedblockentities.client.render.entity;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.EBEUtil;
import net.minecraft.block.BlockState;
import net.minecraft.block.ChestBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.LidOpenable;
import net.minecraft.block.enums.ChestType;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.RotationAxis;
import java.util.function.Function;
import java.util.function.Supplier;
public class ChestBlockEntityRendererOverride extends BlockEntityRendererOverride {
private BakedModel[] models = null;
private final Supplier<BakedModel[]> modelGetter;
private final Function<BlockEntity, Integer> modelSelector;
public ChestBlockEntityRendererOverride(Supplier<BakedModel[]> modelGetter, Function<BlockEntity, Integer> modelSelector) {
this.modelGetter = modelGetter;
this.modelSelector = modelSelector;
}
@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
if (models == null) models = modelGetter.get();
if (blockEntity instanceof LidOpenable) {
matrices.push();
LidOpenable chest = getLidAnimationHolder(blockEntity, tickDelta);
matrices.translate(0.5f, 0, 0.5f);
Direction dir = blockEntity.getCachedState().get(ChestBlock.FACING);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - EBEUtil.angle(dir)));
matrices.translate(-0.5f, 0, -0.5f);
float yPiv = 9f / 16;
float zPiv = 15f / 16;
matrices.translate(0, yPiv, zPiv);
float rot = chest.getAnimationProgress(tickDelta);
rot = 1f - rot;
rot = 1f - (rot * rot * rot);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(rot * 90));
matrices.translate(0, -yPiv, -zPiv);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices, models[modelSelector.apply(blockEntity)], light, overlay);
matrices.pop();
}
}
public static LidOpenable getLidAnimationHolder(BlockEntity blockEntity, float tickDelta) {
LidOpenable chest = (LidOpenable)blockEntity;
BlockState state = blockEntity.getCachedState();
if (state.contains(ChestBlock.CHEST_TYPE) && state.get(ChestBlock.CHEST_TYPE) != ChestType.SINGLE) {
BlockEntity neighbor = null;
BlockPos pos = blockEntity.getPos();
Direction facing = state.get(ChestBlock.FACING);
switch (state.get(ChestBlock.CHEST_TYPE)) {
case LEFT -> neighbor = blockEntity.getWorld().getBlockEntity(pos.offset(facing.rotateYClockwise()));
case RIGHT -> neighbor = blockEntity.getWorld().getBlockEntity(pos.offset(facing.rotateYCounterclockwise()));
}
if (neighbor instanceof LidOpenable) {
float nAnim = ((LidOpenable)neighbor).getAnimationProgress(tickDelta);
if (nAnim > chest.getAnimationProgress(tickDelta)) {
chest = ((LidOpenable)neighbor);
}
}
}
return chest;
}
@Override
public void onModelsReload() {
this.models = null;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/DecoratedPotBlockEntityRendererOverride.java
================================================
package foundationgames.enhancedblockentities.client.render.entity;
import com.google.common.collect.ImmutableMap;
import foundationgames.enhancedblockentities.client.model.ModelIdentifiers;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.EBEUtil;
import net.minecraft.block.DecoratedPotPattern;
import net.minecraft.block.DecoratedPotPatterns;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.DecoratedPotBlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import java.util.Map;
public class DecoratedPotBlockEntityRendererOverride extends BlockEntityRendererOverride {
public static final float WOBBLE_STRENGTH = 1f / 64;
private BakedModel baseModel = null;
private Map<RegistryKey<DecoratedPotPattern>, BakedModel[]> potPatternModels = null;
private void tryGetModels() {
var models = MinecraftClient.getInstance().getBakedModelManager();
if (this.baseModel == null) {
this.baseModel = models.getModel(ModelIdentifiers.DECORATED_POT_BASE);
}
if (this.potPatternModels == null) {
var builder = ImmutableMap.<RegistryKey<DecoratedPotPattern>, BakedModel[]>builder();
Registries.DECORATED_POT_PATTERN.getKeys().forEach(k -> {
var patternModelIDs = ModelIdentifiers.POTTERY_PATTERNS.get(k);
BakedModel[] patternPerFaceModels = new BakedModel[patternModelIDs.length];
for (int i = 0; i < patternModelIDs.length; i++) {
patternPerFaceModels[i] = models.getModel(patternModelIDs[i]);
}
builder.put(k, patternPerFaceModels);
});
this.potPatternModels = builder.build();
}
}
@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
tryGetModels();
if (blockEntity instanceof DecoratedPotBlockEntity pot) {
matrices.push();
var dir = pot.getHorizontalFacing();
matrices.translate(0.5f, 0, 0.5f);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - EBEUtil.angle(dir)));
matrices.translate(-0.5f, 0, -0.5f);
var wobbleType = pot.lastWobbleType;
if (wobbleType != null && pot.getWorld() != null) {
float tilt = ((float)(pot.getWorld().getTime() - pot.lastWobbleTime) + tickDelta) / (float)wobbleType.lengthInTicks;
if (tilt >= 0.0F && tilt <= 1.0F) {
if (wobbleType == DecoratedPotBlockEntity.WobbleType.POSITIVE) {
float animPeriod = tilt * MathHelper.TAU;
float tiltX = -1.5f * (MathHelper.cos(animPeriod) + 0.5f) * MathHelper.sin(animPeriod * 0.5f);
matrices.multiply(RotationAxis.POSITIVE_X.rotation(tiltX * WOBBLE_STRENGTH), 0.5f, 0f, 0.5f);
float tiltZ = MathHelper.sin(animPeriod);
matrices.multiply(RotationAxis.POSITIVE_Z.rotation(tiltZ * WOBBLE_STRENGTH), 0.5f, 0f, 0.5f);
} else {
float yaw = (1f - tilt) * MathHelper.sin(-tilt * 3 * MathHelper.PI) * 0.125f;
matrices.multiply(RotationAxis.POSITIVE_Y.rotation(yaw), 0.5f, 0f, 0.5f);
}
}
}
var sherds = pot.getSherds();
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices, this.baseModel, light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(
sherds.back().map(DecoratedPotPatterns::fromSherd).orElse(DecoratedPotPatterns.BLANK)
)[0], light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(
sherds.left().map(DecoratedPotPatterns::fromSherd).orElse(DecoratedPotPatterns.BLANK)
)[1], light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(
sherds.right().map(DecoratedPotPatterns::fromSherd).orElse(DecoratedPotPatterns.BLANK)
)[2], light, overlay);
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices,
this.potPatternModels.get(
sherds.front().map(DecoratedPotPatterns::fromSherd).orElse(DecoratedPotPatterns.BLANK)
)[3], light, overlay);
matrices.pop();
}
}
@Override
public void onModelsReload() {
this.baseModel = null;
this.potPatternModels = null;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/ShulkerBoxBlockEntityRendererOverride.java
================================================
package foundationgames.enhancedblockentities.client.render.entity;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.EBEUtil;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.DyeColor;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.RotationAxis;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
public class ShulkerBoxBlockEntityRendererOverride extends BlockEntityRendererOverride {
private final Map<DyeColor, BakedModel> models = new HashMap<>();
private final Consumer<Map<DyeColor, BakedModel>> modelMapFiller;
public ShulkerBoxBlockEntityRendererOverride(Consumer<Map<DyeColor, BakedModel>> modelMapFiller) {
this.modelMapFiller = modelMapFiller;
}
@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
if (models.isEmpty()) modelMapFiller.accept(models);
if (blockEntity instanceof ShulkerBoxBlockEntity entity) {
Direction dir = Direction.UP;
BlockState state = entity.getWorld().getBlockState(entity.getPos());
if (state.getBlock() instanceof ShulkerBoxBlock) {
dir = state.get(ShulkerBoxBlock.FACING);
}
matrices.push();
float animation = entity.getAnimationProgress(tickDelta);
matrices.translate(0.5, 0.5, 0.5);
matrices.multiply(dir.getRotationQuaternion());
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(270 * animation));
matrices.translate(-0.5, -0.5, -0.5);
matrices.translate(0, animation * 0.5f, 0);
var lidModel = models.get(entity.getColor());
if (lidModel != null) {
EBEUtil.renderBakedModel(vertexConsumers, blockEntity.getCachedState(), matrices, lidModel, light, overlay);
}
matrices.pop();
}
}
@Override
public void onModelsReload() {
this.models.clear();
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/SignBlockEntityRendererOverride.java
================================================
package foundationgames.enhancedblockentities.client.render.entity;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import foundationgames.enhancedblockentities.mixin.AbstractSignBlockEntityRenderAccessor;
import net.minecraft.block.AbstractSignBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
public class SignBlockEntityRendererOverride extends BlockEntityRendererOverride {
public SignBlockEntityRendererOverride() {}
@Override
public void render(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
if (blockEntity instanceof SignBlockEntity entity) {
var state = entity.getCachedState();
AbstractSignBlock block = (AbstractSignBlock) state.getBlock();
var sign = (AbstractSignBlockEntityRenderAccessor) renderer;
sign.enhanced_bes$applyTransforms(matrices, -block.getRotationDegrees(state), state);
sign.enhanced_bes$renderText(entity.getPos(), entity.getFrontText(), matrices, vertexConsumers, light, entity.getTextLineHeight(), entity.getMaxTextWidth(), true);
sign.enhanced_bes$renderText(entity.getPos(), entity.getBackText(), matrices, vertexConsumers, light, entity.getTextLineHeight(), entity.getMaxTextWidth(), false);
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/AtlasResourceBuilder.java
================================================
package foundationgames.enhancedblockentities.client.resource;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.mojang.serialization.JsonOps;
import net.minecraft.client.texture.atlas.AtlasSource;
import net.minecraft.client.texture.atlas.AtlasSourceManager;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
public class AtlasResourceBuilder {
private static final Gson GSON = new Gson();
private final List<AtlasSource> sources = new ArrayList<>();
public void put(AtlasSource source) {
sources.add(source);
}
public byte[] toBytes() {
return GSON.toJson(AtlasSourceManager.LIST_CODEC.encode(this.sources, JsonOps.INSTANCE, new JsonObject())
.getOrThrow())
.getBytes(StandardCharsets.UTF_8);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java
================================================
package foundationgames.enhancedblockentities.client.resource;
import foundationgames.enhancedblockentities.client.resource.template.TemplateLoader;
import foundationgames.enhancedblockentities.client.resource.template.TemplateProvider;
import net.minecraft.SharedConstants;
import net.minecraft.client.texture.atlas.AtlasSource;
import net.minecraft.client.texture.atlas.DirectoryAtlasSource;
import net.minecraft.client.texture.atlas.SingleAtlasSource;
import net.minecraft.resource.InputSupplier;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.ResourcePackInfo;
import net.minecraft.resource.ResourcePackSource;
import net.minecraft.resource.ResourceType;
import net.minecraft.resource.metadata.PackResourceMetadata;
import net.minecraft.resource.metadata.ResourceMetadataMap;
import net.minecraft.resource.metadata.ResourceMetadataSerializer;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
public class EBEPack implements ResourcePack {
public static final Identifier BLOCK_ATLAS = Identifier.of("blocks");
private final Map<Identifier, AtlasResourceBuilder> atlases = new HashMap<>();
private final Map<Identifier, InputSupplier<InputStream>> resources = new HashMap<>();
private final Set<String> namespaces = new HashSet<>();
private final TemplateLoader templates;
private final PackResourceMetadata packMeta;
private final ResourcePackInfo packInfo;
public EBEPack(Identifier id, TemplateLoader templates) {
this.templates = templates;
this.packMeta = new PackResourceMetadata(
Text.literal("Enhanced Block Entities Resources"),
SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES),
Optional.empty());
this.packInfo = new ResourcePackInfo(id.toString(), Text.literal(id.toString()), ResourcePackSource.BUILTIN, Optional.empty());
}
public void addAtlasSprite(Identifier atlas, AtlasSource source) {
var resource = this.atlases.computeIfAbsent(atlas, id -> new AtlasResourceBuilder());
resource.put(source);
this.addResource(Identifier.of(atlas.getNamespace(), "atlases/" + atlas.getPath() + ".json"), resource::toBytes);
}
public void addSingleBlockSprite(Identifier path) {
this.addAtlasSprite(BLOCK_ATLAS, new SingleAtlasSource(path, Optional.empty()));
}
public void addDirBlockSprites(String dir, String prefix) {
this.addAtlasSprite(BLOCK_ATLAS, new DirectoryAtlasSource(dir, prefix));
}
public void addResource(Identifier id, InputSupplier<byte[]> resource) {
this.namespaces.add(id.getNamespace());
this.resources.put(id, new LazyBufferedResource(resource));
}
public void addResource(Identifier id, byte[] resource) {
this.namespaces.add(id.getNamespace());
this.resources.put(id, () -> new ByteArrayInputStream(resource));
}
public void addPlainTextResource(Identifier id, String plainText) {
this.addResource(id, plainText.getBytes(StandardCharsets.UTF_8));
}
public void addTemplateResource(Identifier id, TemplateProvider.TemplateApplyingFunction template) {
this.addResource(id, () -> template.getAndApplyTemplate(new TemplateProvider(this.templates)).getBytes(StandardCharsets.UTF_8));
}
public void addTemplateResource(Identifier id, String templatePath) {
this.addTemplateResource(id, t -> t.load(templatePath, d -> {}));
}
@Nullable
@Override
public InputSupplier<InputStream> openRoot(String... segments) {
return null; // Provide no root resources
}
@Nullable
@Override
public InputSupplier<InputStream> open(ResourceType type, Identifier id) {
if (type != ResourceType.CLIENT_RESOURCES) return null;
return this.resources.get(id);
}
@Override
public void findResources(ResourceType type, String namespace, String prefix, ResultConsumer consumer) {
if (type != ResourceType.CLIENT_RESOURCES) return;
for (var entry : this.resources.entrySet()) {
var id = entry.getKey();
if (id.getNamespace().startsWith(namespace) && id.getPath().startsWith(prefix)) {
consumer.accept(id, entry.getValue());
}
}
}
@Override
public Set<String> getNamespaces(ResourceType type) {
if (type != ResourceType.CLIENT_RESOURCES) return Set.of();
return this.namespaces;
}
@Nullable
@Override
public <T> T parseMetadata(ResourceMetadataSerializer<T> meta) {
return ResourceMetadataMap.of(PackResourceMetadata.SERIALIZER, this.packMeta).get(meta);
}
@Override
public ResourcePackInfo getInfo() {
return this.packInfo;
}
@Override
public void close() {
}
public void dump(Path dir) throws IOException {
dir = dir.resolve("assets");
for (var entry : this.resources.entrySet()) {
var id = entry.getKey();
var file = dir.resolve(id.getNamespace()).resolve(id.getPath());
Files.createDirectories(file.getParent());
try (var out = Files.newOutputStream(file)) {
var in = entry.getValue().get();
int i;
while ((i = in.read()) >= 0) {
out.write(i);
}
}
}
}
public static class PropertyBuilder {
private Properties properties = new Properties();
private PropertyBuilder() {}
public PropertyBuilder def(String k, String v) {
if (this.properties != null) {
this.properties.setProperty(k, v);
}
return this;
}
private Properties build() {
var properties = this.properties;
this.properties = null;
return properties;
}
}
public static class LazyBufferedResource implements InputSupplier<InputStream> {
private final InputSupplier<byte[]> backing;
private byte[] buffer = null;
public LazyBufferedResource(InputSupplier<byte[]> backing) {
this.backing = backing;
}
@Override
public InputStream get() throws IOException {
if (buffer == null) {
buffer = backing.get();
}
return new ByteArrayInputStream(buffer);
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateDefinitions.java
================================================
package foundationgames.enhancedblockentities.client.resource.template;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public interface TemplateDefinitions {
default TemplateDefinitions def(String k, Object v) {
return this.def(k, templates -> String.valueOf(v));
}
TemplateDefinitions def(String k, TemplateProvider.TemplateApplyingFunction v);
class Impl implements TemplateDefinitions, Iterable<Map.Entry<String, TemplateProvider.TemplateApplyingFunction>> {
private final Deque<HashMap<String, TemplateProvider.TemplateApplyingFunction>> stack = new ArrayDeque<>();
public void push() {
this.stack.addLast(new HashMap<>());
}
public void pop() {
this.stack.removeLast();
}
public TemplateDefinitions def(String k, String v) {
return this.def(k, templates -> v);
}
public TemplateDefinitions def(String k, TemplateProvider.TemplateApplyingFunction v) {
this.stack.getLast().put(k, v);
return this;
}
@NotNull
@Override
public Iterator<Map.Entry<String, TemplateProvider.TemplateApplyingFunction>> iterator() {
return this.stack.getLast().entrySet().iterator();
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateLoader.java
================================================
package foundationgames.enhancedblockentities.client.resource.template;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class TemplateLoader {
private Path rootPath;
private final Map<String, String> loadedTemplates = new HashMap<>();
public TemplateLoader() {
}
public void setRoot(Path path) {
this.rootPath = path;
}
public String getOrLoadRaw(String path) throws IOException {
if (this.rootPath == null) {
return "";
}
if (this.loadedTemplates.containsKey(path)) {
return this.loadedTemplates.get(path);
}
var file = rootPath.resolve(path);
try (var in = Files.newInputStream(file)) {
var templateRaw = new String(in.readAllBytes(), StandardCharsets.UTF_8);
this.loadedTemplates.put(path, templateRaw);
return templateRaw;
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateProvider.java
================================================
package foundationgames.enhancedblockentities.client.resource.template;
import java.io.IOException;
import java.util.HashMap;
import java.util.function.Consumer;
import java.util.regex.Pattern;
public class TemplateProvider {
private final TemplateLoader loader;
private final TemplateDefinitions.Impl definitions = new TemplateDefinitions.Impl();
public TemplateProvider(TemplateLoader loader) {
this.loader = loader;
}
public String load(String templatePath, Consumer<TemplateDefinitions> definitions) throws IOException {
this.definitions.push();
definitions.accept(this.definitions);
try {
var substitutions = new HashMap<String, String>();
for (var entry : this.definitions) {
substitutions.put(entry.getKey(), entry.getValue().getAndApplyTemplate(this));
}
var templateRaw = this.loader.getOrLoadRaw(templatePath);
var matcher = Pattern.compile("!\\[(" + String.join("|", substitutions.keySet()) + ")]")
.matcher(templateRaw);
var result = new StringBuilder();
while (matcher.find()) {
matcher.appendReplacement(result, substitutions.get(matcher.group(1)));
}
matcher.appendTail(result);
this.definitions.pop();
return result.toString();
} catch (IOException ex) {
this.definitions.pop();
throw ex;
}
}
@FunctionalInterface
public interface TemplateApplyingFunction {
String getAndApplyTemplate(TemplateProvider templates) throws IOException;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java
================================================
package foundationgames.enhancedblockentities.config;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.util.ConvUtil;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.function.BiConsumer;
public class EBEConfig {
public static final String RENDER_ENHANCED_CHESTS_KEY = "render_enhanced_chests";
public static final String RENDER_ENHANCED_SIGNS_KEY = "render_enhanced_signs";
public static final String RENDER_ENHANCED_BELLS_KEY = "render_enhanced_bells";
public static final String RENDER_ENHANCED_BEDS_KEY = "render_enhanced_beds";
public static final String RENDER_ENHANCED_SHULKER_BOXES_KEY = "render_enhanced_shulker_boxes";
public static final String RENDER_ENHANCED_DECORATED_POTS_KEY = "render_enhanced_decorated_pots";
public static final String CHEST_AO_KEY = "chest_ao";
public static final String SIGN_AO_KEY = "sign_ao";
public static final String BELL_AO_KEY = "bell_ao";
public static final String BED_AO_KEY = "bed_ao";
public static final String SHULKER_BOX_AO_KEY = "shulker_box_ao";
public static final String DECORATED_POT_AO_KEY = "decorated_pot_ao";
public static final String CHRISTMAS_CHESTS_KEY = "christmas_chests";
public static final String SIGN_TEXT_RENDERING_KEY = "sign_text_rendering";
public static final String EXPERIMENTAL_CHESTS_KEY = "experimental_chests";
public static final String EXPERIMENTAL_BEDS_KEY = "experimental_beds";
public static final String EXPERIMENTAL_SIGNS_KEY = "experimental_signs";
public static final String FORCE_RESOURCE_PACK_COMPAT_KEY = "force_resource_pack_compat";
public boolean renderEnhancedChests = true;
public boolean renderEnhancedSigns = true;
public boolean renderEnhancedBells = true;
public boolean renderEnhancedBeds = true;
public boolean renderEnhancedShulkerBoxes = true;
public boolean renderEnhancedDecoratedPots = true;
public boolean chestAO = false;
public boolean signAO = false;
public boolean bellAO = true;
public boolean bedAO = false;
public boolean shulkerBoxAO = false;
public boolean decoratedPotAO = false;
public String christmasChests = "allowed";
public String signTextRendering = "smart";
public boolean experimentalChests = true;
public boolean experimentalBeds = true;
public boolean experimentalSigns = true;
public boolean forceResourcePackCompat = false;
public final Map<String, Override> overrides = new HashMap<>();
public void writeTo(Properties properties) {
properties.setProperty(RENDER_ENHANCED_CHESTS_KEY, Boolean.toString(renderEnhancedChests));
properties.setProperty(RENDER_ENHANCED_SIGNS_KEY, Boolean.toString(renderEnhancedSigns));
properties.setProperty(RENDER_ENHANCED_BELLS_KEY, Boolean.toString(renderEnhancedBells));
properties.setProperty(RENDER_ENHANCED_BEDS_KEY, Boolean.toString(renderEnhancedBeds));
properties.setProperty(RENDER_ENHANCED_SHULKER_BOXES_KEY, Boolean.toString(renderEnhancedShulkerBoxes));
properties.setProperty(RENDER_ENHANCED_DECORATED_POTS_KEY, Boolean.toString(renderEnhancedDecoratedPots));
properties.setProperty(CHEST_AO_KEY, Boolean.toString(chestAO));
properties.setProperty(SIGN_AO_KEY, Boolean.toString(signAO));
properties.setProperty(BELL_AO_KEY, Boolean.toString(bellAO));
properties.setProperty(BED_AO_KEY, Boolean.toString(bedAO));
properties.setProperty(SHULKER_BOX_AO_KEY, Boolean.toString(shulkerBoxAO));
properties.setProperty(DECORATED_POT_AO_KEY, Boolean.toString(decoratedPotAO));
properties.setProperty(CHRISTMAS_CHESTS_KEY, christmasChests);
properties.setProperty(SIGN_TEXT_RENDERING_KEY, signTextRendering);
properties.setProperty(EXPERIMENTAL_CHESTS_KEY, Boolean.toString(experimentalChests));
properties.setProperty(EXPERIMENTAL_BEDS_KEY, Boolean.toString(experimentalBeds));
properties.setProperty(EXPERIMENTAL_SIGNS_KEY, Boolean.toString(experimentalSigns));
properties.setProperty(FORCE_RESOURCE_PACK_COMPAT_KEY, Boolean.toString(forceResourcePackCompat));
}
public void readFrom(Properties properties) {
this.renderEnhancedChests = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_CHESTS_KEY), true);
this.renderEnhancedSigns = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_SIGNS_KEY), true);
this.renderEnhancedBells = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_BELLS_KEY), true);
this.renderEnhancedBeds = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_BEDS_KEY), true);
this.renderEnhancedShulkerBoxes = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_SHULKER_BOXES_KEY), true);
this.renderEnhancedDecoratedPots = ConvUtil.defaultedBool(properties.getProperty(RENDER_ENHANCED_DECORATED_POTS_KEY), true);
String pCC = properties.getProperty(CHRISTMAS_CHESTS_KEY);
if (pCC != null && (pCC.equals("allowed") || pCC.equals("forced") || pCC.equals("disabled"))) {
this.christmasChests = pCC;
} else {
EnhancedBlockEntities.LOG.warn("Configuration option 'christmas_chests' must be one of: 'allowed', 'forced', 'disabled'");
this.christmasChests = "allowed";
}
String sST = properties.getProperty(SIGN_TEXT_RENDERING_KEY);
if (sST != null && (sST.equals("smart") || sST.equals("all") || sST.equals("most") || sST.equals("some") || sST.equals("few"))) {
this.signTextRendering = sST;
} else {
EnhancedBlockEntities.LOG.warn("Configuration option 'sign_text_rendering' must be one of: 'smart', 'all', 'most', 'some', 'few'");
this.signTextRendering = "smart";
}
this.chestAO = ConvUtil.defaultedBool(properties.getProperty(CHEST_AO_KEY), false);
this.signAO = ConvUtil.defaultedBool(properties.getProperty(SIGN_AO_KEY), false);
this.bellAO = ConvUtil.defaultedBool(properties.getProperty(BELL_AO_KEY), true);
this.bedAO = ConvUtil.defaultedBool(properties.getProperty(BED_AO_KEY), false);
this.shulkerBoxAO = ConvUtil.defaultedBool(properties.getProperty(SHULKER_BOX_AO_KEY), false);
this.decoratedPotAO = ConvUtil.defaultedBool(properties.getProperty(DECORATED_POT_AO_KEY), false);
this.experimentalChests = ConvUtil.defaultedBool(properties.getProperty(EXPERIMENTAL_CHESTS_KEY), true);
this.experimentalBeds = ConvUtil.defaultedBool(properties.getProperty(EXPERIMENTAL_BEDS_KEY), true);
this.experimentalSigns = ConvUtil.defaultedBool(properties.getProperty(EXPERIMENTAL_SIGNS_KEY), true);
this.forceResourcePackCompat = ConvUtil.defaultedBool(properties.getProperty(FORCE_RESOURCE_PACK_COMPAT_KEY), false);
}
public void save() {
Properties properties = new Properties();
writeTo(properties);
Path configPath = FabricLoader.getInstance().getConfigDir().resolve("enhanced_bes.properties");
if (!Files.exists(configPath)) {
try {
Files.createFile(configPath);
} catch (IOException e) {
EnhancedBlockEntities.LOG.error("Failed to create configuration file!", e);
return;
}
}
try {
properties.store(Files.newOutputStream(configPath), "Configuration file for Enhanced Block Entities");
} catch (IOException e) {
EnhancedBlockEntities.LOG.error("Failed to write to configuration file!", e);
}
}
public void load() {
Properties properties = new Properties();
Path configPath = FabricLoader.getInstance().getConfigDir().resolve("enhanced_bes.properties");
if (!Files.exists(configPath)) {
try {
Files.createFile(configPath);
save();
} catch (IOException e) {
EnhancedBlockEntities.LOG.error("Failed to create configuration file!", e);
return;
}
}
try {
properties.load(Files.newInputStream(configPath));
} catch (IOException e) {
EnhancedBlockEntities.LOG.error("Failed to read configuration file!", e);
return;
}
applyCompatConfigModifiers(properties);
readFrom(properties);
}
@SuppressWarnings("unchecked")
private void applyCompatConfigModifiers(Properties properties) {
this.overrides.clear();
var ebeCompatCfgModifiers = FabricLoader.getInstance()
.getEntrypointContainers(EnhancedBlockEntities.API_V1, BiConsumer.class);
for (var modifier : ebeCompatCfgModifiers) {
var mod = modifier.getProvider();
var overrides = new Properties();
var reasons = new HashMap<String, Text>();
modifier.getEntrypoint().accept(overrides, reasons);
for (var key : overrides.stringPropertyNames()) {
@Nullable Text reason = reasons.get(key);
this.overrides.put(key, new Override(mod, reason));
}
properties.putAll(overrides);
}
}
public record Override(ModContainer modResponsible, @Nullable Text reason) {}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/EBEModMenuPlugin.java
================================================
package foundationgames.enhancedblockentities.config.gui;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import foundationgames.enhancedblockentities.config.gui.screen.EBEConfigScreen;
public class EBEModMenuPlugin implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return EBEConfigScreen::new;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/option/ConfigButtonOption.java
================================================
package foundationgames.enhancedblockentities.config.gui.option;
import com.mojang.serialization.Codec;
import foundationgames.enhancedblockentities.config.gui.screen.EBEConfigScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.SimpleOption;
import net.minecraft.text.Text;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class ConfigButtonOption {
public static SimpleOption<?> getOption(Screen parent) {
return new SimpleOption<>(
"option.ebe.config",
SimpleOption.emptyTooltip(),
(title, object) -> title,
new ConfigButtonCallbacks<>(parent),
Optional.empty(),
value -> {
}
);
}
private record ConfigButtonCallbacks<T>(Screen parent) implements SimpleOption.Callbacks<T> {
@Override
public Function<SimpleOption<T>, ClickableWidget> getWidgetCreator(SimpleOption.TooltipFactory<T> tooltipFactory, GameOptions gameOptions, int x, int y, int width, Consumer<T> changed) {
return (option) -> ButtonWidget.builder(Text.translatable("option.ebe.config"), b -> {
MinecraftClient.getInstance().setScreen(new EBEConfigScreen(parent));
}).dimensions(x, y, width, 20).build();
}
@Override
public Optional<T> validate(T value) {
return Optional.empty();
}
@Override
public Codec<T> codec() {
return null;
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java
================================================
package foundationgames.enhancedblockentities.config.gui.option;
import foundationgames.enhancedblockentities.ReloadType;
import foundationgames.enhancedblockentities.config.EBEConfig;
import foundationgames.enhancedblockentities.util.GuiUtil;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public final class EBEOption {
private static final Text NEWLINE = Text.of("\n");
private static final String OPTION_VALUE = "options.generic_value";
private static final String DIVIDER = "text.ebe.option_value_division";
private static final String OVERRIDDEN = "warning.ebe.overridden";
public final String key;
public final boolean hasValueComments;
public final Text comment;
public final ReloadType reloadType;
public final TextPalette palette;
public final @Nullable EBEConfig.Override override;
private final List<String> values;
private final int defaultValue;
private int selected;
private Tooltip tooltip = null;
private Text text = null;
public EBEOption(String key, List<String> values, ConfigView config, boolean hasValueComments, TextPalette palette, ReloadType reloadType) {
this.key = key;
this.values = values;
this.defaultValue = MathHelper.clamp(values.indexOf(config.configValues.getProperty(key)), 0, values.size());
this.override = config.overrides.get(key);
this.selected = this.defaultValue;
this.hasValueComments = hasValueComments;
this.palette = palette;
this.reloadType = reloadType;
String commentKey = I18n.translate(String.format("option.ebe.%s.comment", key));
comment = GuiUtil.shorten(commentKey, 20);
}
public String getValue() {
return values.get(selected);
}
public String getOptionKey() {
return String.format("option.ebe.%s", key);
}
public String getValueKey() {
return String.format("value.ebe.%s", getValue());
}
public Text getText() {
var option = Text.translatable(this.getOptionKey()).styled(style -> style.withColor(isDefault() ? 0xFFFFFF : 0xFFDA5E));
var value = Text.translatable(this.getValueKey()).styled(style -> style.withColor(this.palette.getColor((float)this.selected / this.values.size())));
if (text == null) text = option.append(Text.translatable(DIVIDER).append(value));
return text;
}
public Tooltip getTooltip() {
if (tooltip == null) {
if (override != null) {
var text = Text.translatable(OVERRIDDEN, override.modResponsible().getMetadata().getId())
.formatted(Formatting.RED, Formatting.UNDERLINE);
if (override.reason() != null) {
text.append(NEWLINE).append(override.reason());
}
tooltip = Tooltip.of(text);
}
else if (hasValueComments) tooltip = Tooltip.of(Text.translatable(String.format("option.ebe.%s.valueComment.%s", key, getValue())).append(NEWLINE).append(comment.copyContentOnly()));
else tooltip = Tooltip.of(comment.copyContentOnly());
}
return tooltip;
}
public void next() {
selected++;
if (selected >= values.size()) selected = 0;
tooltip = null;
text = null;
}
public boolean isDefault() {
return selected == defaultValue;
}
public record ConfigView(Properties configValues, Map<String, EBEConfig.Override> overrides) {}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/option/TextPalette.java
================================================
package foundationgames.enhancedblockentities.config.gui.option;
public interface TextPalette {
TextPalette ON_OFF = opt -> (opt < 0.5f) ? 0x74ff45 : 0xff6745;
/**
* Return a color based on the amount the option has been cycled through
*
* @param cycle a value 0-1 representing the progress cycling this palette
* @return a RGB color integer
*/
int getColor(float cycle);
static TextPalette rainbow(float start) {
return opt -> {
opt += start;
float r = 0.5f * (float)Math.cos(2 * Math.PI * opt) + 0.5f;
float g = 0.5f * (float)Math.cos(2 * Math.PI * (opt - 0.333333333f)) + 0.5f;
float b = 0.5f * (float)Math.cos(2 * Math.PI * (opt - 0.666666666f)) + 0.5f;
return ((int)(r * 255) << 16) | ((int)(g * 255) << 8) | (int)(b * 255);
};
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java
================================================
package foundationgames.enhancedblockentities.config.gui.screen;
import com.google.common.collect.ImmutableList;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.ReloadType;
import foundationgames.enhancedblockentities.config.EBEConfig;
import foundationgames.enhancedblockentities.config.gui.option.EBEOption;
import foundationgames.enhancedblockentities.config.gui.option.TextPalette;
import foundationgames.enhancedblockentities.config.gui.widget.SectionTextWidget;
import foundationgames.enhancedblockentities.config.gui.widget.WidgetRowListWidget;
import foundationgames.enhancedblockentities.util.EBEUtil;
import foundationgames.enhancedblockentities.util.GuiUtil;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.GridWidget;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
public class EBEConfigScreen extends Screen {
private WidgetRowListWidget optionsWidget;
private final List<EBEOption> options = new ArrayList<>();
private final Screen parent;
private static final ImmutableList<String> BOOLEAN_OPTIONS = ImmutableList.of("true", "false");
private static final ImmutableList<String> ALLOWED_FORCED_DISABLED = ImmutableList.of("allowed", "forced", "disabled");
private static final ImmutableList<String> SIGN_TEXT_OPTIONS = ImmutableList.of("smart", "all", "most", "some", "few");
private static final Text HOLD_SHIFT = Text.translatable("text.ebe.descriptions").formatted(Formatting.GRAY, Formatting.ITALIC);
private static final Text CHEST_OPTIONS_TITLE = Text.translatable("text.ebe.chest_options");
private static final Text SIGN_OPTIONS_TITLE = Text.translatable("text.ebe.sign_options");
private static final Text BELL_OPTIONS_TITLE = Text.translatable("text.ebe.bell_options");
private static final Text BED_OPTIONS_TITLE = Text.translatable("text.ebe.bed_options");
private static final Text SHULKER_BOX_OPTIONS_TITLE = Text.translatable("text.ebe.shulker_box_options");
private static final Text DECORATED_POT_OPTIONS_TITLE = Text.translatable("text.ebe.decorated_pot_options");
private static final Text ADVANCED_TITLE = Text.translatable("text.ebe.advanced");
private static final Text DUMP_LABEL = Text.translatable("option.ebe.dump");
private final Text dumpTooltip = GuiUtil.shorten(I18n.translate("option.ebe.dump.comment"), 20);
public EBEConfigScreen(Screen screen) {
super(Text.translatable("screen.ebe.config"));
parent = screen;
}
@Override
protected void init() {
super.init();
this.optionsWidget = new WidgetRowListWidget(this.client, this.width, this.height - 69, 34, 316, 20);
this.options.clear();
addOptions();
this.addDrawableChild(optionsWidget);
var menuButtons = new GridWidget();
menuButtons.setColumnSpacing(4);
var menuButtonAdder = menuButtons.createAdder(3);
menuButtonAdder.add(ButtonWidget.builder(ScreenTexts.CANCEL, button -> this.close())
.size(100, 20).build());
menuButtonAdder.add(ButtonWidget.builder(Text.translatable("text.ebe.apply"), button -> this.applyChanges())
.size(100, 20).build());
menuButtonAdder.add(ButtonWidget.builder(ScreenTexts.DONE,
button -> {
applyChanges();
close();
})
.size(100, 20).build());
menuButtons.refreshPositions();
menuButtons.setPosition((this.width - menuButtons.getWidth()) / 2, this.height - 27);
menuButtons.forEachChild((child) -> {
child.setNavigationOrder(1);
this.addDrawableChild(child);
});
}
@Override
protected void renderDarkening(DrawContext context) {
renderDarkening(context, 0, 0, this.width, 34);
renderDarkening(context, 0, this.height - 35, this.width, 35);
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta);
context.drawCenteredTextWithShadow(this.textRenderer, this.title, (int)(this.width * 0.5), 8, 0xFFFFFF);
context.drawCenteredTextWithShadow(this.textRenderer, HOLD_SHIFT, (int)(this.width * 0.5), 21, 0xFFFFFF);
}
@Override
public void close() {
this.client.setScreen(parent);
}
public void applyChanges() {
EBEConfig config = EnhancedBlockEntities.CONFIG;
Properties properties = new Properties();
AtomicReference<ReloadType> type = new AtomicReference<>(ReloadType.NONE);
options.forEach(option -> {
if (!option.isDefault()) {
type.set(type.get().or(option.reloadType));
}
properties.setProperty(option.key, option.getValue());
});
config.readFrom(properties);
config.save();
EnhancedBlockEntities.reload(type.get());
}
public void addOptions() {
Properties config = new Properties();
EnhancedBlockEntities.CONFIG.writeTo(config);
final var configView = new EBEOption.ConfigView(config, EnhancedBlockEntities.CONFIG.overrides);
final var textRenderer = this.client.textRenderer;
optionsWidget.add(new SectionTextWidget(CHEST_OPTIONS_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.RENDER_ENHANCED_CHESTS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.CHEST_AO_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.EXPERIMENTAL_CHESTS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
), option(
new EBEOption(EBEConfig.CHRISTMAS_CHESTS_KEY, ALLOWED_FORCED_DISABLED, configView, true, TextPalette.rainbow(0.35f), ReloadType.WORLD)
));
optionsWidget.add(new SectionTextWidget(SIGN_OPTIONS_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.RENDER_ENHANCED_SIGNS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.SIGN_TEXT_RENDERING_KEY, SIGN_TEXT_OPTIONS, configView, true, TextPalette.rainbow(0.45f), ReloadType.NONE)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.EXPERIMENTAL_SIGNS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
), option(
new EBEOption(EBEConfig.SIGN_AO_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(new SectionTextWidget(BELL_OPTIONS_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.RENDER_ENHANCED_BELLS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.BELL_AO_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(new SectionTextWidget(BED_OPTIONS_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.RENDER_ENHANCED_BEDS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.EXPERIMENTAL_BEDS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
), option(
new EBEOption(EBEConfig.BED_AO_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(new SectionTextWidget(SHULKER_BOX_OPTIONS_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.RENDER_ENHANCED_SHULKER_BOXES_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.SHULKER_BOX_AO_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(new SectionTextWidget(DECORATED_POT_OPTIONS_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.RENDER_ENHANCED_DECORATED_POTS_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(option(
new EBEOption(EBEConfig.DECORATED_POT_AO_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(new SectionTextWidget(ADVANCED_TITLE, textRenderer));
optionsWidget.add(option(
new EBEOption(EBEConfig.FORCE_RESOURCE_PACK_COMPAT_KEY, BOOLEAN_OPTIONS, configView, false, TextPalette.ON_OFF, ReloadType.RESOURCES)
));
optionsWidget.add(ButtonWidget.builder(DUMP_LABEL, b -> {
try {
EBEUtil.dumpResources();
} catch (IOException e) {
EnhancedBlockEntities.LOG.error(e);
}
}).tooltip(Tooltip.of(dumpTooltip)).build());
}
private ButtonWidget option(EBEOption option) {
options.add(option);
var button = ButtonWidget.builder(option.getText(), b -> {
option.next();
b.setMessage(option.getText());
b.setTooltip(option.getTooltip());
}).tooltip(option.getTooltip()).build();
if (option.override != null) {
button.active = false;
}
return button;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/widget/SectionTextWidget.java
================================================
package foundationgames.enhancedblockentities.config.gui.widget;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.widget.AbstractTextWidget;
import net.minecraft.text.Text;
public class SectionTextWidget extends AbstractTextWidget {
public SectionTextWidget(Text message, TextRenderer textRenderer) {
this(0, 0, 200, 20, message, textRenderer);
}
public SectionTextWidget(int x, int y, int width, int height, Text message, TextRenderer textRenderer) {
super(x, y, width, height, message, textRenderer);
this.active = false;
}
@Override
public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) {
final int white = 0xFFFFFFFF;
var font = this.getTextRenderer();
var msg = this.getMessage();
int l = this.getX();
int w = this.getWidth();
int r = l + w;
int y = (this.getY() + this.getHeight()) - 6;
int tx = l + (w / 2);
int ty = y - (font.fontHeight / 2);
int tw = font.getWidth(msg);
int ml = l + ((w - tw) / 2) - 5;
int mr = ml + tw + 10;
l += 1;
r -= 1;
context.fill(l, y, ml, y + 2, white);
context.fill(mr, y, r, y + 2, white);
context.drawCenteredTextWithShadow(font, msg, tx, ty, 0xFFFFFF);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/widget/WidgetRowListWidget.java
================================================
package foundationgames.enhancedblockentities.config.gui.widget;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.widget.ClickableWidget;
import net.minecraft.client.gui.widget.ElementListWidget;
import net.minecraft.client.gui.widget.GridWidget;
import java.util.ArrayList;
import java.util.List;
public class WidgetRowListWidget extends ElementListWidget<WidgetRowListWidget.Entry> {
public static final int SPACING = 3;
public final int rowWidth;
public final int rowHeight;
public WidgetRowListWidget(MinecraftClient mc, int w, int h, int y, int rowWidth, int rowHeight) {
super(mc, w, h, y, rowHeight + SPACING);
this.rowWidth = rowWidth;
this.rowHeight = rowHeight;
}
public void add(ClickableWidget ... widgets) {
if (widgets.length == 0) return;
var grid = new GridWidget();
grid.setColumnSpacing(SPACING);
var adder = grid.createAdder(widgets.length);
int width = (this.rowWidth - ((widgets.length - 1) * SPACING)) / widgets.length;
for (var widget : widgets) {
widget.setDimensions(width, this.rowHeight);
adder.add(widget);
}
grid.refreshPositions();
this.addEntry(new Entry(grid));
}
@Override
public int getRowWidth() {
return rowWidth;
}
@Override
protected int getScrollbarX() {
return this.width - 6;
}
@Override
protected void drawMenuListBackground(DrawContext context) {
}
public static class Entry extends ElementListWidget.Entry<Entry> {
private final GridWidget widget;
private final List<ClickableWidget> children = new ArrayList<>();
public Entry(GridWidget widget) {
this.widget = widget;
widget.forEachChild(children::add);
}
@Override
public List<? extends Element> children() {
return this.children;
}
@Override
public List<? extends Selectable> selectableChildren() {
return this.children;
}
@Override
public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
this.widget.setPosition(x - 3, y);
this.widget.refreshPositions();
this.widget.forEachChild(c -> c.render(context, mouseX, mouseY, tickDelta));
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java
================================================
package foundationgames.enhancedblockentities.event;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public enum EBEEvents {;
public static final Event<Runnable> RESOURCE_RELOAD = EventFactory.createArrayBacked(Runnable.class, (callbacks) -> () -> {
for (var event : callbacks) {
event.run();
}
});
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.EnhancedBlockEntityRegistry;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(AbstractBlock.AbstractBlockState.class)
public abstract class AbstractBlockStateMixin {
@Shadow public abstract Block getBlock();
@Inject(method = "getRenderType", at = @At("HEAD"), cancellable = true)
public void enhanced_bes$overrideRenderType(CallbackInfoReturnable<BlockRenderType> cir) {
Block block = this.getBlock();
if (EnhancedBlockEntityRegistry.BLOCKS.contains(block)) {
cir.setReturnValue(BlockRenderType.MODEL);
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/AbstractSignBlockEntityRenderAccessor.java
================================================
package foundationgames.enhancedblockentities.mixin;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.SignText;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.block.entity.AbstractSignBlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(AbstractSignBlockEntityRenderer.class)
public interface AbstractSignBlockEntityRenderAccessor {
@Invoker("applyTransforms")
void enhanced_bes$applyTransforms(MatrixStack matrices, float rotationDegrees, BlockState state);
@Invoker("renderText")
void enhanced_bes$renderText(BlockPos pos, SignText signText, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int lineHeight, int lineWidth, boolean front);
@Accessor("MAX_COLORED_TEXT_OUTLINE_RENDER_DISTANCE")
static int enhanced_bes$getRenderDistance() {
throw new AssertionError();
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BellBlockEntity;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.math.BlockPos;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@Mixin(BellBlockEntity.class)
public class BellBlockEntityMixin extends BlockEntity implements AppearanceStateHolder {
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;
public BellBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
// Can't inject because one of the args' type is private (BellBlockEntity$Effect) and I don't feel like AW
// So now you get to suffer through this
@ModifyVariable(method = "tick", at = @At(
value = "JUMP", opcode = Opcodes.IF_ICMPLT, ordinal = 0, shift = At.Shift.BEFORE
), index = 3)
private static BellBlockEntity enhanced_bes$listenForStopRinging(BellBlockEntity blockEntity) {
int mState = blockEntity.ringTicks > 0 ? 1 : 0;
if (EnhancedBlockEntities.CONFIG.renderEnhancedBells && ((AppearanceStateHolder)blockEntity).getModelState() != mState) {
((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, blockEntity.getWorld(), blockEntity.getPos());
}
return blockEntity;
}
@Override
public int getModelState() {
return enhanced_bes$modelState;
}
@Override
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}
@Override
public int getRenderState() {
return enhanced_bes$renderState;
}
@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.EnhancedBlockEntityRegistry;
import foundationgames.enhancedblockentities.client.render.BlockEntityRenderCondition;
import foundationgames.enhancedblockentities.client.render.BlockEntityRendererOverride;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Pair;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(BlockEntityRenderDispatcher.class)
public class BlockEntityRenderDispatcherMixin {
@Inject(
method = "render(Lnet/minecraft/client/render/block/entity/BlockEntityRenderer;Lnet/minecraft/block/entity/BlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;)V",
at = @At("HEAD"),
cancellable = true
)
private static void enhanced_bes$renderOverrides(BlockEntityRenderer<BlockEntity> renderer, BlockEntity blockEntity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (EnhancedBlockEntityRegistry.ENTITIES.containsKey(blockEntity.getType()) && EnhancedBlockEntityRegistry.BLOCKS.contains(blockEntity.getCachedState().getBlock())) {
Pair<BlockEntityRenderCondition, BlockEntityRendererOverride> entry = EnhancedBlockEntityRegistry.ENTITIES.get(blockEntity.getType());
if (entry.getLeft().shouldRender(blockEntity)) {
entry.getRight().render(renderer, blockEntity, tickDelta, matrices, vertexConsumers, WorldRenderer.getLightmapCoordinates(blockEntity.getWorld(), blockEntity.getPos()), OverlayTexture.DEFAULT_UV);
}
ci.cancel();
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/BuiltChunkMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess;
import net.minecraft.client.render.chunk.ChunkBuilder;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(ChunkBuilder.BuiltChunk.class)
public class BuiltChunkMixin implements ChunkRebuildTaskAccess {
private @Unique
@Nullable Runnable enhanced_bes$taskAfterRebuild = null;
@Override
public Runnable enhanced_bes$getTaskAfterRebuild() {
return enhanced_bes$taskAfterRebuild;
}
@Override
public void enhanced_bes$setTaskAfterRebuild(Runnable task) {
enhanced_bes$taskAfterRebuild = task;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ChestBlockEntity.class)
public abstract class ChestBlockEntityMixin extends BlockEntity implements AppearanceStateHolder {
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;
private ChestBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Inject(method = "clientTick", at = @At(value = "TAIL"))
private static void enhanced_bes$listenForOpenClose(World world, BlockPos pos, BlockState state, ChestBlockEntity blockEntity, CallbackInfo ci) {
var lid = ChestBlockEntityRendererOverride.getLidAnimationHolder(blockEntity, 0.5f);
int mState = lid.getAnimationProgress(0.5f) > 0 ? 1 : 0;
if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((AppearanceStateHolder)blockEntity).getModelState() != mState) {
((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, world, pos);
}
}
@Override
public int getModelState() {
return enhanced_bes$modelState;
}
@Override
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}
@Override
public int getRenderState() {
return enhanced_bes$renderState;
}
@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.util.WorldUtil;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.entity.DecoratedPotBlockEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.RegistryWrapper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DecoratedPotBlockEntity.class)
public class DecoratedPotBlockEntityMixin implements AppearanceStateHolder {
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;
@Inject(method = "readNbt", at = @At("TAIL"))
private void enhanced_bes$updateChunkOnPatternsLoaded(NbtCompound nbt, RegistryWrapper.WrapperLookup rwl, CallbackInfo ci) {
var self = (DecoratedPotBlockEntity)(Object)this;
if (self.getWorld() != null && self.getWorld().isClient()) {
WorldUtil.rebuildChunk(self.getWorld(), self.getPos());
}
}
@Inject(method = "onSyncedBlockEvent", at = @At(value = "RETURN", shift = At.Shift.BEFORE, ordinal = 0))
private void enhanced_bes$updateOnWobble(int type, int data, CallbackInfoReturnable<Boolean> cir) {
var self = (DecoratedPotBlockEntity)(Object)this;
var world = self.getWorld();
if (self.lastWobbleType == null) {
return;
}
this.updateAppearanceState(1, world, self.getPos());
WorldUtil.scheduleTimed(world, self.lastWobbleTime + self.lastWobbleType.lengthInTicks,
() -> {
if (self.getWorld().getTime() >= self.lastWobbleTime + self.lastWobbleType.lengthInTicks) {
this.updateAppearanceState(0, world, self.getPos());
}
});
}
@Override
public int getModelState() {
return enhanced_bes$modelState;
}
@Override
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}
@Override
public int getRenderState() {
return enhanced_bes$renderState;
}
@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.client.render.entity.ChestBlockEntityRendererOverride;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.EnderChestBlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(EnderChestBlockEntity.class)
public abstract class EnderChestBlockEntityMixin extends BlockEntity implements AppearanceStateHolder {
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;
private EnderChestBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Inject(method = "clientTick", at = @At(value = "TAIL"))
private static void enhanced_bes$listenForOpenClose(World world, BlockPos pos, BlockState state, EnderChestBlockEntity blockEntity, CallbackInfo ci) {
var lid = ChestBlockEntityRendererOverride.getLidAnimationHolder(blockEntity, 0.5f);
int mState = lid.getAnimationProgress(0.5f) > 0 ? 1 : 0;
if (EnhancedBlockEntities.CONFIG.renderEnhancedChests && ((AppearanceStateHolder)blockEntity).getModelState() != mState) {
((AppearanceStateHolder)blockEntity).updateAppearanceState(mState, world, pos);
}
}
@Override
public int getModelState() {
return enhanced_bes$modelState;
}
@Override
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}
@Override
public int getRenderState() {
return enhanced_bes$renderState;
}
@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/LifecycledResourceManagerImplMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.util.EBEUtil;
import foundationgames.enhancedblockentities.util.ResourceUtil;
import foundationgames.enhancedblockentities.util.hacks.ExperimentalSetup;
import net.minecraft.resource.LifecycledResourceManagerImpl;
import net.minecraft.resource.NamespaceResourceManager;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourcePack;
import net.minecraft.resource.ResourceType;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Mixin(LifecycledResourceManagerImpl.class)
public abstract class LifecycledResourceManagerImplMixin {
@Shadow @Final private Map<String, NamespaceResourceManager> subManagers;
@ModifyVariable(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/List;copyOf(Ljava/util/Collection;)Ljava/util/List;", shift = At.Shift.BEFORE), ordinal = 0)
private List<ResourcePack> enhanced_bes$injectBasePack(List<ResourcePack> old) {
var packs = new ArrayList<>(old);
int idx = 0;
if (packs.size() > 0) do {
idx++;
} while (idx < packs.size() && !EBEUtil.isVanillaResourcePack(packs.get(idx - 1)));
packs.add(idx, ResourceUtil.getBasePack());
return packs;
}
@Inject(method = "<init>", at = @At(value = "TAIL"))
private void enhanced_bes$injectTopLevelPack(ResourceType type, List<ResourcePack> packs, CallbackInfo ci) {
ExperimentalSetup.cacheResources((ResourceManager) this);
ExperimentalSetup.setup();
addPack(type, ResourceUtil.getTopLevelPack());
}
private void addPack(ResourceType type, ResourcePack pack) {
for (var namespace : pack.getNamespaces(type)) {
this.subManagers.computeIfAbsent(namespace, n -> new NamespaceResourceManager(type, n)).addPack(pack);
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/MinecraftClientMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.event.EBEEvents;
import net.minecraft.client.MinecraftClient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.concurrent.CompletableFuture;
@Mixin(MinecraftClient.class)
public class MinecraftClientMixin {
@Inject(method = "reloadResources()Ljava/util/concurrent/CompletableFuture;",
at = @At("RETURN"))
private void enhanced_bes$fireReloadEvent(CallbackInfoReturnable<CompletableFuture<Void>> cir) {
cir.getReturnValue().thenAccept(v -> EBEEvents.RESOURCE_RELOAD.invoker().run());
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.util.duck.AppearanceStateHolder;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ShulkerBoxBlockEntity.class)
public abstract class ShulkerBoxBlockEntityMixin extends BlockEntity implements AppearanceStateHolder {
@Shadow public abstract float getAnimationProgress(float delta);
@Unique private int enhanced_bes$modelState = 0;
@Unique private int enhanced_bes$renderState = 0;
public ShulkerBoxBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Inject(method = "updateAnimation", at = @At("TAIL"))
private void enhanced_bes$updateModelState(World world, BlockPos pos, BlockState state, CallbackInfo ci) {
int mState = this.getAnimationProgress(0) > 0 ? 1 : 0;
if (mState != enhanced_bes$modelState) updateAppearanceState(mState, world, pos);
}
@Override
public int getModelState() {
return enhanced_bes$modelState;
}
@Override
public void setModelState(int state) {
this.enhanced_bes$modelState = state;
}
@Override
public int getRenderState() {
return enhanced_bes$renderState;
}
@Override
public void setRenderState(int state) {
this.enhanced_bes$renderState = state;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/SignEditScreenMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.EnhancedBlockEntityRegistry;
import foundationgames.enhancedblockentities.util.EBEUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.ingame.SignEditScreen;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.state.property.Properties;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(SignEditScreen.class)
public class SignEditScreenMixin {
@Inject(method = "renderSignBackground", at = @At("HEAD"), cancellable = true)
private void enhanced_bes$renderBakedModelSign(DrawContext context, CallbackInfo ci) {
BlockState state = ((SignEditScreen) (Object) this).blockEntity.getCachedState();
boolean enhanceSigns = EnhancedBlockEntities.CONFIG.renderEnhancedSigns;
if (!EnhancedBlockEntityRegistry.BLOCKS.contains(state.getBlock())) return;
if (enhanceSigns) {
var models = MinecraftClient.getInstance().getBakedModelManager().getBlockModels();
var buffers = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers();
float up = 0;
if (state.contains(Properties.HORIZONTAL_FACING)) {
state = state.with(Properties.HORIZONTAL_FACING, Direction.SOUTH);
up += 5f/16;
} else if (state.contains(Properties.ROTATION)) {
state = state.with(Properties.ROTATION, 0);
}
var signModel = models.getModel(state);
var matrices = context.getMatrices();
matrices.push();
matrices.translate(0, 31, -50);
matrices.scale(93.75f, -93.75f, 93.75f);
matrices.translate(-0.5, up - 0.5, 0);
EBEUtil.renderBakedModel(buffers, state, matrices, signModel, 15728880, OverlayTexture.DEFAULT_UV);
matrices.pop();
ci.cancel();
}
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.config.gui.option.ConfigButtonOption;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.option.VideoOptionsScreen;
import net.minecraft.client.option.SimpleOption;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@Mixin(VideoOptionsScreen.class)
public abstract class VideoOptionsScreenMixin extends Screen {
protected VideoOptionsScreenMixin(Text title) {
super(title);
}
@ModifyArg(
method = "addOptions",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gui/widget/OptionListWidget;addAll([Lnet/minecraft/client/option/SimpleOption;)V"
),
index = 0
)
private SimpleOption<?>[] enhanced_bes$addEBEOptionButton(SimpleOption<?>[] old) {
var options = new SimpleOption<?>[old.length + 1];
System.arraycopy(old, 0, options, 0, old.length);
options[options.length - 1] = ConfigButtonOption.getOption(this);
return options;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java
================================================
package foundationgames.enhancedblockentities.mixin;
import foundationgames.enhancedblockentities.util.WorldUtil;
import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.chunk.ChunkBuilder;
import net.minecraft.util.math.ChunkSectionPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(WorldRenderer.class)
public class WorldRendererMixin {
@ModifyVariable(method = "updateChunks",
at = @At(value = "INVOKE", shift = At.Shift.BEFORE, ordinal = 0, target = "Lnet/minecraft/client/option/SimpleOption;getValue()Ljava/lang/Object;"),
index = 7)
private ChunkBuilder.BuiltChunk enhanced_bes$addPostRebuildTask(ChunkBuilder.BuiltChunk chunk) {
if (WorldUtil.CHUNK_UPDATE_TASKS.size() > 0) {
var pos = ChunkSectionPos.from(chunk.getOrigin());
if (WorldUtil.CHUNK_UPDATE_TASKS.containsKey(pos)) {
var task = WorldUtil.CHUNK_UPDATE_TASKS.remove(pos);
((ChunkRebuildTaskAccess) chunk).enhanced_bes$setTaskAfterRebuild(task);
}
}
return chunk;
}
@Inject(method = "addBuiltChunk", at = @At("HEAD"))
private void enhanced_bes$runPostRebuildTask(ChunkBuilder.BuiltChunk chunk, CallbackInfo ci) {
((ChunkRebuildTaskAccess) chunk).enhanced_bes$runAfterRebuildTask();
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionManagerMixin.java
================================================
package foundationgames.enhancedblockentities.mixin.compat.sodium;
import foundationgames.enhancedblockentities.util.WorldUtil;
import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.BuilderTaskOutput;
import net.minecraft.util.math.ChunkSectionPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
/**
* <p>Adapted from {@link foundationgames.enhancedblockentities.mixin.WorldRendererMixin}</p>
*/
@Pseudo
@Mixin(value = RenderSectionManager.class, remap = false)
public class RenderSectionManagerMixin {
@ModifyVariable(method = "submitSectionTasks(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/executor/ChunkJobCollector;Lnet/caffeinemc/mods/sodium/client/render/chunk/ChunkUpdateType;Z)V",
at = @At(value = "INVOKE", shift = At.Shift.BEFORE, ordinal = 0, target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSection;isDisposed()Z"),
index = 5, require = 0
)
private RenderSection enhanced_bes$compat_sodium$cacheUpdatingChunk(RenderSection section) {
if (WorldUtil.CHUNK_UPDATE_TASKS.size() > 0) {
var pos = ChunkSectionPos.from(section.getChunkX(), section.getChunkY(), section.getChunkZ());
if (WorldUtil.CHUNK_UPDATE_TASKS.containsKey(pos)) {
var task = WorldUtil.CHUNK_UPDATE_TASKS.remove(pos);
((ChunkRebuildTaskAccess) section).enhanced_bes$setTaskAfterRebuild(task);
}
}
return section;
}
@ModifyVariable(method = "processChunkBuildResults",
at = @At(value = "INVOKE_ASSIGN", shift = At.Shift.BEFORE, ordinal = 0, target = "Lnet/caffeinemc/mods/sodium/client/render/chunk/RenderSection;getTaskCancellationToken()Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;"),
index = 5, require = 0
)
private BuilderTaskOutput enhanced_bes$runPostRebuildTask(BuilderTaskOutput output) {
((ChunkRebuildTaskAccess) output.render).enhanced_bes$runAfterRebuildTask();
return output;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionMixin.java
================================================
package foundationgames.enhancedblockentities.mixin.compat.sodium;
import foundationgames.enhancedblockentities.util.duck.ChunkRebuildTaskAccess;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSection;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Unique;
/**
* <p>Adapted from {@link foundationgames.enhancedblockentities.mixin.BuiltChunkMixin}</p>
*/
@Pseudo
@Mixin(value = RenderSection.class, remap = false)
public class RenderSectionMixin implements ChunkRebuildTaskAccess {
private @Unique @Nullable Runnable enhanced_bes$taskAfterRebuild = null;
@Override
public Runnable enhanced_bes$getTaskAfterRebuild() {
return enhanced_bes$taskAfterRebuild;
}
@Override
public void enhanced_bes$setTaskAfterRebuild(Runnable task) {
enhanced_bes$taskAfterRebuild = task;
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java
================================================
package foundationgames.enhancedblockentities.util;
public enum ConvUtil {;
public static boolean bool(String bool) {
return bool != null && bool.equalsIgnoreCase("true");
}
public static boolean defaultedBool(String bool, boolean defaultVal) {
return bool == null ? defaultVal : bool(bool);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java
================================================
package foundationgames.enhancedblockentities.util;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import net.minecraft.client.render.block.entity.ChestBlockEntityRenderer;
public enum DateUtil {;
public static boolean isChristmas() {
String config = EnhancedBlockEntities.CONFIG.christmasChests;
if (config.equals("disabled")) return false;
if (config.equals("forced")) return true;
return ChestBlockEntityRenderer.isAroundChristmas();
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java
================================================
package foundationgames.enhancedblockentities.util;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import net.fabricmc.fabric.api.renderer.v1.model.ModelHelper;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.resource.DefaultResourcePack;
import net.minecraft.resource.ResourcePack;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.random.Random;
import java.io.IOException;
import java.nio.file.Files;
public enum EBEUtil {;
private static final Random dummy = Random.create();
// Contains all dye colors, and null
public static final DyeColor[] DEFAULTED_DYE_COLORS;
// All directions except up and down
public static final Direction[] HORIZONTAL_DIRECTIONS;
static {
var dColors = DyeColor.values();
DEFAULTED_DYE_COLORS = new DyeColor[dColors.length + 1];
System.arraycopy(dColors, 0, DEFAULTED_DYE_COLORS, 0, dColors.length);
HORIZONTAL_DIRECTIONS = new Direction[] {Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST};
}
public static int angle(Direction dir) {
int h = dir.getHorizontalQuarterTurns();
return h >= 0 ? h * 90 : 0;
}
public static void renderBakedModel(VertexConsumerProvider vertexConsumers, BlockState state, MatrixStack matrices, BakedModel model, int light, int overlay) {
VertexConsumer vertices = vertexConsumers.getBuffer(RenderLayers.getEntityBlockLayer(state));
for (int i = 0; i <= 6; i++) {
for (BakedQuad q : model.getQuads(null, ModelHelper.faceFromIndex(i), dummy)) {
vertices.quad(matrices.peek(), q, 1, 1, 1, 1, light, overlay);
}
}
}
public static boolean isVanillaResourcePack(ResourcePack pack) {
return (pack instanceof DefaultResourcePack) ||
// Terrible quilt compat hack
("org.quiltmc.qsl.resource.loader.api.GroupResourcePack$Wrapped".equals(pack.getClass().getName()));
}
public static Identifier id(String path) {
return Identifier.of(EnhancedBlockEntities.NAMESPACE, path);
}
public static final String DUMP_FOLDER_NAME = "enhanced_bes_dump";
public static void dumpResources() throws IOException {
var path = FabricLoader.getInstance().getGameDir().resolve(DUMP_FOLDER_NAME);
if (!Files.exists(path)) {
Files.createDirectory(path);
}
ResourceUtil.dumpAllPacks(path);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/util/ExecutableRunnableHashSet.java
================================================
package foundationgames.enhancedblockentities.util;
import java.util.HashSet;
public class ExecutableRunnableHashSet extends HashSet<Runnable> implements Runnable {
@Override
public void run() {
this.forEach(Runnable::run);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/util/GuiUtil.java
================================================
package foundationgames.enhancedblockentities.util;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
public enum GuiUtil {;
public static Text shorten(String text, final int maxLength, Formatting ... formats) {
String[] words = text.split(" ");
StringBuilder line = new StringBuilder();
StringBuilder result = new StringBuilder();
for (int i = 0; i < words.length; i++) {
var word = words[i];
line.append(word).append(" ");
if (line.length() > maxLength) {
if (i < words.length - 1) {
line.append("\n");
}
result.append(line);
line = new StringBuilder();
}
}
if (line.length() > 0) result.append(line);
return Text.literal(result.toString()).formatted(formats);
}
}
================================================
FILE: src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java
================================================
package foundationgames.enhancedblockentities.util;
import foundationgames.enhancedblockentities.EnhancedBlockEntities;
import foundationgames.enhancedblockentities.client.resource.EBEPack;
import foundationgames.enhancedblockentities.client.resource.template.TemplateProvider;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.minecraft.block.DecoratedPotPattern;
import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.registry.RegistryKey;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum ResourceUtil {;
private static EBEPack BASE_PACK;
private static EBEPack TOP_LEVEL_PACK;
public static void addChestItemDefinition(String chestName, String centerChest, boolean hasChristmas, EBEPack pack) {
pack.addTemplateResource(Identifier.of("items/"+chestName+".json"),
t -> t.load(hasChristmas ? "item/chest_item.json" : "item/chest_item_no_christmas.json",
d -> d.def("chest", centerChest)));
}
public static void addBedItemDefinition(String bedColor, EBEPack pack) {
pack.addTemplateResource(Identifier.of("items/"+bedColor+"_bed.json"),
t -> t.load("item/bed.json",
d -> d.def("head", bedColor + "_bed_head").def("foot", bedColor + "_bed_foot")));
pack.addTemplateResource(Identifier.of("models/item/"+bedColor+"_bed_head.json"),
t -> t.load("model/bed_head_item.json", d -> d.def("bed", bedColor)));
pack.addTemplateResource(Identifier.of("models/item/"+bedColor+"_bed_foot.json"),
t -> t.load("model/bed_foot_item.json", d -> d.def("bed", bedColor)));
}
private static String list(String ... els) {
return String.join(",", els);
}
private static String kv(String k, String v) {
return String.format("\""+k+"\":\""+v+"\"");
}
private static String kv(String k, int v) {
return String.format("\""+k+"\":"+v+"");
}
private static String variant(TemplateProvider t, String state, String model) throws IOException {
return t.load("blockstate/var.json", d -> d
.def("state", state)
.def("model", model)
.def("extra", ""));
}
private static String variantY(TemplateProvider t, String state, String model, int y) throws IOException {
return t.load("blockstate/var.json", d -> d
.def("state", state)
.def("model", model)
.def("extra", kv("y", y) + ","));
}
private static String variantXY(TemplateProvider t, String state, String model, int x, int y) throws IOException {
return t.load("blockstate/var.json", d -> d
.def("state", state)
.def("model", model)
.def("extra", list(
kv("x", x),
kv("y", y)
) + ","));
}
private static String variantRotation16(TemplateProvider t, String keyPrefix, String modelPrefix) throws IOException {
return list(
variantY(t, keyPrefix+"0", modelPrefix+"_0", 180),
variantY(t, keyPrefix+"1", modelPrefix+"_67_5", 270),
variantY(t, keyPrefix+"2", modelPrefix+"_45", 270),
variantY(t, keyPrefix+"3", modelPrefix+"_22_5", 270),
variantY(t, keyPrefix+"4", modelPrefix+"_0", 270),
variant(t, keyPrefix+"5", modelPrefix+"_67_5"),
variant(t, keyPrefix+"6", modelPrefix+"_45"),
variant(t, keyPrefix+"7", modelPrefix+"_22_5"),
variant(t, keyPrefix+"8", modelPrefix+"_0"),
variantY(t, keyPrefix+"9", modelPrefix+"_67_5", 90),
variantY(t, keyPrefix+"10", modelPrefix+"_45", 90),
variantY(t, keyPrefix+"11", modelPrefix+"_22_5", 90),
variantY(t, keyPrefix+"12", modelPrefix+"_0", 90),
variantY(t, keyPrefix+"13", modelPrefix+"_67_5", 180),
variantY(t, keyPrefix+"14", modelPrefix+"_45", 180),
variantY(t, keyPrefix+"15", modelPrefix+"_22_5", 180)
);
}
private static String variantHFacing(TemplateProvider t, String keyPrefix, String model) throws IOException {
return list(
variant(t, keyPrefix+"north", model),
variantY(t, keyPrefix+"west", model, 270),
variantY(t, keyPrefix+"south", model, 180),
variantY(t, keyPrefix+"east", model, 90)
);
}
private static void addChestLikeModel(String parent, String chestTex, String chestName, Identifier id, EBEPack pack) {
pack.addTemplateResource(Identifier.of(id.getNamespace(), "models/" + id.getPath() + ".json"),
t -> t.load("model/chest_like.json", d -> d
.def("parent", parent)
.def("chest_tex", chestTex)
.def("particle", chestParticle(chestName))
)
);
}
public static void addSingleChestModels(String chestTex, String chestName, EBEPack pack) {
addChestLikeModel("template_chest_center", chestTex, chestName, Identifier.of("block/" + chestName + "_center"), pack);
addChestLikeModel("template_chest_center_lid", chestTex, chestName, Identifier.of("block/" + chestName + "_center_lid"), pack);
addChestLikeModel("template_chest_center_trunk", chestTex, chestName, Identifier.of("block/" + chestName + "_center_trunk"), pack);
}
public static void addDoubleChestModels(String leftTex, String rightTex, String chestName, EBEPack pack) {
addChestLikeModel("template_chest_left", leftTex, chestName, Identifier.of("block/" + chestName + "_left"), pack);
addChestLikeModel("template_chest_left_lid", leftTex, chestName, Identifier.of("block/" + chestName + "_left_lid"), pack);
addChestLikeModel("template_chest_left_trunk", leftTex, chestName, Identifier.of("block/" + chestName + "_left_trunk"), pack);
addChestLikeModel("template_chest_right", rightTex, chestName, Identifier.of("block/" + chestName + "_right"), pack);
addChestLikeModel("template_chest_right_lid", rightTex, chestName, Identifier.of("block/" + chestName + "_right_lid"), pack);
addChestLikeModel("template_chest_right_trunk", rightTex, chestName, Identifier.of("block/" + chestName + "_right_trunk"), pack);
}
private static String chestParticle(String chestName) {
if (EnhancedBlockEntities.CONFIG.experimentalChests) return kv("particle", "block/"+chestName+"_particle") + ",";
return "";
}
private static String bedParticle(String bedColor) {
if (EnhancedBlockEntities.CONFIG.experimentalBeds) return kv("particle", "block/"+bedColor+"_bed_particle") + ",";
return "";
}
private static String signParticle(String signName) {
if (EnhancedBlockEntities.CONFIG.experimentalSigns) return kv("particle", "block/"+signName+"_particle") + ",";
return "";
}
private static void addBlockState(Identifier id, TemplateProvider.TemplateApplyingFunction vars, EBEPack pack) {
pack.addTemplateResource(Identifier.of(id.getNamespace(), "blockstates/" + id.getPath() + ".json"),
t -> t.load("blockstate/base.json", d -> d.def("vars", vars)));
}
public static void addChestBlockStates(String chestName, EBEPack pack) {
addBlockState(Identifier.of(chestName),
t0 -> list(
variantHFacing(t0, "type=single,facing=", "builtin:"+chestName+"_center"),
variantHFacing(t0, "type=left,facing=", "builtin:"+chestName+"_left"),
variantHFacing(t0, "type=right,facing=", "builtin:"+chestName+"_right")
), pack);
}
public static void addSingleChestOnlyBlockStates(String chestName, EBEPack pack) {
addBlockState(Identifier.of(chestName),
t0 -> list(
variantHFacing(t0, "facing=", "builtin:"+chestName+"_center")
), pack);
}
public static void addParentModel(String parent, Identifier id, EBEPack pack) {
pack.addTemplateResource(Identifier.of(id.getNamespace(), "models/" + id.getPath() + ".json"), t ->
"{" + kv("parent", parent) + "}");
}
public static void addParentTexModel(String parent, String textures, Identifier id, EBEPack pack) {
pack.addTemplateResource(Identifier.of(id.getNamespace(), "models/" + id.getPath() + ".json"), t ->
t.load("model/parent_and_tex.json", d -> d.def("parent", parent).def("textures", textures)));
}
public static void addSignTypeModels(String signType, EBEPack pack) {
var signName = signType+"_sign";
var signTex = "entity/signs/"+signType;
addRotation16Models(
signParticle(signName) + kv("sign", signTex),
"block/template_sign", "block/"+signName, ResourceUtil::signAOSuffix, pack);
var hangingTexDef = list(
kv("sign", "entity/signs/hanging/"+signT
gitextract_2wd5jt0b/
├── .github/
│ └── workflows/
│ └── build.yml
├── .gitignore
├── LICENSE.txt
├── README.md
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src/
└── main/
├── java/
│ └── foundationgames/
│ └── enhancedblockentities/
│ ├── EBESetup.java
│ ├── EnhancedBlockEntities.java
│ ├── EnhancedBlockEntityRegistry.java
│ ├── ReloadType.java
│ ├── client/
│ │ ├── model/
│ │ │ ├── DynamicBakedModel.java
│ │ │ ├── DynamicModelEffects.java
│ │ │ ├── DynamicModelProvidingPlugin.java
│ │ │ ├── DynamicUnbakedModel.java
│ │ │ ├── ModelIdentifiers.java
│ │ │ ├── ModelSelector.java
│ │ │ ├── item/
│ │ │ │ └── EBEIsChristmasProperty.java
│ │ │ └── misc/
│ │ │ └── DecoratedPotModelSelector.java
│ │ ├── render/
│ │ │ ├── BlockEntityRenderCondition.java
│ │ │ ├── BlockEntityRendererOverride.java
│ │ │ ├── SignRenderManager.java
│ │ │ └── entity/
│ │ │ ├── BellBlockEntityRendererOverride.java
│ │ │ ├── ChestBlockEntityRendererOverride.java
│ │ │ ├── DecoratedPotBlockEntityRendererOverride.java
│ │ │ ├── ShulkerBoxBlockEntityRendererOverride.java
│ │ │ └── SignBlockEntityRendererOverride.java
│ │ └── resource/
│ │ ├── AtlasResourceBuilder.java
│ │ ├── EBEPack.java
│ │ └── template/
│ │ ├── TemplateDefinitions.java
│ │ ├── TemplateLoader.java
│ │ └── TemplateProvider.java
│ ├── config/
│ │ ├── EBEConfig.java
│ │ └── gui/
│ │ ├── EBEModMenuPlugin.java
│ │ ├── option/
│ │ │ ├── ConfigButtonOption.java
│ │ │ ├── EBEOption.java
│ │ │ └── TextPalette.java
│ │ ├── screen/
│ │ │ └── EBEConfigScreen.java
│ │ └── widget/
│ │ ├── SectionTextWidget.java
│ │ └── WidgetRowListWidget.java
│ ├── event/
│ │ └── EBEEvents.java
│ ├── mixin/
│ │ ├── AbstractBlockStateMixin.java
│ │ ├── AbstractSignBlockEntityRenderAccessor.java
│ │ ├── BellBlockEntityMixin.java
│ │ ├── BlockEntityRenderDispatcherMixin.java
│ │ ├── BuiltChunkMixin.java
│ │ ├── ChestBlockEntityMixin.java
│ │ ├── DecoratedPotBlockEntityMixin.java
│ │ ├── EnderChestBlockEntityMixin.java
│ │ ├── LifecycledResourceManagerImplMixin.java
│ │ ├── MinecraftClientMixin.java
│ │ ├── ShulkerBoxBlockEntityMixin.java
│ │ ├── SignEditScreenMixin.java
│ │ ├── VideoOptionsScreenMixin.java
│ │ ├── WorldRendererMixin.java
│ │ └── compat/
│ │ └── sodium/
│ │ ├── RenderSectionManagerMixin.java
│ │ └── RenderSectionMixin.java
│ └── util/
│ ├── ConvUtil.java
│ ├── DateUtil.java
│ ├── EBEUtil.java
│ ├── ExecutableRunnableHashSet.java
│ ├── GuiUtil.java
│ ├── ResourceUtil.java
│ ├── WorldUtil.java
│ ├── duck/
│ │ ├── AppearanceStateHolder.java
│ │ └── ChunkRebuildTaskAccess.java
│ └── hacks/
│ ├── ExperimentalSetup.java
│ ├── ResourceHacks.java
│ └── TextureHacks.java
└── resources/
├── assets/
│ ├── enhancedblockentities/
│ │ └── lang/
│ │ ├── en_us.json
│ │ ├── ru_ru.json
│ │ └── zh_cn.json
│ └── minecraft/
│ └── models/
│ ├── block/
│ │ ├── bell_between_walls_with_bell.json
│ │ ├── bell_body.json
│ │ ├── bell_ceiling_with_bell.json
│ │ ├── bell_floor_with_bell.json
│ │ ├── bell_wall_with_bell.json
│ │ ├── decorated_pot_base.json
│ │ ├── decorated_pot_shaking.json
│ │ ├── template_bed_foot.json
│ │ ├── template_bed_foot_ao.json
│ │ ├── template_bed_foot_offset.json
│ │ ├── template_bed_head.json
│ │ ├── template_bed_head_ao.json
│ │ ├── template_chest_center.json
│ │ ├── template_chest_center_lid.json
│ │ ├── template_chest_center_trunk.json
│ │ ├── template_chest_left.json
│ │ ├── template_chest_left_lid.json
│ │ ├── template_chest_left_trunk.json
│ │ ├── template_chest_right.json
│ │ ├── template_chest_right_lid.json
│ │ ├── template_chest_right_trunk.json
│ │ ├── template_hanging_sign_0.json
│ │ ├── template_hanging_sign_0_ao.json
│ │ ├── template_hanging_sign_22_5.json
│ │ ├── template_hanging_sign_22_5_ao.json
│ │ ├── template_hanging_sign_45.json
│ │ ├── template_hanging_sign_45_ao.json
│ │ ├── template_hanging_sign_67_5.json
│ │ ├── template_hanging_sign_67_5_ao.json
│ │ ├── template_hanging_sign_attached_0.json
│ │ ├── template_hanging_sign_attached_0_ao.json
│ │ ├── template_hanging_sign_attached_22_5.json
│ │ ├── template_hanging_sign_attached_22_5_ao.json
│ │ ├── template_hanging_sign_attached_45.json
│ │ ├── template_hanging_sign_attached_45_ao.json
│ │ ├── template_hanging_sign_attached_67_5.json
│ │ ├── template_hanging_sign_attached_67_5_ao.json
│ │ ├── template_pottery_pattern_east.json
│ │ ├── template_pottery_pattern_north.json
│ │ ├── template_pottery_pattern_south.json
│ │ ├── template_pottery_pattern_west.json
│ │ ├── template_shulker_box.json
│ │ ├── template_shulker_box_bottom.json
│ │ ├── template_shulker_box_lid.json
│ │ ├── template_sign_0.json
│ │ ├── template_sign_0_ao.json
│ │ ├── template_sign_22_5.json
│ │ ├── template_sign_22_5_ao.json
│ │ ├── template_sign_45.json
│ │ ├── template_sign_45_ao.json
│ │ ├── template_sign_67_5.json
│ │ ├── template_sign_67_5_ao.json
│ │ ├── template_wall_hanging_sign.json
│ │ ├── template_wall_hanging_sign_ao.json
│ │ ├── template_wall_sign.json
│ │ └── template_wall_sign_ao.json
│ └── item/
│ └── christmas_chest.json
├── enhancedblockentities.accesswidener
├── enhancedblockentities.mixins.json
├── fabric.mod.json
└── templates/
├── blockstate/
│ ├── base.json
│ └── var.json
├── item/
│ ├── bed.json
│ ├── chest_item.json
│ └── chest_item_no_christmas.json
└── model/
├── bed_foot_item.json
├── bed_head_item.json
├── chest_like.json
└── parent_and_tex.json
SYMBOL INDEX (358 symbols across 62 files)
FILE: src/main/java/foundationgames/enhancedblockentities/EBESetup.java
type EBESetup (line 39) | public enum EBESetup {;
method setupRRPChests (line 40) | public static void setupRRPChests() {
method setupRRPSigns (line 65) | public static void setupRRPSigns() {
method setupRRPBells (line 114) | public static void setupRRPBells() {
method setupRRPBeds (line 120) | public static void setupRRPBeds() {
method setupRRPShulkerBoxes (line 132) | public static void setupRRPShulkerBoxes() {
method setupRRPDecoratedPots (line 146) | public static void setupRRPDecoratedPots() {
method setupResourceProviders (line 158) | public static void setupResourceProviders() {
method setupChests (line 319) | public static void setupChests() {
method setupSigns (line 363) | public static void setupSigns() {
method setupBells (line 404) | public static void setupBells() {
method setupBeds (line 410) | public static void setupBeds() {
method setupShulkerBoxes (line 429) | public static void setupShulkerBoxes() {
method setupDecoratedPots (line 444) | public static void setupDecoratedPots() {
FILE: src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java
class EnhancedBlockEntities (line 22) | public final class EnhancedBlockEntities implements ClientModInitializer {
method onInitializeClient (line 32) | @Override
method reload (line 59) | public static void reload(ReloadType type) {
method load (line 68) | public static void load() {
FILE: src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntityRegistry.java
class EnhancedBlockEntityRegistry (line 14) | public final class EnhancedBlockEntityRegistry {
method EnhancedBlockEntityRegistry (line 18) | private EnhancedBlockEntityRegistry() {}
method register (line 20) | public static void register(Block block, BlockEntityType<?> type, Bloc...
method clear (line 25) | public static void clear() {
FILE: src/main/java/foundationgames/enhancedblockentities/ReloadType.java
type ReloadType (line 3) | public enum ReloadType {
method ReloadType (line 10) | ReloadType(int pertinence) {
method or (line 14) | public ReloadType or(ReloadType type) {
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicBakedModel.java
class DynamicBakedModel (line 23) | public class DynamicBakedModel implements BakedModel, FabricBakedModel {
method DynamicBakedModel (line 31) | public DynamicBakedModel(BakedModel[] models, ModelSelector selector, ...
method isVanillaAdapter (line 40) | @Override
method emitBlockQuads (line 45) | @Override
method getQuads (line 79) | @Override
method useAmbientOcclusion (line 84) | @Override
method hasDepth (line 89) | @Override
method isSideLit (line 94) | @Override
method getParticleSprite (line 99) | @Override
method getTransformation (line 104) | @Override
method getModels (line 109) | public BakedModel[] getModels() {
method getSelector (line 113) | public ModelSelector getSelector() {
method getEffects (line 117) | public DynamicModelEffects getEffects() {
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelEffects.java
class DynamicModelEffects (line 8) | public abstract class DynamicModelEffects {
method ambientOcclusion (line 14) | @Override
method ambientOcclusion (line 21) | @Override
method ambientOcclusion (line 28) | @Override
method ambientOcclusion (line 35) | @Override
method DynamicModelEffects (line 43) | public DynamicModelEffects() {
method ambientOcclusion (line 48) | public boolean ambientOcclusion() {
method fromId (line 52) | public static DynamicModelEffects fromId(int id) {
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvidingPlugin.java
class DynamicModelProvidingPlugin (line 11) | public class DynamicModelProvidingPlugin implements ModelLoadingPlugin, ...
method DynamicModelProvidingPlugin (line 15) | public DynamicModelProvidingPlugin(Identifier id, Supplier<DynamicUnba...
method initialize (line 20) | @Override
method modifyModelOnLoad (line 25) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/DynamicUnbakedModel.java
class DynamicUnbakedModel (line 12) | public class DynamicUnbakedModel implements UnbakedModel {
method DynamicUnbakedModel (line 17) | public DynamicUnbakedModel(Identifier[] models, ModelSelector selector...
method resolve (line 23) | @Override
method bake (line 31) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java
class ModelIdentifiers (line 20) | public final class ModelIdentifiers implements ModelLoadingPlugin {
method init (line 92) | public static void init() {
method refreshPotteryPatterns (line 96) | public static void refreshPotteryPatterns() {
method of (line 115) | private static Identifier of(String id, Predicate<EBEConfig> condition) {
method initialize (line 121) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java
class ModelSelector (line 14) | public abstract class ModelSelector {
method writeModelIndices (line 18) | @Override
method getParticleModelIndex (line 31) | @Override
method writeModelIndices (line 36) | @Override
method getParticleModelIndex (line 50) | public int getParticleModelIndex() {
method writeModelIndices (line 54) | public abstract void writeModelIndices(BlockRenderView view, BlockStat...
method ModelSelector (line 59) | public ModelSelector(int displayedModelCount) {
method ModelSelector (line 65) | public ModelSelector() {
method fromId (line 69) | public static ModelSelector fromId(int id) {
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/item/EBEIsChristmasProperty.java
method getValue (line 15) | @Override
method getCodec (line 20) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java
class DecoratedPotModelSelector (line 25) | public class DecoratedPotModelSelector extends ModelSelector {
method DecoratedPotModelSelector (line 33) | public DecoratedPotModelSelector() {
method createModelIDs (line 39) | public Identifier[] createModelIDs() {
method writeModelIndices (line 58) | @Override
method getPatternIndex (line 84) | private int getPatternIndex(Optional<Item> sherd, int max) {
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java
type BlockEntityRenderCondition (line 11) | @FunctionalInterface
method shouldRender (line 57) | boolean shouldRender(BlockEntity entity);
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java
class BlockEntityRendererOverride (line 9) | public abstract class BlockEntityRendererOverride {
method render (line 11) | @Override
method BlockEntityRendererOverride (line 15) | public BlockEntityRendererOverride() {
method render (line 19) | public abstract void render(BlockEntityRenderer<BlockEntity> renderer,...
method onModelsReload (line 21) | public void onModelsReload() {}
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/SignRenderManager.java
class SignRenderManager (line 5) | public class SignRenderManager {
method getRenderedSignAmount (line 9) | public static int getRenderedSignAmount() {
method endFrame (line 13) | public static void endFrame(WorldRenderContext ctx) {
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java
class BellBlockEntityRendererOverride (line 17) | public class BellBlockEntityRendererOverride extends BlockEntityRenderer...
method render (line 20) | @Override
method getBellModel (line 50) | private BakedModel getBellModel() {
method onModelsReload (line 54) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java
class ChestBlockEntityRendererOverride (line 21) | public class ChestBlockEntityRendererOverride extends BlockEntityRendere...
method ChestBlockEntityRendererOverride (line 26) | public ChestBlockEntityRendererOverride(Supplier<BakedModel[]> modelGe...
method render (line 31) | @Override
method getLidAnimationHolder (line 56) | public static LidOpenable getLidAnimationHolder(BlockEntity blockEntit...
method onModelsReload (line 79) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/DecoratedPotBlockEntityRendererOverride.java
class DecoratedPotBlockEntityRendererOverride (line 23) | public class DecoratedPotBlockEntityRendererOverride extends BlockEntity...
method tryGetModels (line 29) | private void tryGetModels() {
method render (line 54) | @Override
method onModelsReload (line 110) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/ShulkerBoxBlockEntityRendererOverride.java
class ShulkerBoxBlockEntityRendererOverride (line 21) | public class ShulkerBoxBlockEntityRendererOverride extends BlockEntityRe...
method ShulkerBoxBlockEntityRendererOverride (line 25) | public ShulkerBoxBlockEntityRendererOverride(Consumer<Map<DyeColor, Ba...
method render (line 29) | @Override
method onModelsReload (line 58) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/render/entity/SignBlockEntityRendererOverride.java
class SignBlockEntityRendererOverride (line 12) | public class SignBlockEntityRendererOverride extends BlockEntityRenderer...
method SignBlockEntityRendererOverride (line 13) | public SignBlockEntityRendererOverride() {}
method render (line 15) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/AtlasResourceBuilder.java
class AtlasResourceBuilder (line 13) | public class AtlasResourceBuilder {
method put (line 17) | public void put(AtlasSource source) {
method toBytes (line 21) | public byte[] toBytes() {
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java
class EBEPack (line 34) | public class EBEPack implements ResourcePack {
method EBEPack (line 46) | public EBEPack(Identifier id, TemplateLoader templates) {
method addAtlasSprite (line 57) | public void addAtlasSprite(Identifier atlas, AtlasSource source) {
method addSingleBlockSprite (line 64) | public void addSingleBlockSprite(Identifier path) {
method addDirBlockSprites (line 68) | public void addDirBlockSprites(String dir, String prefix) {
method addResource (line 72) | public void addResource(Identifier id, InputSupplier<byte[]> resource) {
method addResource (line 77) | public void addResource(Identifier id, byte[] resource) {
method addPlainTextResource (line 82) | public void addPlainTextResource(Identifier id, String plainText) {
method addTemplateResource (line 86) | public void addTemplateResource(Identifier id, TemplateProvider.Templa...
method addTemplateResource (line 90) | public void addTemplateResource(Identifier id, String templatePath) {
method openRoot (line 94) | @Nullable
method open (line 100) | @Nullable
method findResources (line 108) | @Override
method getNamespaces (line 121) | @Override
method parseMetadata (line 128) | @Nullable
method getInfo (line 134) | @Override
method close (line 139) | @Override
method dump (line 143) | public void dump(Path dir) throws IOException {
class PropertyBuilder (line 163) | public static class PropertyBuilder {
method PropertyBuilder (line 166) | private PropertyBuilder() {}
method def (line 168) | public PropertyBuilder def(String k, String v) {
method build (line 176) | private Properties build() {
class LazyBufferedResource (line 184) | public static class LazyBufferedResource implements InputSupplier<Inpu...
method LazyBufferedResource (line 188) | public LazyBufferedResource(InputSupplier<byte[]> backing) {
method get (line 192) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateDefinitions.java
type TemplateDefinitions (line 11) | public interface TemplateDefinitions {
method def (line 12) | default TemplateDefinitions def(String k, Object v) {
method def (line 16) | TemplateDefinitions def(String k, TemplateProvider.TemplateApplyingFun...
class Impl (line 18) | class Impl implements TemplateDefinitions, Iterable<Map.Entry<String, ...
method push (line 21) | public void push() {
method pop (line 25) | public void pop() {
method def (line 29) | public TemplateDefinitions def(String k, String v) {
method def (line 33) | public TemplateDefinitions def(String k, TemplateProvider.TemplateAp...
method iterator (line 39) | @NotNull
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateLoader.java
class TemplateLoader (line 10) | public class TemplateLoader {
method TemplateLoader (line 15) | public TemplateLoader() {
method setRoot (line 18) | public void setRoot(Path path) {
method getOrLoadRaw (line 22) | public String getOrLoadRaw(String path) throws IOException {
FILE: src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateProvider.java
class TemplateProvider (line 8) | public class TemplateProvider {
method TemplateProvider (line 12) | public TemplateProvider(TemplateLoader loader) {
method load (line 16) | public String load(String templatePath, Consumer<TemplateDefinitions> ...
type TemplateApplyingFunction (line 44) | @FunctionalInterface
method getAndApplyTemplate (line 46) | String getAndApplyTemplate(TemplateProvider templates) throws IOExce...
FILE: src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java
class EBEConfig (line 18) | public class EBEConfig {
method writeTo (line 59) | public void writeTo(Properties properties) {
method readFrom (line 80) | public void readFrom(Properties properties) {
method save (line 113) | public void save() {
method load (line 132) | public void load() {
method applyCompatConfigModifiers (line 156) | @SuppressWarnings("unchecked")
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/EBEModMenuPlugin.java
class EBEModMenuPlugin (line 7) | public class EBEModMenuPlugin implements ModMenuApi {
method getModConfigScreenFactory (line 8) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/option/ConfigButtonOption.java
class ConfigButtonOption (line 17) | public class ConfigButtonOption {
method getOption (line 18) | public static SimpleOption<?> getOption(Screen parent) {
method getWidgetCreator (line 31) | @Override
method validate (line 38) | @Override
method codec (line 43) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java
class EBEOption (line 17) | public final class EBEOption {
method EBEOption (line 37) | public EBEOption(String key, List<String> values, ConfigView config, b...
method getValue (line 51) | public String getValue() {
method getOptionKey (line 55) | public String getOptionKey() {
method getValueKey (line 59) | public String getValueKey() {
method getText (line 63) | public Text getText() {
method getTooltip (line 71) | public Tooltip getTooltip() {
method next (line 88) | public void next() {
method isDefault (line 95) | public boolean isDefault() {
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/option/TextPalette.java
type TextPalette (line 3) | public interface TextPalette {
method getColor (line 12) | int getColor(float cycle);
method rainbow (line 14) | static TextPalette rainbow(float start) {
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java
class EBEConfigScreen (line 29) | public class EBEConfigScreen extends Screen {
method EBEConfigScreen (line 51) | public EBEConfigScreen(Screen screen) {
method init (line 56) | @Override
method renderDarkening (line 90) | @Override
method render (line 96) | @Override
method close (line 104) | @Override
method applyChanges (line 109) | public void applyChanges() {
method addOptions (line 124) | public void addOptions() {
method option (line 204) | private ButtonWidget option(EBEOption option) {
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/widget/SectionTextWidget.java
class SectionTextWidget (line 8) | public class SectionTextWidget extends AbstractTextWidget {
method SectionTextWidget (line 9) | public SectionTextWidget(Text message, TextRenderer textRenderer) {
method SectionTextWidget (line 13) | public SectionTextWidget(int x, int y, int width, int height, Text mes...
method renderWidget (line 18) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/config/gui/widget/WidgetRowListWidget.java
class WidgetRowListWidget (line 14) | public class WidgetRowListWidget extends ElementListWidget<WidgetRowList...
method WidgetRowListWidget (line 20) | public WidgetRowListWidget(MinecraftClient mc, int w, int h, int y, in...
method add (line 26) | public void add(ClickableWidget ... widgets) {
method getRowWidth (line 45) | @Override
method getScrollbarX (line 50) | @Override
method drawMenuListBackground (line 55) | @Override
class Entry (line 59) | public static class Entry extends ElementListWidget.Entry<Entry> {
method Entry (line 63) | public Entry(GridWidget widget) {
method children (line 68) | @Override
method selectableChildren (line 73) | @Override
method render (line 78) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java
type EBEEvents (line 6) | public enum EBEEvents {;
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java
class AbstractBlockStateMixin (line 13) | @Mixin(AbstractBlock.AbstractBlockState.class)
method getBlock (line 15) | @Shadow public abstract Block getBlock();
method enhanced_bes$overrideRenderType (line 17) | @Inject(method = "getRenderType", at = @At("HEAD"), cancellable = true)
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/AbstractSignBlockEntityRenderAccessor.java
type AbstractSignBlockEntityRenderAccessor (line 13) | @Mixin(AbstractSignBlockEntityRenderer.class)
method enhanced_bes$applyTransforms (line 15) | @Invoker("applyTransforms")
method enhanced_bes$renderText (line 18) | @Invoker("renderText")
method enhanced_bes$getRenderDistance (line 21) | @Accessor("MAX_COLORED_TEXT_OUTLINE_RENDER_DISTANCE")
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java
class BellBlockEntityMixin (line 16) | @Mixin(BellBlockEntity.class)
method BellBlockEntityMixin (line 21) | public BellBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, Blo...
method enhanced_bes$listenForStopRinging (line 27) | @ModifyVariable(method = "tick", at = @At(
method getModelState (line 38) | @Override
method setModelState (line 43) | @Override
method getRenderState (line 48) | @Override
method setRenderState (line 53) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java
class BlockEntityRenderDispatcherMixin (line 19) | @Mixin(BlockEntityRenderDispatcher.class)
method enhanced_bes$renderOverrides (line 21) | @Inject(
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/BuiltChunkMixin.java
class BuiltChunkMixin (line 9) | @Mixin(ChunkBuilder.BuiltChunk.class)
method enhanced_bes$getTaskAfterRebuild (line 14) | @Override
method enhanced_bes$setTaskAfterRebuild (line 19) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java
class ChestBlockEntityMixin (line 18) | @Mixin(ChestBlockEntity.class)
method ChestBlockEntityMixin (line 23) | private ChestBlockEntityMixin(BlockEntityType<?> type, BlockPos pos, B...
method enhanced_bes$listenForOpenClose (line 27) | @Inject(method = "clientTick", at = @At(value = "TAIL"))
method getModelState (line 37) | @Override
method setModelState (line 42) | @Override
method getRenderState (line 47) | @Override
method setRenderState (line 52) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java
class DecoratedPotBlockEntityMixin (line 15) | @Mixin(DecoratedPotBlockEntity.class)
method enhanced_bes$updateChunkOnPatternsLoaded (line 20) | @Inject(method = "readNbt", at = @At("TAIL"))
method enhanced_bes$updateOnWobble (line 29) | @Inject(method = "onSyncedBlockEvent", at = @At(value = "RETURN", shif...
method getModelState (line 48) | @Override
method setModelState (line 53) | @Override
method getRenderState (line 58) | @Override
method setRenderState (line 63) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java
class EnderChestBlockEntityMixin (line 18) | @Mixin(EnderChestBlockEntity.class)
method EnderChestBlockEntityMixin (line 23) | private EnderChestBlockEntityMixin(BlockEntityType<?> type, BlockPos p...
method enhanced_bes$listenForOpenClose (line 27) | @Inject(method = "clientTick", at = @At(value = "TAIL"))
method getModelState (line 37) | @Override
method setModelState (line 42) | @Override
method getRenderState (line 47) | @Override
method setRenderState (line 52) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/LifecycledResourceManagerImplMixin.java
class LifecycledResourceManagerImplMixin (line 23) | @Mixin(LifecycledResourceManagerImpl.class)
method enhanced_bes$injectBasePack (line 27) | @ModifyVariable(method = "<init>", at = @At(value = "INVOKE", target =...
method enhanced_bes$injectTopLevelPack (line 40) | @Inject(method = "<init>", at = @At(value = "TAIL"))
method addPack (line 48) | private void addPack(ResourceType type, ResourcePack pack) {
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/MinecraftClientMixin.java
class MinecraftClientMixin (line 12) | @Mixin(MinecraftClient.class)
method enhanced_bes$fireReloadEvent (line 14) | @Inject(method = "reloadResources()Ljava/util/concurrent/CompletableFu...
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java
class ShulkerBoxBlockEntityMixin (line 17) | @Mixin(ShulkerBoxBlockEntity.class)
method getAnimationProgress (line 19) | @Shadow public abstract float getAnimationProgress(float delta);
method ShulkerBoxBlockEntityMixin (line 24) | public ShulkerBoxBlockEntityMixin(BlockEntityType<?> type, BlockPos po...
method enhanced_bes$updateModelState (line 28) | @Inject(method = "updateAnimation", at = @At("TAIL"))
method getModelState (line 34) | @Override
method setModelState (line 39) | @Override
method getRenderState (line 44) | @Override
method setRenderState (line 49) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/SignEditScreenMixin.java
class SignEditScreenMixin (line 18) | @Mixin(SignEditScreen.class)
method enhanced_bes$renderBakedModelSign (line 20) | @Inject(method = "renderSignBackground", at = @At("HEAD"), cancellable...
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java
class VideoOptionsScreenMixin (line 12) | @Mixin(VideoOptionsScreen.class)
method VideoOptionsScreenMixin (line 14) | protected VideoOptionsScreenMixin(Text title) {
method enhanced_bes$addEBEOptionButton (line 18) | @ModifyArg(
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java
class WorldRendererMixin (line 14) | @Mixin(WorldRenderer.class)
method enhanced_bes$addPostRebuildTask (line 17) | @ModifyVariable(method = "updateChunks",
method enhanced_bes$runPostRebuildTask (line 33) | @Inject(method = "addBuiltChunk", at = @At("HEAD"))
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionManagerMixin.java
class RenderSectionManagerMixin (line 17) | @Pseudo
method enhanced_bes$compat_sodium$cacheUpdatingChunk (line 20) | @ModifyVariable(method = "submitSectionTasks(Lnet/caffeinemc/mods/sodi...
method enhanced_bes$runPostRebuildTask (line 37) | @ModifyVariable(method = "processChunkBuildResults",
FILE: src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionMixin.java
class RenderSectionMixin (line 14) | @Pseudo
method enhanced_bes$getTaskAfterRebuild (line 19) | @Override
method enhanced_bes$setTaskAfterRebuild (line 24) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java
type ConvUtil (line 3) | public enum ConvUtil {;
method bool (line 4) | public static boolean bool(String bool) {
method defaultedBool (line 8) | public static boolean defaultedBool(String bool, boolean defaultVal) {
FILE: src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java
type DateUtil (line 6) | public enum DateUtil {;
method isChristmas (line 7) | public static boolean isChristmas() {
FILE: src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java
type EBEUtil (line 23) | public enum EBEUtil {;
method angle (line 39) | public static int angle(Direction dir) {
method renderBakedModel (line 44) | public static void renderBakedModel(VertexConsumerProvider vertexConsu...
method isVanillaResourcePack (line 53) | public static boolean isVanillaResourcePack(ResourcePack pack) {
method id (line 59) | public static Identifier id(String path) {
method dumpResources (line 65) | public static void dumpResources() throws IOException {
FILE: src/main/java/foundationgames/enhancedblockentities/util/ExecutableRunnableHashSet.java
class ExecutableRunnableHashSet (line 5) | public class ExecutableRunnableHashSet extends HashSet<Runnable> impleme...
method run (line 6) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/util/GuiUtil.java
type GuiUtil (line 6) | public enum GuiUtil {;
method shorten (line 7) | public static Text shorten(String text, final int maxLength, Formattin...
FILE: src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java
type ResourceUtil (line 25) | public enum ResourceUtil {;
method addChestItemDefinition (line 29) | public static void addChestItemDefinition(String chestName, String cen...
method addBedItemDefinition (line 35) | public static void addBedItemDefinition(String bedColor, EBEPack pack) {
method list (line 46) | private static String list(String ... els) {
method kv (line 50) | private static String kv(String k, String v) {
method kv (line 54) | private static String kv(String k, int v) {
method variant (line 58) | private static String variant(TemplateProvider t, String state, String...
method variantY (line 65) | private static String variantY(TemplateProvider t, String state, Strin...
method variantXY (line 72) | private static String variantXY(TemplateProvider t, String state, Stri...
method variantRotation16 (line 82) | private static String variantRotation16(TemplateProvider t, String key...
method variantHFacing (line 103) | private static String variantHFacing(TemplateProvider t, String keyPre...
method addChestLikeModel (line 112) | private static void addChestLikeModel(String parent, String chestTex, ...
method addSingleChestModels (line 122) | public static void addSingleChestModels(String chestTex, String chestN...
method addDoubleChestModels (line 128) | public static void addDoubleChestModels(String leftTex, String rightTe...
method chestParticle (line 137) | private static String chestParticle(String chestName) {
method bedParticle (line 142) | private static String bedParticle(String bedColor) {
method signParticle (line 147) | private static String signParticle(String signName) {
method addBlockState (line 152) | private static void addBlockState(Identifier id, TemplateProvider.Temp...
method addChestBlockStates (line 157) | public static void addChestBlockStates(String chestName, EBEPack pack) {
method addSingleChestOnlyBlockStates (line 166) | public static void addSingleChestOnlyBlockStates(String chestName, EBE...
method addParentModel (line 173) | public static void addParentModel(String parent, Identifier id, EBEPac...
method addParentTexModel (line 178) | public static void addParentTexModel(String parent, String textures, I...
method addSignTypeModels (line 183) | public static void addSignTypeModels(String signType, EBEPack pack) {
method addRotation16Models (line 205) | public static void addRotation16Models(String textures, String templat...
method signAOSuffix (line 212) | private static String signAOSuffix(String model) {
method addSignBlockStates (line 217) | public static void addSignBlockStates(String signName, String wallSign...
method addHangingSignBlockStates (line 224) | public static void addHangingSignBlockStates(String signName, String w...
method addBellBlockState (line 235) | public static void addBellBlockState(EBEPack pack) {
method addBedModels (line 251) | public static void addBedModels(DyeColor bedColor, EBEPack pack) {
method addBedBlockState (line 264) | public static void addBedBlockState(DyeColor bedColor, EBEPack pack) {
method bedAOSuffix (line 279) | private static String bedAOSuffix(String model) {
method addShulkerBoxModels (line 284) | public static void addShulkerBoxModels(@Nullable DyeColor color, EBEPa...
method addShulkerBoxBlockStates (line 299) | public static void addShulkerBoxBlockStates(@Nullable DyeColor color, ...
method addDecoratedPotBlockState (line 315) | public static void addDecoratedPotBlockState(EBEPack pack) {
method addDecoratedPotPatternModels (line 320) | public static void addDecoratedPotPatternModels(RegistryKey<DecoratedP...
method resetBasePack (line 329) | public static void resetBasePack() {
method resetTopLevelPack (line 333) | public static void resetTopLevelPack() {
method getBasePack (line 337) | public static EBEPack getBasePack() {
method getTopLevelPack (line 341) | public static EBEPack getTopLevelPack() {
method getPackForCompat (line 348) | public static EBEPack getPackForCompat() {
method dumpModAssets (line 356) | public static void dumpModAssets(Path dest) throws IOException {
method dumpAllPacks (line 374) | public static void dumpAllPacks(Path dest) throws IOException {
class DelimitedAppender (line 380) | private static class DelimitedAppender {
method DelimitedAppender (line 384) | private DelimitedAppender(CharSequence delimiter) {
method append (line 388) | public DelimitedAppender append(CharSequence seq) {
method get (line 395) | public String get() {
FILE: src/main/java/foundationgames/enhancedblockentities/util/WorldUtil.java
type WorldUtil (line 16) | public enum WorldUtil implements ClientTickEvents.EndWorldTick {
method rebuildChunk (line 22) | public static void rebuildChunk(World world, BlockPos pos) {
method rebuildChunkAndThen (line 27) | public static void rebuildChunkAndThen(World world, BlockPos pos, Runn...
method scheduleTimed (line 32) | public static void scheduleTimed(World world, long time, Runnable acti...
method onEndTick (line 36) | @Override
FILE: src/main/java/foundationgames/enhancedblockentities/util/duck/AppearanceStateHolder.java
type AppearanceStateHolder (line 7) | public interface AppearanceStateHolder {
method getModelState (line 8) | int getModelState();
method setModelState (line 10) | void setModelState(int state);
method getRenderState (line 12) | int getRenderState();
method setRenderState (line 14) | void setRenderState(int state);
method updateAppearanceState (line 16) | default void updateAppearanceState(int state, World world, BlockPos po...
FILE: src/main/java/foundationgames/enhancedblockentities/util/duck/ChunkRebuildTaskAccess.java
type ChunkRebuildTaskAccess (line 3) | public interface ChunkRebuildTaskAccess {
method enhanced_bes$getTaskAfterRebuild (line 4) | Runnable enhanced_bes$getTaskAfterRebuild();
method enhanced_bes$setTaskAfterRebuild (line 6) | void enhanced_bes$setTaskAfterRebuild(Runnable task);
method enhanced_bes$runAfterRebuildTask (line 8) | default void enhanced_bes$runAfterRebuildTask() {
FILE: src/main/java/foundationgames/enhancedblockentities/util/hacks/ExperimentalSetup.java
type ExperimentalSetup (line 12) | public enum ExperimentalSetup {;
method setup (line 15) | public static void setup() {
method setupChests (line 47) | public static void setupChests(ResourceManager manager) throws IOExcep...
method setupBeds (line 56) | public static void setupBeds(ResourceManager manager) throws IOExcepti...
method setupSigns (line 64) | public static void setupSigns(ResourceManager manager) throws IOExcept...
method cacheResources (line 80) | public static void cacheResources(ResourceManager resources) {
FILE: src/main/java/foundationgames/enhancedblockentities/util/hacks/ResourceHacks.java
type ResourceHacks (line 11) | public enum ResourceHacks {;
method cropAndPutTexture (line 12) | private static void cropAndPutTexture(Identifier source, Identifier re...
method addChestParticleTexture (line 25) | public static void addChestParticleTexture(String chestName, String ch...
method addBedParticleTexture (line 33) | public static void addBedParticleTexture(String bedColor, String bedTe...
method addSignParticleTexture (line 41) | public static void addSignParticleTexture(String signType, String sign...
FILE: src/main/java/foundationgames/enhancedblockentities/util/hacks/TextureHacks.java
type TextureHacks (line 13) | public enum TextureHacks {;
method cropImage (line 14) | public static Optional<byte[]> cropImage(@Nullable InputStream image, ...
Condensed preview — 145 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (355K chars).
[
{
"path": ".github/workflows/build.yml",
"chars": 775,
"preview": "name: build\non: [pull_request, push]\n\njobs:\n build:\n strategy:\n matrix:\n java: [21]\n runs-on: ubuntu-"
},
{
"path": ".gitignore",
"chars": 188,
"preview": "# gradle\n\n.gradle/\nbuild/\nout/\nclasses/\n\n# eclipse\n\n*.launch\n\n# idea\n\n.idea/\n*.iml\n*.ipr\n*.iws\n\n# vscode\n\n.settings/\n.vs"
},
{
"path": "LICENSE.txt",
"chars": 7691,
"preview": " GNU LESSER GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007"
},
{
"path": "README.md",
"chars": 5613,
"preview": "## Enhanced Block Entities\n\nEBE is a **100% client side** Minecraft mod for the **[Fabric](https://fabricmc.net/use/)** "
},
{
"path": "build.gradle",
"chars": 2401,
"preview": "plugins {\n\tid 'fabric-loom' version '1.8-SNAPSHOT'\n\tid 'maven-publish'\n}\n\nsourceCompatibility = JavaVersion.VERSION_21\nt"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 251,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "gradle.properties",
"chars": 298,
"preview": "org.gradle.jvmargs=-Xmx2G\n\nminecraft_version=1.21.4\nyarn_mappings=1.21.4+build.8\nloader_version=0.16.10\n\nfabric_version="
},
{
"path": "gradlew",
"chars": 8683,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "gradlew.bat",
"chars": 2918,
"preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
},
{
"path": "settings.gradle",
"chars": 177,
"preview": "pluginManagement {\n repositories {\n maven {\n name = 'Fabric'\n url = 'https://maven.fabri"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/EBESetup.java",
"chars": 25316,
"preview": "package foundationgames.enhancedblockentities;\n\nimport foundationgames.enhancedblockentities.client.model.DynamicModelEf"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntities.java",
"chars": 3805,
"preview": "package foundationgames.enhancedblockentities;\n\nimport foundationgames.enhancedblockentities.client.model.ModelIdentifie"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/EnhancedBlockEntityRegistry.java",
"chars": 1068,
"preview": "package foundationgames.enhancedblockentities;\n\nimport foundationgames.enhancedblockentities.client.render.BlockEntityRe"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/ReloadType.java",
"chars": 348,
"preview": "package foundationgames.enhancedblockentities;\n\npublic enum ReloadType {\n NONE(0),\n WORLD(1),\n RESOURCES(2);\n\n "
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/DynamicBakedModel.java",
"chars": 3862,
"preview": "package foundationgames.enhancedblockentities.client.model;\n\nimport net.fabricmc.fabric.api.renderer.v1.Renderer;\nimport"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelEffects.java",
"chars": 1580,
"preview": "package foundationgames.enhancedblockentities.client.model;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockE"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/DynamicModelProvidingPlugin.java",
"chars": 1077,
"preview": "package foundationgames.enhancedblockentities.client.model;\n\nimport net.fabricmc.fabric.api.client.model.loading.v1.Mode"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/DynamicUnbakedModel.java",
"chars": 1528,
"preview": "package foundationgames.enhancedblockentities.client.model;\n\nimport net.minecraft.client.render.model.BakedModel;\nimport"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/ModelIdentifiers.java",
"chars": 7907,
"preview": "package foundationgames.enhancedblockentities.client.model;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockE"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/ModelSelector.java",
"chars": 2491,
"preview": "package foundationgames.enhancedblockentities.client.model;\n\nimport foundationgames.enhancedblockentities.util.DateUtil;"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/item/EBEIsChristmasProperty.java",
"chars": 963,
"preview": "package foundationgames.enhancedblockentities.client.model.item;\n\nimport com.mojang.serialization.MapCodec;\nimport found"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/model/misc/DecoratedPotModelSelector.java",
"chars": 3375,
"preview": "package foundationgames.enhancedblockentities.client.model.misc;\n\nimport foundationgames.enhancedblockentities.client.mo"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRenderCondition.java",
"chars": 2354,
"preview": "package foundationgames.enhancedblockentities.client.render;\n\nimport foundationgames.enhancedblockentities.EnhancedBlock"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/BlockEntityRendererOverride.java",
"chars": 1086,
"preview": "package foundationgames.enhancedblockentities.client.render;\n\nimport foundationgames.enhancedblockentities.event.EBEEven"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/SignRenderManager.java",
"chars": 480,
"preview": "package foundationgames.enhancedblockentities.client.render;\n\nimport net.fabricmc.fabric.api.client.rendering.v1.WorldRe"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/entity/BellBlockEntityRendererOverride.java",
"chars": 2705,
"preview": "package foundationgames.enhancedblockentities.client.render.entity;\n\nimport foundationgames.enhancedblockentities.client"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/entity/ChestBlockEntityRendererOverride.java",
"chars": 3806,
"preview": "package foundationgames.enhancedblockentities.client.render.entity;\n\nimport foundationgames.enhancedblockentities.client"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/entity/DecoratedPotBlockEntityRendererOverride.java",
"chars": 5502,
"preview": "package foundationgames.enhancedblockentities.client.render.entity;\n\nimport com.google.common.collect.ImmutableMap;\nimpo"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/entity/ShulkerBoxBlockEntityRendererOverride.java",
"chars": 2595,
"preview": "package foundationgames.enhancedblockentities.client.render.entity;\n\nimport foundationgames.enhancedblockentities.client"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/render/entity/SignBlockEntityRendererOverride.java",
"chars": 1640,
"preview": "package foundationgames.enhancedblockentities.client.render.entity;\n\nimport foundationgames.enhancedblockentities.client"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/resource/AtlasResourceBuilder.java",
"chars": 844,
"preview": "package foundationgames.enhancedblockentities.client.resource;\n\nimport com.google.gson.Gson;\nimport com.google.gson.Json"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/resource/EBEPack.java",
"chars": 6857,
"preview": "package foundationgames.enhancedblockentities.client.resource;\n\nimport foundationgames.enhancedblockentities.client.reso"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateDefinitions.java",
"chars": 1408,
"preview": "package foundationgames.enhancedblockentities.client.resource.template;\n\nimport org.jetbrains.annotations.NotNull;\n\nimpo"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateLoader.java",
"chars": 1030,
"preview": "package foundationgames.enhancedblockentities.client.resource.template;\n\nimport java.io.IOException;\nimport java.nio.cha"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/client/resource/template/TemplateProvider.java",
"chars": 1662,
"preview": "package foundationgames.enhancedblockentities.client.resource.template;\n\nimport java.io.IOException;\nimport java.util.Ha"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/EBEConfig.java",
"chars": 9660,
"preview": "package foundationgames.enhancedblockentities.config;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntitie"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/EBEModMenuPlugin.java",
"chars": 426,
"preview": "package foundationgames.enhancedblockentities.config.gui;\n\nimport com.terraformersmc.modmenu.api.ConfigScreenFactory;\nim"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/option/ConfigButtonOption.java",
"chars": 1759,
"preview": "package foundationgames.enhancedblockentities.config.gui.option;\n\nimport com.mojang.serialization.Codec;\nimport foundati"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/option/EBEOption.java",
"chars": 3782,
"preview": "package foundationgames.enhancedblockentities.config.gui.option;\n\nimport foundationgames.enhancedblockentities.ReloadTyp"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/option/TextPalette.java",
"chars": 863,
"preview": "package foundationgames.enhancedblockentities.config.gui.option;\n\npublic interface TextPalette {\n TextPalette ON_OFF "
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/screen/EBEConfigScreen.java",
"chars": 10380,
"preview": "package foundationgames.enhancedblockentities.config.gui.screen;\n\nimport com.google.common.collect.ImmutableList;\nimport"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/widget/SectionTextWidget.java",
"chars": 1399,
"preview": "package foundationgames.enhancedblockentities.config.gui.widget;\n\nimport net.minecraft.client.font.TextRenderer;\nimport "
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/config/gui/widget/WidgetRowListWidget.java",
"chars": 2613,
"preview": "package foundationgames.enhancedblockentities.config.gui.widget;\n\nimport net.minecraft.client.MinecraftClient;\nimport ne"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/event/EBEEvents.java",
"chars": 386,
"preview": "package foundationgames.enhancedblockentities.event;\n\nimport net.fabricmc.fabric.api.event.Event;\nimport net.fabricmc.fa"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/AbstractBlockStateMixin.java",
"chars": 1005,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntityRe"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/AbstractSignBlockEntityRenderAccessor.java",
"chars": 1113,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport net.minecraft.block.BlockState;\nimport net.minecraft.block."
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/BellBlockEntityMixin.java",
"chars": 2201,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/BlockEntityRenderDispatcherMixin.java",
"chars": 2227,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntityRe"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/BuiltChunkMixin.java",
"chars": 760,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.util.duck.ChunkRebuil"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/ChestBlockEntityMixin.java",
"chars": 2214,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/DecoratedPotBlockEntityMixin.java",
"chars": 2502,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.util.WorldUtil;\nimpor"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/EnderChestBlockEntityMixin.java",
"chars": 2239,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/LifecycledResourceManagerImplMixin.java",
"chars": 2274,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.util.EBEUtil;\nimport "
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/MinecraftClientMixin.java",
"chars": 810,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.event.EBEEvents;\nimpo"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/ShulkerBoxBlockEntityMixin.java",
"chars": 1897,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.util.duck.AppearanceS"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/SignEditScreenMixin.java",
"chars": 2329,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/VideoOptionsScreenMixin.java",
"chars": 1254,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.config.gui.option.Con"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/WorldRendererMixin.java",
"chars": 1650,
"preview": "package foundationgames.enhancedblockentities.mixin;\n\nimport foundationgames.enhancedblockentities.util.WorldUtil;\nimpor"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionManagerMixin.java",
"chars": 2391,
"preview": "package foundationgames.enhancedblockentities.mixin.compat.sodium;\n\nimport foundationgames.enhancedblockentities.util.Wo"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/mixin/compat/sodium/RenderSectionMixin.java",
"chars": 951,
"preview": "package foundationgames.enhancedblockentities.mixin.compat.sodium;\n\nimport foundationgames.enhancedblockentities.util.du"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/ConvUtil.java",
"chars": 330,
"preview": "package foundationgames.enhancedblockentities.util;\n\npublic enum ConvUtil {;\n public static boolean bool(String bool)"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/DateUtil.java",
"chars": 504,
"preview": "package foundationgames.enhancedblockentities.util;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities;"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/EBEUtil.java",
"chars": 2916,
"preview": "package foundationgames.enhancedblockentities.util;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities;"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/ExecutableRunnableHashSet.java",
"chars": 250,
"preview": "package foundationgames.enhancedblockentities.util;\n\nimport java.util.HashSet;\n\npublic class ExecutableRunnableHashSet e"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/GuiUtil.java",
"chars": 885,
"preview": "package foundationgames.enhancedblockentities.util;\n\nimport net.minecraft.text.Text;\nimport net.minecraft.util.Formattin"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/ResourceUtil.java",
"chars": 19597,
"preview": "package foundationgames.enhancedblockentities.util;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEntities;"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/WorldUtil.java",
"chars": 1959,
"preview": "package foundationgames.enhancedblockentities.util;\n\nimport it.unimi.dsi.fastutil.longs.Long2ObjectMap;\nimport it.unimi."
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/duck/AppearanceStateHolder.java",
"chars": 633,
"preview": "package foundationgames.enhancedblockentities.util.duck;\n\nimport foundationgames.enhancedblockentities.util.WorldUtil;\ni"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/duck/ChunkRebuildTaskAccess.java",
"chars": 452,
"preview": "package foundationgames.enhancedblockentities.util.duck;\n\npublic interface ChunkRebuildTaskAccess {\n Runnable enhance"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/hacks/ExperimentalSetup.java",
"chars": 3846,
"preview": "package foundationgames.enhancedblockentities.util.hacks;\n\nimport foundationgames.enhancedblockentities.EnhancedBlockEnt"
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/hacks/ResourceHacks.java",
"chars": 2080,
"preview": "package foundationgames.enhancedblockentities.util.hacks;\n\nimport foundationgames.enhancedblockentities.client.resource."
},
{
"path": "src/main/java/foundationgames/enhancedblockentities/util/hacks/TextureHacks.java",
"chars": 1954,
"preview": "package foundationgames.enhancedblockentities.util.hacks;\n\nimport net.minecraft.client.texture.NativeImage;\nimport org.j"
},
{
"path": "src/main/resources/assets/enhancedblockentities/lang/en_us.json",
"chars": 6930,
"preview": "{\n \"option.ebe.config\": \"Block Entities...\",\n\n \"value.ebe.true\": \"On\",\n \"value.ebe.false\": \"Off\",\n \"value.eb"
},
{
"path": "src/main/resources/assets/enhancedblockentities/lang/ru_ru.json",
"chars": 6924,
"preview": "{\n \"option.ebe.config\": \"Блоки-сущности...\",\n\n \"value.ebe.true\": \"Вкл\",\n \"value.ebe.false\": \"Выкл\",\n \"value."
},
{
"path": "src/main/resources/assets/enhancedblockentities/lang/zh_cn.json",
"chars": 3487,
"preview": "{\n \"option.ebe.config\": \"方块实体...\",\n\n \"value.ebe.true\": \"开\",\n \"value.ebe.false\": \"关\",\n \"value.ebe.allowed\": \""
},
{
"path": "src/main/resources/assets/minecraft/models/block/bell_between_walls_with_bell.json",
"chars": 1549,
"preview": "{\n\t\"textures\": {\n\t\t\"bell\": \"entity/bell/bell_body\",\n\t\t\"bar\": \"block/dark_oak_planks\",\n\t\t\"particle\": \"entity/bell/bell_bo"
},
{
"path": "src/main/resources/assets/minecraft/models/block/bell_body.json",
"chars": 1108,
"preview": "{\n\t\"texture_size\": [32, 32],\n\t\"textures\": {\n\t\t\"bell\": \"entity/bell/bell_body\",\n\t\t\"particle\": \"entity/bell/bell_body\"\n\t},"
},
{
"path": "src/main/resources/assets/minecraft/models/block/bell_ceiling_with_bell.json",
"chars": 1577,
"preview": "{\n\t\"textures\": {\n\t\t\"bell\": \"entity/bell/bell_body\",\n\t\t\"bar\": \"block/dark_oak_planks\",\n\t\t\"particle\": \"entity/bell/bell_bo"
},
{
"path": "src/main/resources/assets/minecraft/models/block/bell_floor_with_bell.json",
"chars": 2344,
"preview": "{\n\t\"textures\": {\n\t\t\"bell\": \"entity/bell/bell_body\",\n\t\t\"bar\": \"block/dark_oak_planks\",\n\t\t\"post\": \"block/stone\",\n\t\t\"partic"
},
{
"path": "src/main/resources/assets/minecraft/models/block/bell_wall_with_bell.json",
"chars": 1529,
"preview": "{\n\t\"textures\": {\n\t\t\"bell\": \"entity/bell/bell_body\",\n\t\t\"bar\": \"block/dark_oak_planks\",\n\t\t\"particle\": \"entity/bell/bell_bo"
},
{
"path": "src/main/resources/assets/minecraft/models/block/decorated_pot_base.json",
"chars": 1109,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [32, 32],\n\t\"textures\": {\n\t\t\"0\": \"entity/decorated_pot/decorated_pot_base\",\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/decorated_pot_shaking.json",
"chars": 68,
"preview": "{\n \"textures\": {\n \"particle\": \"minecraft:block/terracotta\"\n }\n}"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_bed_foot.json",
"chars": 1718,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#bed\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_bed_foot_ao.json",
"chars": 1717,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#bed\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\"f"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_bed_foot_offset.json",
"chars": 1719,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#bed\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_bed_head.json",
"chars": 1662,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#bed\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_bed_head_ao.json",
"chars": 1661,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#bed\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\"f"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_center.json",
"chars": 1698,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_center_lid.json",
"chars": 1295,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_center_trunk.json",
"chars": 724,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_left.json",
"chars": 1546,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_left_lid.json",
"chars": 1117,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_left_trunk.json",
"chars": 657,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_right.json",
"chars": 1452,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_right_lid.json",
"chars": 1107,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_chest_right_trunk.json",
"chars": 652,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#chest\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_0.json",
"chars": 2568,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_0_ao.json",
"chars": 2566,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_22_5.json",
"chars": 2647,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_22_5_ao.json",
"chars": 2645,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_45.json",
"chars": 2629,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_45_ao.json",
"chars": 2627,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_67_5.json",
"chars": 2677,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [7, 0, 1],\n\t\t\t\"to\": [9, 10, 15],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_67_5_ao.json",
"chars": 2675,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [7, 0, 1],\n\t\t\t\"to\": [9, 10, 15],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_0.json",
"chars": 974,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_0_ao.json",
"chars": 972,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_22_5.json",
"chars": 1043,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_22_5_ao.json",
"chars": 1041,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_45.json",
"chars": 1039,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_45_ao.json",
"chars": 1037,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_67_5.json",
"chars": 1111,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [7, 0, 1],\n\t\t\t\"to\": [9, 10, 15],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_hanging_sign_attached_67_5_ao.json",
"chars": 1109,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [7, 0, 1],\n\t\t\t\"to\": [9, 10, 15],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_pottery_pattern_east.json",
"chars": 177,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 1],\n\t\t\t\"to\": [15, 16, 15],\n\t\t\t\"faces\": {\n\t\t\t\t\"east\": {\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_pottery_pattern_north.json",
"chars": 178,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 1],\n\t\t\t\"to\": [15, 16, 15],\n\t\t\t\"faces\": {\n\t\t\t\t\"north\": {"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_pottery_pattern_south.json",
"chars": 178,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 1],\n\t\t\t\"to\": [15, 16, 15],\n\t\t\t\"faces\": {\n\t\t\t\t\"south\": {"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_pottery_pattern_west.json",
"chars": 177,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 1],\n\t\t\t\"to\": [15, 16, 15],\n\t\t\t\"faces\": {\n\t\t\t\t\"west\": {\""
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_shulker_box.json",
"chars": 1050,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#shulker\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_shulker_box_bottom.json",
"chars": 976,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#shulker\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_shulker_box_lid.json",
"chars": 952,
"preview": "{\n\t\"parent\": \"block/block\",\n\t\"texture_size\": [64, 64],\n\t\"textures\": {\n\t\t\"particle\": \"#shulker\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_0.json",
"chars": 956,
"preview": "{\n \"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_0_ao.json",
"chars": 955,
"preview": "{\n \"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_22_5.json",
"chars": 1085,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_22_5_ao.json",
"chars": 1087,
"preview": "{\n \"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_45.json",
"chars": 1081,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_45_ao.json",
"chars": 1083,
"preview": "{\n \"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_67_5.json",
"chars": 1136,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_sign_67_5_ao.json",
"chars": 1138,
"preview": "{\n \"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_wall_hanging_sign.json",
"chars": 3023,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_wall_hanging_sign_ao.json",
"chars": 3022,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"elements\": [\n\t\t{\n\t\t\t\"from\": [1, 0, 7],\n\t\t\t\"to\": [15, 10, 9],\n\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_wall_sign.json",
"chars": 616,
"preview": "{\n\t\"ambientocclusion\": false,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t"
},
{
"path": "src/main/resources/assets/minecraft/models/block/template_wall_sign_ao.json",
"chars": 615,
"preview": "{\n\t\"ambientocclusion\": true,\n\t\"texture_size\": [64, 32],\n\t\"textures\": {\n\t\t\"particle\": \"#sign\"\n\t},\n\t\"elements\": [\n\t\t{\n\t\t\t\""
},
{
"path": "src/main/resources/assets/minecraft/models/item/christmas_chest.json",
"chars": 45,
"preview": "{\n\t\"parent\": \"block/christmas_chest_center\"\n}"
},
{
"path": "src/main/resources/enhancedblockentities.accesswidener",
"chars": 451,
"preview": "accessWidener v2 named\n\naccessible class net/minecraft/client/option/SimpleOption$Callbacks\naccessible "
},
{
"path": "src/main/resources/enhancedblockentities.mixins.json",
"chars": 746,
"preview": "{\n \"required\": true,\n \"minVersion\": \"0.8\",\n \"package\": \"foundationgames.enhancedblockentities.mixin\",\n \"compatibilit"
},
{
"path": "src/main/resources/fabric.mod.json",
"chars": 1224,
"preview": "{\n \"schemaVersion\": 1,\n \"id\": \"enhancedblockentities\",\n \"version\": \"${version}\",\n\n \"name\": \"Enhanced Block Entities\""
},
{
"path": "src/main/resources/templates/blockstate/base.json",
"chars": 35,
"preview": "{\n \"variants\": {\n ![vars]\n }\n}"
},
{
"path": "src/main/resources/templates/blockstate/var.json",
"chars": 41,
"preview": "\"![state]\": {![extra]\"model\": \"![model]\"}"
},
{
"path": "src/main/resources/templates/item/bed.json",
"chars": 264,
"preview": "{\n \"model\": {\n \"type\": \"minecraft:composite\",\n \"models\": [\n {\n \"type\": \"minecraft:model\",\n \"mo"
},
{
"path": "src/main/resources/templates/item/chest_item.json",
"chars": 307,
"preview": "{\n \"model\": {\n \"type\": \"minecraft:condition\",\n \"on_false\": {\n \"type\": \"minecraft:model\",\n \"model\": \"min"
},
{
"path": "src/main/resources/templates/item/chest_item_no_christmas.json",
"chars": 91,
"preview": "{\n \"model\": {\n \"type\": \"minecraft:model\",\n \"model\": \"minecraft:block/![chest]\"\n }\n}"
},
{
"path": "src/main/resources/templates/model/bed_foot_item.json",
"chars": 904,
"preview": "{\n \"parent\": \"minecraft:block/template_bed_foot_offset\",\n \"textures\": {\n \"bed\": \"minecraft:entity/bed/![bed]\"\n },\n"
},
{
"path": "src/main/resources/templates/model/bed_head_item.json",
"chars": 833,
"preview": "{\n \"parent\": \"minecraft:block/![bed]_bed_head\",\n \"display\": {\n \"thirdperson_righthand\": {\n \"rotation\": [ 30, 3"
},
{
"path": "src/main/resources/templates/model/chest_like.json",
"chars": 111,
"preview": "{\n \"parent\": \"block/![parent]\",\n \"textures\": {\n ![particle]\n \"chest\": \"entity/chest/![chest_tex]\"\n }\n}"
},
{
"path": "src/main/resources/templates/model/parent_and_tex.json",
"chars": 64,
"preview": "{\n \"parent\": \"![parent]\",\n \"textures\": {\n ![textures]\n }\n}"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the FoundationGames/EnhancedBlockEntities GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 145 files (300.9 KB), approximately 95.9k tokens, and a symbol index with 358 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.