Showing preview only (627K chars total). Download the full file or copy to clipboard to get everything.
Repository: Darkhax-Minecraft/Bookshelf
Branch: 1.21.1
Commit: 5dead2485866
Files: 225
Total size: 544.4 KB
Directory structure:
gitextract_et8g_e68/
├── .gitattributes
├── .gitignore
├── Jenkinsfile
├── LICENSE
├── README.md
├── build.gradle
├── buildSrc/
│ ├── build.gradle
│ └── src/
│ └── main/
│ └── groovy/
│ ├── build-number.gradle
│ ├── git-changelog.gradle
│ ├── minify-json.gradle
│ ├── multiloader-common.gradle
│ ├── multiloader-loader.gradle
│ ├── patreon.gradle
│ ├── project_validation.gradle
│ ├── readme-update.gradle
│ ├── secret-loader.gradle
│ └── version-checker.gradle
├── common/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── java/
│ │ └── net/
│ │ └── darkhax/
│ │ └── bookshelf/
│ │ └── common/
│ │ ├── api/
│ │ │ ├── ModEntry.java
│ │ │ ├── PhysicalSide.java
│ │ │ ├── annotation/
│ │ │ │ ├── InternalUse.java
│ │ │ │ └── OnlyFor.java
│ │ │ ├── block/
│ │ │ │ └── IBlockHooks.java
│ │ │ ├── commands/
│ │ │ │ ├── IEnumCommand.java
│ │ │ │ ├── PermissionLevel.java
│ │ │ │ └── args/
│ │ │ │ ├── ArgumentSerializer.java
│ │ │ │ ├── FontArgument.java
│ │ │ │ ├── SingletonArgumentInfo.java
│ │ │ │ └── TagArgument.java
│ │ │ ├── data/
│ │ │ │ ├── BookshelfTags.java
│ │ │ │ ├── ISidedRecipeManager.java
│ │ │ │ ├── codecs/
│ │ │ │ │ ├── EnumStreamCodec.java
│ │ │ │ │ ├── map/
│ │ │ │ │ │ ├── MapCodecHelper.java
│ │ │ │ │ │ ├── MapCodecs.java
│ │ │ │ │ │ └── RegistryMapCodecHelper.java
│ │ │ │ │ └── stream/
│ │ │ │ │ └── StreamCodecs.java
│ │ │ │ ├── conditions/
│ │ │ │ │ ├── ConditionType.java
│ │ │ │ │ ├── ILoadCondition.java
│ │ │ │ │ └── LoadConditions.java
│ │ │ │ ├── enchantment/
│ │ │ │ │ └── EnchantmentLevel.java
│ │ │ │ ├── ingredient/
│ │ │ │ │ └── IngredientLogic.java
│ │ │ │ └── loot/
│ │ │ │ ├── PoolTarget.java
│ │ │ │ └── modifiers/
│ │ │ │ └── LootPoolAddition.java
│ │ │ ├── entity/
│ │ │ │ └── villager/
│ │ │ │ ├── MerchantTier.java
│ │ │ │ └── trades/
│ │ │ │ ├── VillagerBuys.java
│ │ │ │ ├── VillagerOffers.java
│ │ │ │ └── VillagerSells.java
│ │ │ ├── function/
│ │ │ │ ├── CachedSupplier.java
│ │ │ │ ├── QuadConsumer.java
│ │ │ │ ├── ReloadableCache.java
│ │ │ │ ├── SidedReloadableCache.java
│ │ │ │ ├── TriConsumer.java
│ │ │ │ └── TriFunction.java
│ │ │ ├── item/
│ │ │ │ └── IItemHooks.java
│ │ │ ├── loot/
│ │ │ │ ├── LootPoolEntryDescriber.java
│ │ │ │ └── LootPoolEntryDescriptions.java
│ │ │ ├── menu/
│ │ │ │ ├── data/
│ │ │ │ │ └── BlockPosData.java
│ │ │ │ └── slot/
│ │ │ │ ├── InputSlot.java
│ │ │ │ └── OutputSlot.java
│ │ │ ├── network/
│ │ │ │ ├── AbstractPacket.java
│ │ │ │ ├── Destination.java
│ │ │ │ ├── INetworkHandler.java
│ │ │ │ └── IPacket.java
│ │ │ ├── registry/
│ │ │ │ ├── ContentProvider.java
│ │ │ │ ├── RegistrationContext.java
│ │ │ │ ├── RegistryReference.java
│ │ │ │ └── adapters/
│ │ │ │ ├── GameRegistryAdapter.java
│ │ │ │ ├── GenericRegistryAdapter.java
│ │ │ │ └── RegistryAdapter.java
│ │ │ ├── service/
│ │ │ │ └── Services.java
│ │ │ ├── text/
│ │ │ │ ├── font/
│ │ │ │ │ ├── BuiltinFonts.java
│ │ │ │ │ └── IFontEntry.java
│ │ │ │ ├── format/
│ │ │ │ │ ├── IPropertyFormat.java
│ │ │ │ │ └── PropertyFormat.java
│ │ │ │ └── unit/
│ │ │ │ ├── IUnit.java
│ │ │ │ └── Units.java
│ │ │ └── util/
│ │ │ ├── CommandHelper.java
│ │ │ ├── DataHelper.java
│ │ │ ├── ExperienceHelper.java
│ │ │ ├── FunctionHelper.java
│ │ │ ├── IGameplayHelper.java
│ │ │ ├── IPlatformHelper.java
│ │ │ ├── IRenderHelper.java
│ │ │ ├── MathsHelper.java
│ │ │ ├── TextHelper.java
│ │ │ └── TickAccumulator.java
│ │ ├── impl/
│ │ │ ├── BookshelfContent.java
│ │ │ ├── BookshelfMod.java
│ │ │ ├── Constants.java
│ │ │ ├── DebugContentProvider.java
│ │ │ ├── command/
│ │ │ │ ├── BlockTagToItemTagCommand.java
│ │ │ │ ├── DebugCommands.java
│ │ │ │ ├── EnchantCommand.java
│ │ │ │ ├── FontCommand.java
│ │ │ │ ├── HandCommand.java
│ │ │ │ ├── RenameCommand.java
│ │ │ │ ├── StructureCommand.java
│ │ │ │ └── TranslateCommand.java
│ │ │ ├── data/
│ │ │ │ ├── conditions/
│ │ │ │ │ ├── And.java
│ │ │ │ │ ├── ModLoaded.java
│ │ │ │ │ ├── Not.java
│ │ │ │ │ ├── OnPlatform.java
│ │ │ │ │ ├── Or.java
│ │ │ │ │ └── RegistryContains.java
│ │ │ │ ├── criterion/
│ │ │ │ │ ├── item/
│ │ │ │ │ │ └── NamespaceItemPredicate.java
│ │ │ │ │ └── trigger/
│ │ │ │ │ └── AdvancementTrigger.java
│ │ │ │ ├── ingredient/
│ │ │ │ │ ├── AllOfIngredient.java
│ │ │ │ │ ├── BlockTagIngredient.java
│ │ │ │ │ ├── EitherIngredient.java
│ │ │ │ │ ├── FalseIngredient.java
│ │ │ │ │ └── ModIdIngredient.java
│ │ │ │ └── loot/
│ │ │ │ ├── entries/
│ │ │ │ │ └── LootItemStack.java
│ │ │ │ └── modifiers/
│ │ │ │ ├── FingerprintCodec.java
│ │ │ │ ├── ILootPoolHooks.java
│ │ │ │ └── LootModificationHandler.java
│ │ │ ├── recipe/
│ │ │ │ └── RecipeTypeImpl.java
│ │ │ ├── registry/
│ │ │ │ └── adapter/
│ │ │ │ ├── BlockEntityRendererAdapter.java
│ │ │ │ ├── BlockRegistryAdapter.java
│ │ │ │ ├── BlockRenderTypeAdapter.java
│ │ │ │ ├── CommandArgumentAdapter.java
│ │ │ │ ├── CreativeModeTabAdapter.java
│ │ │ │ ├── IngredientTypeAdapter.java
│ │ │ │ ├── LootDescriptionAdapter.java
│ │ │ │ ├── LootEntryTypeAdapter.java
│ │ │ │ ├── LootPoolAdditionAdapter.java
│ │ │ │ ├── MenuScreenAdapter.java
│ │ │ │ ├── MenuTypeAdapter.java
│ │ │ │ ├── PacketAdapter.java
│ │ │ │ ├── PotPatternAdapter.java
│ │ │ │ ├── PotionBrewAdapter.java
│ │ │ │ ├── RecipeTypeAdapter.java
│ │ │ │ ├── SoundEventAdapter.java
│ │ │ │ └── VillagerTradeAdapter.java
│ │ │ └── resources/
│ │ │ └── ExtendedText.java
│ │ └── mixin/
│ │ ├── access/
│ │ │ ├── block/
│ │ │ │ ├── AccessorBannerBlockEntity.java
│ │ │ │ ├── AccessorBaseContainerBlockEntity.java
│ │ │ │ ├── AccessorBlockEntityRenderers.java
│ │ │ │ └── AccessorCropBlock.java
│ │ │ ├── client/
│ │ │ │ ├── AccessorFontManager.java
│ │ │ │ ├── AccessorItemBlockRenderTypes.java
│ │ │ │ ├── AccessorMinecraft.java
│ │ │ │ └── gui/
│ │ │ │ └── AccessorAbstractWidget.java
│ │ │ ├── entity/
│ │ │ │ └── AccessorEntity.java
│ │ │ ├── level/
│ │ │ │ └── AccessorRecipeManager.java
│ │ │ ├── loot/
│ │ │ │ ├── AccessorCompositeEntryBase.java
│ │ │ │ ├── AccessorDynamicLoot.java
│ │ │ │ ├── AccessorLootItem.java
│ │ │ │ ├── AccessorLootPool.java
│ │ │ │ ├── AccessorLootPoolSingletonContainer.java
│ │ │ │ ├── AccessorLootTable.java
│ │ │ │ ├── AccessorNestedLootTable.java
│ │ │ │ └── AccessorTagEntry.java
│ │ │ └── particles/
│ │ │ └── AccessSimpleParticleType.java
│ │ └── patch/
│ │ ├── advancement/
│ │ │ └── MixinPlayerAdvancements.java
│ │ ├── block/
│ │ │ └── MixinDecoratedPotPatterns.java
│ │ ├── client/
│ │ │ └── MixinClientPacketListener.java
│ │ ├── entity/
│ │ │ ├── MixinLightningBolt.java
│ │ │ └── MixinLivingEntity.java
│ │ ├── item/
│ │ │ └── MixinCreativeModeTab.java
│ │ ├── level/
│ │ │ ├── MixinRecipeManager.java
│ │ │ └── MixinWalkNodeEvaluator.java
│ │ ├── locale/
│ │ │ └── MixinClientLanguage.java
│ │ ├── loot/
│ │ │ ├── MixinLootDataType.java
│ │ │ ├── MixinLootItemKilledByPlayerCondition.java
│ │ │ └── MixinLootPool.java
│ │ ├── packs/
│ │ │ └── MixinSimpleJsonResourceReloadListener.java
│ │ ├── potions/
│ │ │ └── MixinPotionBrewing.java
│ │ └── server/
│ │ └── MixinReloadableServerResources.java
│ └── resources/
│ ├── META-INF/
│ │ └── services/
│ │ └── net.darkhax.bookshelf.common.api.registry.ContentProvider
│ ├── assets/
│ │ └── bookshelf/
│ │ └── lang/
│ │ ├── en_us.json
│ │ ├── es_ar.json
│ │ ├── ja_jp.json
│ │ ├── pt_br.json
│ │ └── zh_cn.json
│ ├── bookshelf.mixins.json
│ ├── data/
│ │ └── bookshelf/
│ │ ├── damage_type/
│ │ │ └── fake_player.json
│ │ └── tags/
│ │ ├── damage_type/
│ │ │ └── fake_player.json
│ │ └── item/
│ │ └── creative_tab/
│ │ └── minecraft/
│ │ ├── building_blocks.json
│ │ ├── colored_blocks.json
│ │ ├── combat.json
│ │ ├── food_and_drinks.json
│ │ ├── functional_blocks.json
│ │ ├── ingredients.json
│ │ ├── natural_blocks.json
│ │ ├── op_blocks.json
│ │ ├── redstone_blocks.json
│ │ ├── spawn_eggs.json
│ │ └── tools_and_utilities.json
│ └── pack.mcmeta
├── fabric/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── java/
│ │ └── net/
│ │ └── darkhax/
│ │ └── bookshelf/
│ │ └── fabric/
│ │ └── impl/
│ │ ├── FabricMod.java
│ │ ├── FabricModClient.java
│ │ ├── data/
│ │ │ └── FabricIngredient.java
│ │ ├── network/
│ │ │ └── FabricNetworkHandler.java
│ │ └── util/
│ │ ├── FabricGameplayHelper.java
│ │ ├── FabricPlatformHelper.java
│ │ ├── FabricRegistryHelper.java
│ │ └── FabricRenderHelper.java
│ └── resources/
│ ├── META-INF/
│ │ └── services/
│ │ ├── net.darkhax.bookshelf.common.api.network.INetworkHandler
│ │ ├── net.darkhax.bookshelf.common.api.util.IGameplayHelper
│ │ ├── net.darkhax.bookshelf.common.api.util.IPlatformHelper
│ │ └── net.darkhax.bookshelf.common.api.util.IRenderHelper
│ ├── bookshelf.fabric.mixins.json
│ └── fabric.mod.json
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── neoforge/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── java/
│ │ └── net/
│ │ └── darkhax/
│ │ └── bookshelf/
│ │ └── neoforge/
│ │ ├── impl/
│ │ │ ├── NeoForgeMod.java
│ │ │ ├── data/
│ │ │ │ └── NeoForgeIngredient.java
│ │ │ ├── network/
│ │ │ │ └── NeoForgeNetworkHandler.java
│ │ │ └── util/
│ │ │ ├── NeoForgeGameplayHelper.java
│ │ │ ├── NeoForgePlatformHelper.java
│ │ │ ├── NeoForgeRegistryHelper.java
│ │ │ └── NeoForgeRenderHelper.java
│ │ └── mixin/
│ │ └── access/
│ │ └── gui/
│ │ └── screen/
│ │ └── AccessorMenuScreens.java
│ └── resources/
│ ├── META-INF/
│ │ ├── neoforge.mods.toml
│ │ └── services/
│ │ ├── net.darkhax.bookshelf.common.api.network.INetworkHandler
│ │ ├── net.darkhax.bookshelf.common.api.util.IGameplayHelper
│ │ ├── net.darkhax.bookshelf.common.api.util.IPlatformHelper
│ │ └── net.darkhax.bookshelf.common.api.util.IRenderHelper
│ └── bookshelf.neoforge.mixins.json
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
* text eol=lf
*.bat text eol=crlf
*.patch text eol=lf
*.java text eol=lf
*.gradle text eol=crlf
*.png binary
*.gif binary
*.exe binary
*.dll binary
*.jar binary
*.lzma binary
*.zip binary
*.pyd binary
*.cfg text eol=lf
*.jks binary
================================================
FILE: .gitignore
================================================
# eclipse
bin
*.launch
.settings
.metadata
.classpath
.project
# idea
out
*.ipr
*.iws
*.iml
.idea/*
!.idea/scopes
# gradle
build
.gradle
# other
eclipse
run
runs
.profileconfig.json
================================================
FILE: Jenkinsfile
================================================
#!/usr/bin/env groovy
pipeline {
agent any
tools {
jdk "jdk-21"
}
stages {
stage('Setup') {
steps {
echo 'Setup Project'
sh 'chmod +x gradlew'
sh './gradlew clean'
}
}
stage('Build') {
steps {
withCredentials([
file(credentialsId: 'build_secrets', variable: 'ORG_GRADLE_PROJECT_secretFile'),
file(credentialsId: 'java_keystore', variable: 'ORG_GRADLE_PROJECT_keyStore'),
file(credentialsId: 'gpg_key', variable: 'ORG_GRADLE_PROJECT_pgpKeyRing')
]) {
echo 'Building project.'
sh './gradlew build publish publishCurseForge modrinth updateVersionTracker --stacktrace --warn'
}
}
}
}
}
================================================
FILE: LICENSE
================================================
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU
General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the
software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated software packages--typically
libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest
you first think carefully about whether this license or the ordinary General Public License is the better strategy to
use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed
to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish);
that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new
free programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to
surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the
library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the
rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code
with the library, you must provide complete object files to the recipients, so that they can relink them with the
library after making changes to the library and recompiling it. And you must show them these terms so they know their
rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which
gives you legal permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the
library is modified by someone else and passed on, the recipients should know that what they have is not the original
version, so that the original author's reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a
company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder.
Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full
freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the
GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary
General Public License. We use this license for certain libraries in order to permit linking those libraries into
non-free programs.
When a program is linked with a library, whether statically or using a shared library, the combination of the two is
legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore
permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License
permits more lax criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the
ordinary General Public License. It also provides other free software developers Less of an advantage over competing
non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries.
However, the Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library,
so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more
frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little
to gain by limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a
large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more
people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a
program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version
of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the
difference between a
"work based on the library" and a "work that uses the library". The former contains code derived from the library,
whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND
CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program which contains a notice placed by the
copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public
License (also called "this License"). Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with
application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work
based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work
containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly
into another language. (Hereinafter, translation is included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete
source code means all the source code for all modules it contains, plus any associated interface definition files, plus
the scripts used to control compilation and installation of the library.
Activities other than copying, distribution and modification are not covered by this License; they are outside its
scope. The act of running a program using the Library is not restricted, and output from such a program is covered only
if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it).
Whether that is true depends on what the Library does and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium,
provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer
of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and
distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection
in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and
copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of
these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of
any change.
c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this
License.
d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application
program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a
good faith effort to ensure that, in the event an application does not supply such function or table, the facility
still operates, and performs whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent
of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this
function must be optional: if the application does not supply it, the square root function must still compute square
roots.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the
Library, and can be reasonably considered independent and separate works in themselves, then this License, and its
terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same
sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part
regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you;
rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the
Library.
In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the
Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of
the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the
ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of
the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not
make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy,
so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or
executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete
corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated place, then offering equivalent
access to copy the source code from the same place satisfies the requirement to distribute the source code, even though
third parties are not compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by
being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a
derivative work of the Library, and therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the
Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is
therefore covered by this License. Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for
the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially
significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to
be true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small
inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether
it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall
under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms
of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly
with the Library itself.
6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library
to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided
that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such
modifications.
You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its
use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright
notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to
the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library" must include any data and utility programs
needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not
include anything that is normally distributed (in either source or binary form) with the major components (compiler,
kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the
executable.
It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not
normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in
an executable that you distribute.
7. 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 not covered by this License, and distribute such a combined library, provided that the
separate distribution of the work based on the Library and of the other library facilities is otherwise permitted,
and provided that you do these two things:
a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other
library facilities. This must be distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and
explaining where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this
License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will
automatically terminate your rights under this License. However, parties who have received copies, or rights, from
you under this License will not have their licenses terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it. However, nothing else grants you
permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do
not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you
indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or
modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a
license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and
conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited
to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict
the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute
so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a
consequence you may not distribute the Library at all. For example, if a patent license would not permit
royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to refrain entirely from distribution of the
Library.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the
section is intended to apply, and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest
validity of any such claims; this section has the sole purpose of protecting the integrity of the free software
distribution system which is implemented by public license practices. Many people have made generous contributions to
the wide range of software distributed through that system in reliance on consistent application of that system; it is
up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee
cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted
interfaces, the original copyright holder who places the Library under this License may add an explicit geographical
distribution limitation excluding those countries, so that distribution is permitted only in or among countries not
thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of the 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 specifies a version number of this License which
applies to it and
"any later version", you have the option of following the terms and conditions either of that version or of any later
version published by the Free Software Foundation. If the Library does not specify a license version number, you may
choose any version ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are
incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will
be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting
the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (
INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it
free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (
or, alternatively, under the terms of the ordinary General Public License).
To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each
source file to most effectively convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer"
for the library, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by
James Random Hacker.
<signature of Ty Coon>, 1 April 1990 Ty Coon, President of Vice
That's all there is to it!
================================================
FILE: README.md
================================================
<!-- name-start -->
# Bookshelf [](https://www.curseforge.com/minecraft/mc-mods/bookshelf) [](https://modrinth.com/mod/bookshelf-lib) [](https://maven.blamejared.com/net/darkhax/bookshelf)
<!-- name-end -->
<!-- description-start -->
Bookshelf is a library mod that provides code, frameworks, and utilities for other mods. Many mods make use of Bookshelf and are powered by its code. The documentation for this mod can be found [here](https://docs.darkhax.net/mods/bookshelf).
<!-- description-end -->
## Why use a library mod?
Library mods like Bookshelf allow seemingly unrelated mods to reuse parts
of the same code base. This reduces the amount of time required to develop
and maintain certain mods and features. Library code is also tested in a
wider range of circumstances and communities which can lead to fewer bugs
and faster code.
## Built With Bookshelf
The following mods were built using Bookshelf and are powered by its code!
- [Enchantment Descriptions](https://www.curseforge.com/minecraft/mc-mods/enchantment-descriptions) - Adds in-game descriptions for enchantments to tooltips.
- [Botany Pots](https://www.curseforge.com/minecraft/mc-mods/botany-pots) - Adds pots that you can use to grow crops!
- [Tips](https://www.curseforge.com/minecraft/mc-mods/tips) - Adds tips to various loading screens.
- [Dark Utilities](https://www.curseforge.com/minecraft/mc-mods/dark-utilities) - Blocks and items with interesting effects and abilities.
<!-- maven-start -->
## Maven Dependency
If you are using [Gradle](https://gradle.org) to manage your dependencies, add the following into your `build.gradle` file. Make sure to replace the version with the correct one. All versions can be viewed [here](https://maven.blamejared.com/net/darkhax/bookshelf).
```gradle
repositories {
maven {
url 'https://maven.blamejared.com'
}
}
dependencies {
// NeoForge
implementation group: 'net.darkhax.bookshelf', name: 'bookshelf-neoforge-1.21.1', version: '21.1.0'
// Forge
implementation group: 'net.darkhax.bookshelf', name: 'bookshelf-forge-1.21.1', version: '21.1.0'
// Fabric & Quilt
modImplementation group: 'net.darkhax.bookshelf', name: 'bookshelf-fabric-1.21.1', version: '21.1.0'
// Common / MultiLoader / Vanilla
compileOnly group: 'net.darkhax.bookshelf', name: 'bookshelf-common-1.21.1', version: '21.1.0'
}
```
<!-- maven-end -->
<!-- sponsor-start -->
## Sponsors
[](https://nodecraft.com/r/darkhax)
Bookshelf is sponsored by Nodecraft. Use code **[DARKHAX](https://nodecraft.com/r/darkhax)** for 30% of your first month of service!
<!-- sponsor-end -->
================================================
FILE: build.gradle
================================================
plugins {
id 'secret-loader'
id 'fabric-loom' version '1.11-SNAPSHOT' apply false
id 'net.neoforged.moddev' version '2.0.112' apply false
id 'net.darkhax.curseforgegradle' version '1.1.25' apply(false)
id 'com.modrinth.minotaur' version '2.8.7' apply(false)
id 'project_validation'
id 'build-number'
id 'git-changelog'
id 'patreon'
id 'version-checker'
id 'readme-update'
}
================================================
FILE: buildSrc/build.gradle
================================================
plugins {
id 'groovy-gradle-plugin'
}
repositories {
mavenCentral()
}
dependencies {
implementation group: 'com.diluv.schoomp', name: 'Schoomp', version: '1.2.6'
}
================================================
FILE: buildSrc/src/main/groovy/build-number.gradle
================================================
// This script attempts to append the build number to the project version.
// The build number is read from an environment variable that is set by
// a CI like Jenkins. If the build number is missing it will default to 0.
var buildNumber = System.getenv('BUILD_NUMBER') ? System.getenv('BUILD_NUMBER') : 0
project.version = "${project.version}.${buildNumber}".toString()
project.getSubprojects().each { proj -> proj.version = project.version }
project.logger.lifecycle("Appending build number to version. Build #${buildNumber} Version is now ${project.version}")
================================================
FILE: buildSrc/src/main/groovy/git-changelog.gradle
================================================
project.ext.mod_changelog = 'No changelog was provided. Please refer to the project page for more information.'
try {
project.mod_changelog = 'No changelog was provided. Please refer to the project page for more information.'
def gitCommit = System.getenv('GIT_COMMIT') ?: getExecOutput(['git', 'log', '-n', '1', '--pretty=tformat:%h'])
def gitPrevCommit = System.getenv('GIT_PREVIOUS_COMMIT')
// If a full range is available use that range.
if (gitCommit && gitPrevCommit) {
project.ext.mod_changelog = getExecOutput(['git', 'log', "--pretty=tformat:- %s", '' + gitPrevCommit + '..' + gitCommit])
project.logger.lifecycle("Generated changelog using commits ${gitPrevCommit} to ${gitCommit}.")
}
// If only one commit is available, use the last commit.
else if (gitCommit) {
project.ext.mod_changelog = getExecOutput(['git', 'log', '' + "--pretty=tformat:- %s", '-1', '' + gitCommit])
project.logger.lifecycle("Generated changelog using commit ${gitCommit}.")
}
}
catch (Exception e) {
project.logger.warn("Changelogs could not be generated! ${e.message}")
}
def getExecOutput(commands) {
def out = new ByteArrayOutputStream()
exec {
commandLine commands
standardOutput out
}
return out.toString().trim()
}
================================================
FILE: buildSrc/src/main/groovy/minify-json.gradle
================================================
// This script will minify JSON files as the project is built. This is
// done by removing unused whitespace and newlines from the file. The
// original source file is not modified.
//
// Minifying JSON files will produce a smaller JAR file. This will make
// upload/download times faster, reduce bandwidth usage, and reduce the
// amount of storage space required to use or host the project.
//
// Minified JSON files are also faster to read and parse. The reduced file
// size makes them faster to stream from disk, and the JSON tokenizer does
// not need to waste cycles handling unnecessary data.
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
processResources {
doLast {
def jsonMinifyStart = System.currentTimeMillis()
def jsonMinified = 0
def jsonBytesSaved = 0
fileTree(dir: outputs.files.asPath, include: ['**/*.json', '**/*.mcmeta']).each {
try {
def oldLength = it.length()
it.text = JsonOutput.toJson(new JsonSlurper().parse(it))
jsonBytesSaved += oldLength - it.length()
jsonMinified++
}
catch (Exception e) {
project.logger.error("Failed to minify file '${it.path}'.")
throw e
}
}
project.logger.lifecycle("Minified ${jsonMinified} files. Saved ${jsonBytesSaved} bytes before compression. Took ${System.currentTimeMillis() - jsonMinifyStart}ms.")
}
}
================================================
FILE: buildSrc/src/main/groovy/multiloader-common.gradle
================================================
plugins {
id 'java-library'
id 'maven-publish'
id 'minify-json'
}
base {
archivesName = "${mod_id}-${project.name}-${minecraft_version}"
}
java {
toolchain.languageVersion = JavaLanguageVersion.of(java_version)
withSourcesJar()
withJavadocJar()
}
javadoc {
options.addStringOption('Xdoclint:-missing', '-quiet')
}
repositories {
mavenCentral()
exclusiveContent {
forRepository {
maven {
name = 'Sponge'
url = 'https://repo.spongepowered.org/repository/maven-public'
}
}
filter {
includeGroupAndSubgroups('org.spongepowered')
}
}
exclusiveContent {
forRepositories(
maven {
name = 'ParchmentMC'
url = 'https://maven.parchmentmc.org/'
},
maven {
name = "NeoForge"
url = 'https://maven.neoforged.net/releases'
}
)
filter {
includeGroup('org.parchmentmc.data')
}
}
exclusiveContent {
forRepository {
maven {
url "https://cursemaven.com"
}
}
filter {
includeGroup "curse.maven"
}
}
maven {
name = 'BlameJared'
url = 'https://maven.blamejared.com'
}
}
['apiElements', 'runtimeElements', 'sourcesElements', 'javadocElements'].each { variant ->
configurations."$variant".outgoing {
capability("$group:${base.archivesName.get()}:$version")
capability("$group:$mod_id-${project.name}-${minecraft_version}:$version")
capability("$group:$mod_id:$version")
}
publishing.publications.configureEach {
suppressPomMetadataWarningsFor(variant)
}
}
sourcesJar {
from(rootProject.file('LICENSE')) {
rename { "license_${mod_id}.txt" }
}
}
jar {
from(rootProject.file('LICENSE')) {
rename { "license_${mod_id}.txt" }
}
manifest {
attributes([
'Specification-Title' : mod_name,
'Specification-Vendor' : mod_author,
'Specification-Version' : project.jar.archiveVersion,
'Implementation-Title' : project.name,
'Implementation-Version': project.jar.archiveVersion,
'Implementation-Vendor' : mod_author,
'Built-On-Minecraft' : minecraft_version,
'CurseForge' : curse_page,
'Modrinth' : modrinth_page
])
}
}
processResources {
var expandProps = [
'version' : project.version,
'group' : project.group,
'platform' : project.name,
'minecraft_version' : minecraft_version,
'minecraft_version_range' : minecraft_version_range,
'mod_name' : mod_name,
'mod_author' : mod_author,
'mod_id' : mod_id,
'mod_repo' : mod_repo,
'mod_license' : mod_license,
'mod_description' : mod_description,
'mod_item_icon' : mod_item_icon,
'neoforge_version' : neoforge_version,
'neoforge_loader_version_range': neoforge_loader_version_range,
'fabric_version' : fabric_version,
'fabric_loader_version' : fabric_loader_version,
'java_version' : java_version,
'curse_project' : curse_project,
'curse_page' : curse_page,
'modrinth_project' : modrinth_project,
'modrinth_page' : modrinth_page,
'mod_client_only' : mod_client_only,
'patreon_pledges' : rootProject.ext.patreon.pledgeNames,
'patreon_url' : rootProject.ext.patreon.campaignUrl
]
boolean clientOnly = project.hasProperty('mod_client_only') && project.findProperty('mod_client_only') == 'true'
if ('fabric' == project.name) {
expandProps.put('mod_target_environment', clientOnly ? 'client' : '*')
expandProps.put('mod_target_environment', clientOnly ? 'client' : '*')
}
filesMatching(['pack.mcmeta', 'fabric.mod.json', 'META-INF/mods.toml', 'META-INF/neoforge.mods.toml', '*.mixins.json']) {
expand expandProps
}
inputs.properties(expandProps)
}
publishing {
publications {
register('mavenJava', MavenPublication) {
artifactId base.archivesName.get()
from components.java
}
}
repositories {
maven {
url System.getenv('local_maven_url')
}
}
}
================================================
FILE: buildSrc/src/main/groovy/multiloader-loader.gradle
================================================
plugins {
id 'multiloader-common'
}
configurations {
commonJava{
canBeResolved = true
}
commonResources{
canBeResolved = true
}
}
dependencies {
compileOnly(project(':common')) {
capabilities {
requireCapability "$group:$mod_id"
}
}
commonJava project(path: ':common', configuration: 'commonJava')
commonResources project(path: ':common', configuration: 'commonResources')
}
tasks.named('compileJava', JavaCompile) {
dependsOn(configurations.commonJava)
source(configurations.commonJava)
}
processResources {
dependsOn(configurations.commonResources)
from(configurations.commonResources)
}
tasks.named('javadoc', Javadoc).configure {
dependsOn(configurations.commonJava)
source(configurations.commonJava)
}
tasks.named('sourcesJar', Jar) {
dependsOn(configurations.commonJava)
from(configurations.commonJava)
dependsOn(configurations.commonResources)
from(configurations.commonResources)
}
================================================
FILE: buildSrc/src/main/groovy/patreon.gradle
================================================
import groovy.json.JsonSlurper
project.ext.patreon = [
pledgeNames : '',
campaignUrl : ''
]
project.ext.mod_supporters = 'No supporters loaded.'
if (project.hasProperty('patreon_campaign_id') && project.hasProperty('patreon_auth_token')) {
project.ext.patreon.campaign = project.findProperty('patreon_campaign_id')
def authToken = project.findProperty('patreon_auth_token')
getPledges(project.ext.patreon.campaign, authToken)
if (project.hasProperty('patreon_campaign_url')) {
project.ext.patreon.campaignUrl = project.getProperty('patreon_campaign_url')
}
project.logger.lifecycle("Loading pledge data for default campaign ${project.ext.patreon.campaign}.")
} else {
project.logger.warn("Patreon data can not be loaded! has_id:${project.hasProperty('patreon_campaign_id')} has_campaign:${project.hasProperty('patreon_auth_token')}")
}
/*
Gets a list of pledges for a specified campaign using a specified auth token.
*/
def getPledges(campaignId, authToken) {
// Connect to the Patreon API using the provided auth info.
def connection = new URL('https://www.patreon.com/api/oauth2/api/campaigns/' + campaignId + '/pledges').openConnection() as HttpURLConnection
connection.setRequestProperty('User-Agent', 'Patreon-Groovy, platform ' + System.properties['os.name'] + ' ' + System.properties['os.version'])
connection.setRequestProperty('Authorization', 'Bearer ' + authToken)
connection.setRequestProperty('Accept', 'application/json')
// Check if connection was valid.
if (connection.responseCode == 200) {
// Map holding pledge data. The key is a string representation of the
// users ID and the value is an object holding information about the
// pledge.
Map<String, Pledge> pledges = new HashMap<String, Pledge>()
// Parse the response into an ambiguous json object.
def json = connection.inputStream.withCloseable { inStream -> new JsonSlurper().parse(inStream as InputStream) }
// Iterate all the pledge entries
for (pledgeInfo in json.data) {
// Create new pledge entry, and set pledge specific info.
def pledge = new Pledge()
pledge.id = pledgeInfo.relationships.patron.data.id
pledge.amountInCents = pledgeInfo.attributes.amount_cents
pledge.declined = pledgeInfo.attributes.declined_since
if (pledge.isValid()) {
pledges.put(pledge.id, pledge)
}
}
// Parse out the pledges display info from the JSON.
for (pledgeInfo in json.included) {
// Get pledge by user ID
def pledge = pledges.get(pledgeInfo.id)
// If the pledge exists, set the user data.
if (pledge != null) {
def info = pledgeInfo.attributes
pledge.name = info.full_name
pledge.vanityName = info.vanity
}
}
def pledgeNames = new ArrayList<>()
def pledgeLog = ''
List<Pledge> validPledges = new ArrayList<>()
for (entry in pledges) {
def currentPledge = entry.value
validPledges.add(currentPledge)
pledgeLog += "- ${currentPledge.getDisplayName()}\n"
pledgeNames.add(currentPledge.getDisplayName())
}
project.ext.patreon.pledges = validPledges
project.ext.patreon.pledgeNames = pledgeNames.join(', ')
project.ext.patreon.pledgeLog = pledgeLog
}
}
class Pledge {
// The ID for this user in the Patreon system.
def id
// The amount this user is currently paying in USD cents.
def amountInCents
// The date they declined. This will be null if they haven't declined.
def declined
// The full name of the user.
def name
// The vanity name of the user, like a display name.
def vanityName
/*
Checks if the user is valid, and is paying.
*/
def isValid() {
return declined == null && amountInCents > 0
}
/*
Gets the display name for the user. Defaults to full name if no vanity name is specified by the user.
*/
def getDisplayName() {
return vanityName != null ? vanityName : name
}
}
================================================
FILE: buildSrc/src/main/groovy/project_validation.gradle
================================================
import javax.imageio.ImageIO
import java.awt.image.BufferedImage
gradle.taskGraph.whenReady { graph ->
// Validate the logo file for the project.
// - logo.png must exist in the root project folder.
// - logo.png must be a 1:1 aspect ratio.
final File logoFile = project('common').file("src/main/resources/logo_${mod_id}.png")
if (!logoFile.exists()) {
throw new GradleException("A logo_${mod_id}.png file is required to build this mod.")
}
else {
try {
final BufferedImage logoImage = ImageIO.read(logoFile)
if (logoImage.getWidth() != logoImage.getHeight()) {
throw new GradleException('The logo image must be a 1:1 aspect ratio.')
}
}
catch (IOException e) {
throw new GradleException('Unable to process logo file.', e)
}
}
// Validate the license file for the project.
// - A file named LICENSE must exist in the root project folder.
if (!rootProject.file('LICENSE').exists()) {
throw new GradleException('LICENSE file does not exist.')
}
}
================================================
FILE: buildSrc/src/main/groovy/readme-update.gradle
================================================
task updateReadme {
var readme = rootProject.file('README.md')
if (!readme.exists()) {
throw new GradleException('The README.md file is missing!')
}
doLast {
rootProject.logger.lifecycle('Updating the README.md file...')
var text = readme.text
text = updateSection(text, 'name', buildName(rootProject))
text = updateSection(text, 'description', buildIntro(rootProject))
text = updateSection(text, 'maven', buildMavenInfo(rootProject))
text = updateSection(text, 'sponsor', buildSponsors(rootProject))
readme.text = text
}
}
static String buildName(Project project) {
var encodedPath = project.group.replaceAll('\\.', '%2F')
var projectPath = project.group.replaceAll('\\.', '/')
var modId = project.property('mod_id')
var mcVersion = project.property('minecraft_version')
var curseBadge = "[}?logo=curseforge&label=CurseForge&style=flat-square&labelColor=2D2D2D&color=555555)](${project.property('curse_page')})"
var modrinthBadge = "[}?logo=modrinth&label=Modrinth&style=flat-square&labelColor=2D2D2D&color=555555)](${project.property('modrinth_page')})"
var versionBadge = "[](https://maven.blamejared.com/${projectPath})"
return "# ${project.property('mod_name')} ${curseBadge} ${modrinthBadge} ${versionBadge}"
}
static String buildIntro(Project project) {
return "${project.property('mod_description')} The documentation for this mod can be found [here](${project.property('mod_docs')})."
}
static String buildMavenInfo(Project project) {
var group = project.property('group')
var modId = project.property('mod_id')
var mcVersion = project.property('minecraft_version')
var projectVersion = project.version
return """|## Maven Dependency
|
|If you are using [Gradle](https://gradle.org) to manage your dependencies, add the following into your `build.gradle` file. Make sure to replace the version with the correct one. All versions can be viewed [here](https://maven.blamejared.com/${group.replaceAll('\\.', '/')}).
|
|```gradle
|repositories {
| maven {
| url 'https://maven.blamejared.com'
| }
|}
|
|dependencies {
| // NeoForge
| implementation group: '${group}', name: '${modId}-neoforge-${mcVersion}', version: '${projectVersion}'
|
| // Forge
| implementation group: '${group}', name: '${modId}-forge-${mcVersion}', version: '${projectVersion}'
|
| // Fabric & Quilt
| modImplementation group: '${group}', name: '${modId}-fabric-${mcVersion}', version: '${projectVersion}'
|
| // Common / MultiLoader / Vanilla
| compileOnly group: '${group}', name: '${modId}-common-${mcVersion}', version: '${projectVersion}'
|}
|```""".stripMargin()
}
static String buildSponsors(Project project) {
var modName = project.property('mod_name')
return """|## Sponsors
|
|[](https://nodecraft.com/r/darkhax)
|${modName} is sponsored by Nodecraft. Use code **[DARKHAX](https://nodecraft.com/r/darkhax)** for 30% of your first month of service!""".stripMargin()
}
static String updateSection(String inputText, String region, String text) {
var startComment = commentOf("${region}-start")
var startPos = inputText.indexOf(startComment) + startComment.length()
var endComment = commentOf("${region}-end")
var endPos = inputText.indexOf(endComment)
return inputText.substring(0, startPos) + System.lineSeparator() + text + System.lineSeparator() + inputText.substring(endPos)
}
static String commentOf(String commentText) {
return "<!-- ${commentText} -->"
}
================================================
FILE: buildSrc/src/main/groovy/secret-loader.gradle
================================================
// Loads properties from a file containing environmental secrets.
import groovy.json.JsonSlurper
// Auto detects a secret file and injects it.
if (rootProject.hasProperty('secretFile')) {
project.logger.lifecycle('Automatically loading properties from the secretFile')
final def secretsFile = rootProject.file(rootProject.findProperty('secretFile'))
if (secretsFile.exists() && secretsFile.name.endsWith('.json')) {
loadProperties(secretsFile)
}
else {
project.logger.lifecycle("Properties could not be read from the secretFile because it does not exist. ${secretsFile}")
}
}
else {
project.logger.lifecycle('The secretFile property has not been set. Some API tokens will not be available.')
}
// Loads properties using a specified json file.
def loadProperties(propertyFile) {
if (propertyFile.exists()) {
propertyFile.withReader {
Map propMap = new JsonSlurper().parse it
for (entry in propMap) {
// Filter entries that use _comment in the key.
if (!entry.key.endsWith('_comment')) {
project.ext.set(entry.key, entry.value)
}
}
project.logger.lifecycle("Successfully loaded ${propMap.size()} environment secrets.")
propMap.clear()
}
} else {
project.logger.warn("Could not find property file! Expected: ${propertyFile}")
}
}
================================================
FILE: buildSrc/src/main/groovy/version-checker.gradle
================================================
// This plugin adds a task that can update the latest version on Jared's
// update checker API. This is a private service that requires an API key
// to use. For more information contact Jared https://x.com/jaredlll08
import groovy.json.JsonOutput
task updateVersionTracker {
if (!rootProject.hasProperty('versionTrackerAPI') || !rootProject.hasProperty('versionTrackerUsername')) {
rootProject.logger.warn('Skipping Version Checker update. Authentication is required!')
}
onlyIf {
rootProject.hasProperty('versionTrackerAPI') && rootProject.hasProperty('versionTrackerUsername')
}
doLast {
def username = rootProject.findProperty('versionTrackerUsername')
def apiKey = rootProject.findProperty('versionTrackerKey')
// Creates a Map that acts as the Json body of the API request.
def body = [
'author' : username,
'projectName' : project.ext.mod_id,
'gameVersion' : project.ext.minecraft_version,
'projectVersion': project.version,
'homepage' : project.ext.curse_page,
'uid' : apiKey
]
// Opens a connection to the version tracker API and writes the payload JSON.
def req = new URL(rootProject.findProperty('versionTrackerAPI')).openConnection()
req.setRequestMethod('POST')
req.setRequestProperty('Content-Type', 'application/json; charset=UTF-8')
req.setRequestProperty('User-Agent', "${project.ext.mod_name} Tracker Gradle")
req.setDoOutput(true)
req.getOutputStream().write(JsonOutput.toJson(body).getBytes("UTF-8"))
// For the request to be sent we need to read data from the stream.
project.logger.lifecycle("Version Check: Status ${req.getResponseCode()}")
project.logger.lifecycle("Version Check: Response ${req.getInputStream().getText()}")
}
}
================================================
FILE: common/build.gradle
================================================
plugins {
id 'multiloader-common'
id 'net.neoforged.moddev'
}
neoForge {
neoFormVersion = neo_form_version
parchment {
minecraftVersion = parchment_minecraft
mappingsVersion = parchment_version
}
}
dependencies {
compileOnly group: 'org.spongepowered', name: 'mixin', version: '0.8.5'
compileOnly group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.4.0'
annotationProcessor group: 'io.github.llamalad7', name: 'mixinextras-common', version: '0.4.0'
if (project.hasProperty('jei_version')) {
compileOnly("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}")
}
}
configurations {
commonJava {
canBeResolved = false
canBeConsumed = true
}
commonResources {
canBeResolved = false
canBeConsumed = true
}
}
artifacts {
commonJava sourceSets.main.java.sourceDirectories.singleFile
commonResources sourceSets.main.resources.sourceDirectories.singleFile
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/ModEntry.java
================================================
package net.darkhax.bookshelf.common.api;
public record ModEntry(String modId, String name, String description, String version) {
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/PhysicalSide.java
================================================
package net.darkhax.bookshelf.common.api;
/**
* Represents a physical location in the client/server network diagram.
*/
public enum PhysicalSide {
/**
* A physical client. This includes single player, and LAN worlds.
*/
CLIENT,
/**
* A physical server. This includes dedicated servers where client code and logic is not accessible.
*/
SERVER;
/**
* Checks if this is a physical client.
*
* @return Returns true when on a physical client.
*/
public boolean isClient() {
return this == CLIENT;
}
/**
* Checks if this is a physical server.
*
* @return Returns true when on a physical server.
*/
public boolean isServer() {
return this == SERVER;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/annotation/InternalUse.java
================================================
package net.darkhax.bookshelf.common.api.annotation;
/**
* A visual indicator for members that may be visible for technical reasons or convenience but are not intended for
* general use. For example, if a method you did not create is decorated with this annotation you should not invoke it.
*/
public @interface InternalUse {
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/annotation/OnlyFor.java
================================================
package net.darkhax.bookshelf.common.api.annotation;
import net.darkhax.bookshelf.common.api.PhysicalSide;
/**
* A visual indicator that a class, field, or method can only be accessed in certain environments. There is no special
* magic or ASM behind this annotation, it is only a visual indicator to help navigate the code.
*/
public @interface OnlyFor {
PhysicalSide value();
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/block/IBlockHooks.java
================================================
package net.darkhax.bookshelf.common.api.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathType;
import org.jetbrains.annotations.Nullable;
public interface IBlockHooks {
Direction[] LIGHTNING_REDIRECTION_FACES = new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.DOWN};
Direction[] NO_LIGHTNING_REDIRECTION_FACES = new Direction[]{};
/**
* Allows the block to determine its own pathfinding type.
*
* @param state The current state of the block.
* @param context Additional context from the world the block is in.
* @param pos The position of the block.
* @return The pathfinding type for the block. If null is returned the vanilla behavior for determining pathfinding
* will be used instead.
*/
@Nullable
default PathType getPathfindingType(BlockState state, BlockGetter context, BlockPos pos) {
return null;
}
/**
* Called when the block is directly struck by lightning.
*
* @param state The state of this block.
* @param level The level.
* @param pos The position of this block.
* @param lightning The lightning bolt that hit the block.
*/
default void onLightningStrike(BlockState state, Level level, BlockPos pos, LightningBolt lightning) {
}
/**
* Called when a neighbor is struck by lightning and the block is not insulated from the strike.
*
* @param state The state of this block.
* @param level The level.
* @param pos The position of this block.
* @param lightning The lightning bolt that hit the block.
* @param strikeOrigin The original strike position of the lightning bolt.
*/
default void onLightningStrikeIndirect(BlockState state, Level level, BlockPos pos, LightningBolt lightning, BlockPos strikeOrigin) {
}
/**
* Provides an array of directions lightning can travel and indirectly hit when this block is hit by lightning.
*
* @param state The state of this block.
* @param level The level.
* @param pos The position of this block.
* @return An array of directions that should be indirectly hit by the lightning.
*/
default Direction[] redirectLightningStrike(BlockState state, Level level, BlockPos pos) {
return NO_LIGHTNING_REDIRECTION_FACES;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/IEnumCommand.java
================================================
package net.darkhax.bookshelf.common.api.commands;
import com.mojang.brigadier.Command;
import net.minecraft.commands.CommandSourceStack;
/**
* Allows an enum to be used as a branching command path.
*/
public interface IEnumCommand extends Command<CommandSourceStack> {
/**
* Gets the name of the command. This must be unique for each enum value.
*
* @return The name of the command.
*/
String getCommandName();
/**
* Gets the required permission level to perform the command.
*
* @return The required permission level.
*/
default PermissionLevel requiredPermissionLevel() {
return PermissionLevel.PLAYER;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/PermissionLevel.java
================================================
package net.darkhax.bookshelf.common.api.commands;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import java.util.function.Predicate;
public enum PermissionLevel implements Predicate<CommandSourceStack> {
/**
* All players will generally meet the requirements for this permission level.
*/
PLAYER(Commands.LEVEL_ALL),
/**
* These players have slightly elevated permission levels. In vanilla, they do not gain access to any additional
* commands, but they are able to bypass spawn chunk protection.
*/
MODERATOR(Commands.LEVEL_MODERATORS),
/**
* These players can execute commands that modify the world and player data. They are also allowed to use and modify
* command blocks.
*/
GAMEMASTER(Commands.LEVEL_GAMEMASTERS),
/**
* These players can use commands related to player management. For example, they can ban, kick, op, and de-op.
*/
ADMIN(Commands.LEVEL_ADMINS),
/**
* This is the highest permission level available in vanilla Minecraft. Players with this permission level generally
* have no restrictions.
*/
OWNER(Commands.LEVEL_OWNERS);
final int level;
PermissionLevel(int level) {
this.level = level;
}
public int get() {
return this.level;
}
@Override
public boolean test(CommandSourceStack source) {
return source.hasPermission(this.level);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/ArgumentSerializer.java
================================================
package net.darkhax.bookshelf.common.api.commands.args;
import com.google.gson.JsonObject;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiFunction;
import java.util.function.Function;
public class ArgumentSerializer<T extends ArgumentType<?>, V> implements ArgumentTypeInfo<T, ArgumentSerializer.ArgTemplate<T, V>> {
private final MapCodec<V> codec;
private final StreamCodec<FriendlyByteBuf, V> stream;
private final BiFunction<CommandBuildContext, V, T> fromData;
private final Function<T, V> toData;
public ArgumentSerializer(MapCodec<V> codec, StreamCodec<FriendlyByteBuf, V> stream, BiFunction<CommandBuildContext, V, T> mapFunc, Function<T, V> toData) {
this.codec = codec;
this.stream = stream;
this.fromData = mapFunc;
this.toData = toData;
}
@Override
public void serializeToNetwork(ArgTemplate<T, V> template, @NotNull FriendlyByteBuf buf) {
this.stream.encode(buf, template.data);
}
@NotNull
@Override
public ArgTemplate<T, V> deserializeFromNetwork(@NotNull FriendlyByteBuf buf) {
return new ArgTemplate<>(this, this.stream.decode(buf));
}
@Override
public void serializeToJson(@NotNull ArgTemplate<T, V> template, @NotNull JsonObject json) {
json.add("value", this.codec.codec().encodeStart(JsonOps.INSTANCE, template.data).getOrThrow());
}
@NotNull
@Override
public ArgTemplate<T, V> unpack(@NotNull T t) {
return new ArgTemplate<>(this, this.toData.apply(t));
}
public static class ArgTemplate<T extends ArgumentType<?>, V> implements ArgumentTypeInfo.Template<T> {
private final ArgumentSerializer<T, V> type;
private final V data;
protected ArgTemplate(ArgumentSerializer<T, V> type, V data) {
this.type = type;
this.data = data;
}
@NotNull
@Override
public T instantiate(@NotNull CommandBuildContext ctx) {
return this.type.fromData.apply(ctx, this.data);
}
@NotNull
@Override
public ArgumentTypeInfo<T, ?> type() {
return this.type;
}
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/FontArgument.java
================================================
package net.darkhax.bookshelf.common.api.commands.args;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.darkhax.bookshelf.common.api.service.Services;
import net.darkhax.bookshelf.common.api.text.font.BuiltinFonts;
import net.darkhax.bookshelf.common.api.util.TextHelper;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.resources.ResourceLocation;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class FontArgument implements ArgumentType<ResourceLocation> {
public static final FontArgument ARGUMENT = new FontArgument();
public static final ArgumentTypeInfo<FontArgument, ?> SERIALIZER = SingletonArgumentInfo.of(() -> ARGUMENT);
private static final Set<String> EXAMPLES = Set.of(BuiltinFonts.DEFAULT.identifier().toString(), BuiltinFonts.ALT.identifier().toString(), BuiltinFonts.ILLAGER.identifier().toString());
public static ResourceLocation get(CommandContext<CommandSourceStack> context) {
return get("font", context);
}
public static ResourceLocation get(String argName, CommandContext<CommandSourceStack> context) {
return context.getArgument(argName, ResourceLocation.class);
}
public static RequiredArgumentBuilder<CommandSourceStack, ResourceLocation> argument() {
return argument("font");
}
public static RequiredArgumentBuilder<CommandSourceStack, ResourceLocation> argument(String argName) {
return Commands.argument(argName, ARGUMENT);
}
@Override
public ResourceLocation parse(StringReader reader) throws CommandSyntaxException {
return ResourceLocation.read(reader);
}
@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
if (Services.PLATFORM.isPhysicalClient()) {
return SharedSuggestionProvider.suggestResource(TextHelper.getRegisteredFonts(), builder);
}
return SharedSuggestionProvider.suggestResource(BuiltinFonts.FONT_IDS, builder);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/SingletonArgumentInfo.java
================================================
package net.darkhax.bookshelf.common.api.commands.args;
import com.google.gson.JsonObject;
import com.mojang.brigadier.arguments.ArgumentType;
import net.darkhax.bookshelf.common.api.function.CachedSupplier;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.network.FriendlyByteBuf;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* An argument info type that will always resolve to the same singleton instance. This is beneficial when the values are
* already known by the client in advance, or may even be only known by the client.
*
* @param <T> The argument type.
*/
public final class SingletonArgumentInfo<T extends ArgumentType<?>> implements ArgumentTypeInfo<T, SingletonArgumentInfo.Template<T>> {
/**
* Creates argument info for a given argument instance.
*
* @param argSupplier A supplier that resolves the singleton instance. This supplier should always return the same
* instance!
* @param <T> The argument type.
* @return The argument info for the singleton.
*/
public static <T extends ArgumentType<?>> SingletonArgumentInfo<T> of(Supplier<T> argSupplier) {
return new SingletonArgumentInfo<>(argSupplier);
}
private final CachedSupplier<Template<T>> templateSupplier;
private SingletonArgumentInfo(Supplier<T> singletonSupplier) {
this.templateSupplier = CachedSupplier.cache(() -> new Template<>(singletonSupplier, this));
}
@Override
public void serializeToNetwork(@NotNull Template<T> tTemplate, @NotNull FriendlyByteBuf friendlyByteBuf) {
// NO-OP
}
@NotNull
@Override
public Template<T> deserializeFromNetwork(@NotNull FriendlyByteBuf buffer) {
return this.templateSupplier.get();
}
@Override
public void serializeToJson(@NotNull Template<T> tTemplate, @NotNull JsonObject jsonObject) {
// NO-OP
}
@NotNull
@Override
public Template<T> unpack(@NotNull T template) {
return this.templateSupplier.get();
}
/**
* A template that holds a cached argument singleton.
*
* @param <T> The argument type.
*/
public static class Template<T extends ArgumentType<?>> implements ArgumentTypeInfo.Template<T> {
private final ArgumentTypeInfo<T, ?> info;
private final Supplier<T> singletonSupplier;
protected Template(Supplier<T> supplier, ArgumentTypeInfo<T, ?> info) {
this.singletonSupplier = supplier;
this.info = info;
}
@NotNull
@Override
public T instantiate(@NotNull CommandBuildContext ctx) {
return this.singletonSupplier.get();
}
@NotNull
@Override
public ArgumentTypeInfo<T, ?> type() {
return this.info;
}
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/TagArgument.java
================================================
package net.darkhax.bookshelf.common.api.commands.args;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.CompletableFuture;
public class TagArgument<T> implements ArgumentType<TagKey<T>> {
private static final MapCodec<ResourceKey<? extends Registry<?>>> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
ResourceLocation.CODEC.fieldOf("registry_name").forGetter(ResourceKey::location)
).apply(instance, ResourceKey::createRegistryKey));
private static final StreamCodec<FriendlyByteBuf, ResourceKey<? extends Registry<?>>> STREAM = StreamCodec.of(
(buf, key) -> buf.writeResourceLocation(key.location()),
buf -> ResourceKey.createRegistryKey(buf.readResourceLocation())
);
public static final ArgumentSerializer<TagArgument<?>, ResourceKey<? extends Registry<?>>> SERIALIZER = new ArgumentSerializer<>(CODEC, STREAM, TagArgument::makeRaw, t -> t.registryKey);
private static final Collection<String> EXAMPLES = Arrays.asList("minecraft:dirt", "minecraft:axolotl_food", "minecraft:enchantable/bow");
private final HolderLookup<T> registryLookup;
private final ResourceKey<? extends Registry<T>> registryKey;
@SuppressWarnings({"rawtypes", "unchecked"})
private static TagArgument<?> makeRaw(CommandBuildContext context, ResourceKey registryKey) {
return new TagArgument<>(context, registryKey);
}
private TagArgument(CommandBuildContext context, ResourceKey<? extends Registry<T>> registryKey) {
this.registryKey = registryKey;
this.registryLookup = context.lookupOrThrow(registryKey);
}
@Override
public TagKey<T> parse(StringReader reader) throws CommandSyntaxException {
final ResourceLocation tagId = ResourceLocation.read(reader);
return TagKey.create(this.registryKey, tagId);
}
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return SharedSuggestionProvider.suggestResource(this.registryLookup.listTagIds().map(TagKey::location), builder);
}
@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
public static <T> TagArgument<T> arg(CommandBuildContext context, ResourceKey<? extends Registry<T>> registry) {
return new TagArgument<>(context, registry);
}
@SuppressWarnings("unchecked")
public static <T> TagKey<T> get(String argName, CommandContext<CommandSourceStack> context, ResourceKey<? extends Registry<T>> registry) {
return (TagKey<T>) context.getArgument(argName, TagKey.class);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/BookshelfTags.java
================================================
package net.darkhax.bookshelf.common.api.data;
import net.darkhax.bookshelf.common.impl.Constants;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.damagesource.DamageType;
public class BookshelfTags {
public static TagKey<DamageType> FAKE_PLAYER_DAMAGE = TagKey.create(Registries.DAMAGE_TYPE, ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "fake_player"));
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/ISidedRecipeManager.java
================================================
package net.darkhax.bookshelf.common.api.data;
public interface ISidedRecipeManager {
void bookshelf$setLogicalClient();
void bookshelf$setLogicalServer();
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/EnumStreamCodec.java
================================================
package net.darkhax.bookshelf.common.api.data.codecs;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import org.jetbrains.annotations.NotNull;
public class EnumStreamCodec<T extends Enum<T>> implements StreamCodec<FriendlyByteBuf, T> {
private final Class<T> enumClass;
public EnumStreamCodec(Class<T> clazz) {
this.enumClass = clazz;
}
@NotNull
@Override
public T decode(FriendlyByteBuf buf) {
return buf.readEnum(enumClass);
}
@Override
public void encode(FriendlyByteBuf buf, @NotNull T toWrite) {
buf.writeEnum(toWrite);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/MapCodecHelper.java
================================================
package net.darkhax.bookshelf.common.api.data.codecs.map;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.random.SimpleWeightedRandomList;
import net.minecraft.util.random.WeightedEntry;
import java.lang.reflect.Array;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.IntFunction;
/**
* A CodecHelper wraps a Codec to provide a large amount of helpers and utilities to make working with the Codec easier
* and more flexible.
*
* @param <T> The type handled by the codec helper.
*/
public class MapCodecHelper<T> {
/**
* The root codec that powers all the helpers and utilities offered by the CodecHelper.
*/
private final Codec<T> elementCodec;
/**
* A function for creating an array of the codecs type. This allows us to create clean arrays for our codecs without
* relying on sketchy code.
*/
private final IntFunction<T[]> arrayBuilder;
@SafeVarargs
public MapCodecHelper(Codec<T> elementCodec, T... vargs) {
if (vargs.length > 0) {
throw new IllegalArgumentException("The arrayBuilder must be empty!");
}
this.elementCodec = elementCodec;
this.arrayBuilder = size -> (T[]) Array.newInstance(vargs.getClass().getComponentType(), size);
}
/**
* Gets a codec that can read and write single instances of the element.
*
* @return A Codec that can read and write single instances of the element.
*/
public Codec<T> get() {
return this.elementCodec;
}
/**
* A helper for defining a field of this type in a RecordCodecBuilder.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodecBuilder.
* @return A RecordCodecBuilder that represents a field.
*/
public <O> RecordCodecBuilder<O, T> get(String fieldName, Function<O, T> getter) {
return this.get().fieldOf(fieldName).forGetter(getter);
}
/**
* A helper for defining a field of this type in a RecordCodecBuilder. If the field is not present the fallback
* value will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodecBuilder.
* @return A RecordCodecBuilder that represents a field of the helpers type with a fallback value.
*/
public <O> RecordCodecBuilder<O, T> get(String fieldName, Function<O, T> getter, T fallback) {
return this.get().optionalFieldOf(fieldName, fallback).forGetter(getter);
}
/**
* Gets a codec that can read and write an array. For the sake of convenience single elements are treated as an
* array of one.
*
* @return A Codec that can read and write an array.
*/
public Codec<T[]> getArray() {
return MapCodecs.flexibleArray(this.get(), this.arrayBuilder);
}
/**
* A helper for defining a field for an array of this type in a RecordCodecBuilder. For the sake of convenience
* single elements are treated as an array of one.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for an array.
*/
public <O> RecordCodecBuilder<O, T[]> getArray(String fieldName, Function<O, T[]> getter) {
return this.getArray().fieldOf(fieldName).forGetter(getter);
}
/**
* A helper for defining a field for an array of this type in a RecordCodecBuilder. For the sake of convenience
* single elements are treated as an array of one. If the field is not present the fallback will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for an array.
*/
public <O> RecordCodecBuilder<O, T[]> getArray(String fieldName, Function<O, T[]> getter, T... fallback) {
return this.getArray().optionalFieldOf(fieldName, fallback).forGetter(getter);
}
/**
* Gets a codec that can read and write a list. For the sake of convenience single elements are treated as a list of
* one.
*
* @return A Codec that can read and write a list.
*/
public Codec<List<T>> getList() {
return MapCodecs.flexibleList(this.get());
}
/**
* A helper for defining a field for a list of this type in a RecordCodecBuilder. For the sake of convenience single
* elements are treated as a list of one.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a list.
*/
public <O> RecordCodecBuilder<O, List<T>> getList(String fieldName, Function<O, List<T>> getter) {
return this.getList().fieldOf(fieldName).forGetter(getter);
}
/**
* A helper for defining a field for a list of this type in a RecordCodecBuilder. For the sake of convenience single
* elements are treated as a list of one. If the field is not present the fallback will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a list.
*/
public <O> RecordCodecBuilder<O, List<T>> getList(String fieldName, Function<O, List<T>> getter, List<T> fallback) {
return this.getList().optionalFieldOf(fieldName, fallback).forGetter(getter);
}
/**
* A helper for defining a field for a list of this type in a RecordCodecBuilder. For the sake of convenience single
* elements are treated as a list of one. If the field is not present the fallback will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a list.
*/
public <O> RecordCodecBuilder<O, List<T>> getList(String fieldName, Function<O, List<T>> getter, T... fallback) {
return this.getList().optionalFieldOf(fieldName, List.of(fallback)).forGetter(getter);
}
/**
* Gets a codec that can read and write a set. For the sake of convenience single elements are treated as a list of
* one.
*
* @return A Codec that can read and write a set.
*/
public Codec<Set<T>> getSet() {
return MapCodecs.flexibleSet(this.get());
}
/**
* A helper for defining a field for a set of this type in a RecordCodecBuilder. For the sake of convenience single
* elements are treated as a set of one.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a set.
*/
public <O> RecordCodecBuilder<O, Set<T>> getSet(String fieldName, Function<O, Set<T>> getter) {
return this.getSet().fieldOf(fieldName).forGetter(getter);
}
/**
* A helper for defining a field for a set of this type in a RecordCodecBuilder. For the sake of convenience single
* elements are treated as a set of one. If the field is not present the fallback will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a set.
*/
public <O> RecordCodecBuilder<O, Set<T>> getSet(String fieldName, Function<O, Set<T>> getter, Set<T> fallback) {
return this.getSet().optionalFieldOf(fieldName, fallback).forGetter(getter);
}
/**
* A helper for defining a field for a set of this type in a RecordCodecBuilder. For the sake of convenience single
* elements are treated as a set of one. If the field is not present the fallback will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a set.
*/
public <O> RecordCodecBuilder<O, Set<T>> getSet(String fieldName, Function<O, Set<T>> getter, T... fallback) {
return this.getSet().optionalFieldOf(fieldName, Set.of(fallback)).forGetter(getter);
}
/**
* Gets a codec that can read and write an optional value.
*
* @param fieldName The name of the field to read the value from.
* @return A Codec that can read and write an optional value.
*/
public MapCodec<Optional<T>> getOptional(String fieldName) {
return this.get().optionalFieldOf(fieldName);
}
/**
* A helper for defining a field for an optional value of this type in a RecordCodecBuilder.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for an optional value.
*/
public <O> RecordCodecBuilder<O, Optional<T>> getOptional(String fieldName, Function<O, Optional<T>> getter) {
return this.get().optionalFieldOf(fieldName).forGetter(getter);
}
/**
* A helper for defining a field for an optional value of this type in a RecordCodecBuilder. If the field is not
* present the fallback will be used.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param fallback The fallback value to use when the field is not present.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for an optional value.
*/
public <O> RecordCodecBuilder<O, Optional<T>> getOptional(String fieldName, Function<O, Optional<T>> getter, Optional<T> fallback) {
return MapCodecs.optional(this.get(), fieldName, fallback, true).forGetter(getter);
}
/**
* Gets a codec that can read and write nullable values.
*
* @param fieldName The name of the field to read the value from.
* @return A Codec that can read and write nullable values.
*/
public MapCodec<T> getNullable(String fieldName) {
return MapCodecs.nullable(this.get(), fieldName);
}
/**
* A helper for defining a field for a nullable value of this type in a RecordCodecBuilder.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodedBuilder.
* @return A RecordCodecBuilder that represents a field for a nullable value.
*/
public <O> RecordCodecBuilder<O, T> getNullable(String fieldName, Function<O, T> getter) {
return this.getNullable(fieldName).forGetter(getter);
}
/**
* Gets a codec that can read and write a weighted entry.
*
* @return A Codec that can read and write a weighted entry.
*/
public Codec<WeightedEntry.Wrapper<T>> getWeighted() {
return WeightedEntry.Wrapper.codec(this.get());
}
/**
* A helper for defining a field for a weighted entry of this type in a RecordCodecBuilder.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodecBuilder.
* @return A RecordCodecBuilder that represents a field for a weighted entry.
*/
public <O> RecordCodecBuilder<O, WeightedEntry.Wrapper<T>> getWeighted(String fieldName, Function<O, WeightedEntry.Wrapper<T>> getter) {
return WeightedEntry.Wrapper.codec(this.get()).fieldOf(fieldName).forGetter(getter);
}
/**
* Gets a codec that can read and write a weighted list.
*
* @return A Codec that can read and write a weighted list.
*/
public Codec<SimpleWeightedRandomList<T>> getWeightedList() {
return SimpleWeightedRandomList.wrappedCodec(this.get());
}
/**
* A helper for defining a field for a weighted list of this type in a RecordCodecBuilder.
*
* @param fieldName The name of the field to read the value from.
* @param getter A getter that will read the value from an object of the RecordCodecBuilders type.
* @param <O> The type of the RecordCodecBuilder.
* @return A RecordCodecBuilder that represents a field for a weighted list.
*/
public <O> RecordCodecBuilder<O, SimpleWeightedRandomList<T>> getWeightedList(String fieldName, Function<O, SimpleWeightedRandomList<T>> getter) {
return this.getWeightedList().fieldOf(fieldName).forGetter(getter);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/MapCodecs.java
================================================
package net.darkhax.bookshelf.common.api.data.codecs.map;
import com.mojang.datafixers.util.Either;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import net.darkhax.bookshelf.common.api.data.conditions.ILoadCondition;
import net.darkhax.bookshelf.common.api.data.conditions.LoadConditions;
import net.darkhax.bookshelf.common.api.util.FunctionHelper;
import net.darkhax.bookshelf.common.api.util.TextHelper;
import net.darkhax.bookshelf.common.impl.Constants;
import net.minecraft.Optionull;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.advancements.critereon.EntitySubPredicate;
import net.minecraft.advancements.critereon.ItemSubPredicate;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.particles.ParticleType;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.chat.numbers.NumberFormatType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.StatType;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.valueproviders.FloatProviderType;
import net.minecraft.util.valueproviders.IntProviderType;
import net.minecraft.world.Difficulty;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.sensing.SensorType;
import net.minecraft.world.entity.ai.village.poi.PoiType;
import net.minecraft.world.entity.animal.CatVariant;
import net.minecraft.world.entity.animal.FrogVariant;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerType;
import net.minecraft.world.entity.schedule.Activity;
import net.minecraft.world.entity.schedule.Schedule;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ArmorMaterial;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Instrument;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.item.enchantment.LevelBasedValue;
import net.minecraft.world.item.enchantment.effects.EnchantmentEntityEffect;
import net.minecraft.world.item.enchantment.effects.EnchantmentLocationBasedEffect;
import net.minecraft.world.item.enchantment.effects.EnchantmentValueEffect;
import net.minecraft.world.item.enchantment.providers.EnchantmentProvider;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.entity.DecoratedPotPattern;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.PositionSourceType;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.SurfaceRules;
import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType;
import net.minecraft.world.level.levelgen.carver.WorldCarver;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.featuresize.FeatureSizeType;
import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType;
import net.minecraft.world.level.levelgen.feature.rootplacers.RootPlacerType;
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProviderType;
import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecoratorType;
import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType;
import net.minecraft.world.level.levelgen.heightproviders.HeightProviderType;
import net.minecraft.world.level.levelgen.placement.PlacementModifierType;
import net.minecraft.world.level.levelgen.structure.StructureType;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType;
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacementType;
import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElementType;
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasBinding;
import net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestType;
import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTestType;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
import net.minecraft.world.level.levelgen.structure.templatesystem.rule.blockentity.RuleBlockEntityModifierType;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.saveddata.maps.MapDecorationType;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryType;
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType;
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType;
import net.minecraft.world.level.storage.loot.providers.nbt.LootNbtProviderType;
import net.minecraft.world.level.storage.loot.providers.number.LootNumberProviderType;
import net.minecraft.world.level.storage.loot.providers.score.LootScoreProviderType;
import org.joml.Vector3f;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
@SuppressWarnings("unused")
public class MapCodecs {
// JAVA TYPES
public static final MapCodecHelper<Boolean> BOOLEAN = new MapCodecHelper<>(Codec.BOOL);
public static final MapCodecHelper<Byte> BYTE = new MapCodecHelper<>(Codec.BYTE);
public static final MapCodecHelper<Short> SHORT = new MapCodecHelper<>(Codec.SHORT);
public static final MapCodecHelper<Integer> INT = new MapCodecHelper<>(Codec.INT);
public static final MapCodecHelper<Float> FLOAT = new MapCodecHelper<>(Codec.FLOAT);
public static final MapCodecHelper<Long> LONG = new MapCodecHelper<>(Codec.LONG);
public static final MapCodecHelper<Double> DOUBLE = new MapCodecHelper<>(Codec.DOUBLE);
public static final MapCodecHelper<String> STRING = new MapCodecHelper<>(Codec.STRING);
public static final MapCodecHelper<UUID> UUID = new MapCodecHelper<>(UUIDUtil.CODEC);
// REGISTRIES
public static final MapCodecHelper<Holder<GameEvent>> GAME_EVENT = RegistryMapCodecHelper.create(BuiltInRegistries.GAME_EVENT);
public static final MapCodecHelper<Holder<SoundEvent>> SOUND_EVENT = RegistryMapCodecHelper.create(BuiltInRegistries.SOUND_EVENT);
public static final MapCodecHelper<Holder<Fluid>> FLUID = RegistryMapCodecHelper.create(BuiltInRegistries.FLUID);
public static final MapCodecHelper<Holder<MobEffect>> MOB_EFFECT = RegistryMapCodecHelper.create(BuiltInRegistries.MOB_EFFECT);
public static final MapCodecHelper<Holder<Block>> BLOCK = RegistryMapCodecHelper.create(BuiltInRegistries.BLOCK);
public static final MapCodecHelper<Holder<EntityType<?>>> ENTITY_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENTITY_TYPE);
public static final MapCodecHelper<Holder<Item>> ITEM = RegistryMapCodecHelper.create(BuiltInRegistries.ITEM);
public static final MapCodecHelper<Holder<Potion>> POTION = RegistryMapCodecHelper.create(BuiltInRegistries.POTION);
public static final MapCodecHelper<Holder<ParticleType<?>>> PARTICLE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.PARTICLE_TYPE);
public static final MapCodecHelper<Holder<BlockEntityType<?>>> BLOCK_ENTITY_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.BLOCK_ENTITY_TYPE);
public static final MapCodecHelper<Holder<ResourceLocation>> CUSTOM_STAT = RegistryMapCodecHelper.create(BuiltInRegistries.CUSTOM_STAT);
public static final MapCodecHelper<Holder<ChunkStatus>> CHUNK_STATUS = RegistryMapCodecHelper.create(BuiltInRegistries.CHUNK_STATUS);
public static final MapCodecHelper<Holder<RuleTestType<?>>> RULE_TEST = RegistryMapCodecHelper.create(BuiltInRegistries.RULE_TEST);
public static final MapCodecHelper<Holder<RuleBlockEntityModifierType<?>>> RULE_BLOCK_ENTITY_MODIFIER = RegistryMapCodecHelper.create(BuiltInRegistries.RULE_BLOCK_ENTITY_MODIFIER);
public static final MapCodecHelper<Holder<PosRuleTestType<?>>> POS_RULE_TEST = RegistryMapCodecHelper.create(BuiltInRegistries.POS_RULE_TEST);
public static final MapCodecHelper<Holder<MenuType<?>>> MENU = RegistryMapCodecHelper.create(BuiltInRegistries.MENU);
public static final MapCodecHelper<Holder<RecipeType<?>>> RECIPE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.RECIPE_TYPE);
public static final MapCodecHelper<Holder<RecipeSerializer<?>>> RECIPE_SERIALIZER = RegistryMapCodecHelper.create(BuiltInRegistries.RECIPE_SERIALIZER);
public static final MapCodecHelper<Holder<Attribute>> ATTRIBUTE = RegistryMapCodecHelper.create(BuiltInRegistries.ATTRIBUTE);
public static final MapCodecHelper<Holder<PositionSourceType<?>>> POSITION_SOURCE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.POSITION_SOURCE_TYPE);
public static final MapCodecHelper<Holder<ArgumentTypeInfo<?, ?>>> COMMAND_ARGUMENT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.COMMAND_ARGUMENT_TYPE);
public static final MapCodecHelper<Holder<StatType<?>>> STAT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.STAT_TYPE);
public static final MapCodecHelper<Holder<VillagerType>> VILLAGER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.VILLAGER_TYPE);
public static final MapCodecHelper<Holder<VillagerProfession>> VILLAGER_PROFESSION = RegistryMapCodecHelper.create(BuiltInRegistries.VILLAGER_PROFESSION);
public static final MapCodecHelper<Holder<PoiType>> POINT_OF_INTEREST_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.POINT_OF_INTEREST_TYPE);
public static final MapCodecHelper<Holder<MemoryModuleType<?>>> MEMORY_MODULE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.MEMORY_MODULE_TYPE);
public static final MapCodecHelper<Holder<SensorType<?>>> SENSOR_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.SENSOR_TYPE);
public static final MapCodecHelper<Holder<Schedule>> SCHEDULE = RegistryMapCodecHelper.create(BuiltInRegistries.SCHEDULE);
public static final MapCodecHelper<Holder<Activity>> ACTIVITY = RegistryMapCodecHelper.create(BuiltInRegistries.ACTIVITY);
public static final MapCodecHelper<Holder<LootPoolEntryType>> LOOT_POOL_ENTRY_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.LOOT_POOL_ENTRY_TYPE);
public static final MapCodecHelper<Holder<LootItemFunctionType<?>>> LOOT_FUNCTION_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.LOOT_FUNCTION_TYPE);
public static final MapCodecHelper<Holder<LootItemConditionType>> LOOT_CONDITION_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.LOOT_CONDITION_TYPE);
public static final MapCodecHelper<Holder<LootNumberProviderType>> LOOT_NUMBER_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.LOOT_NUMBER_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<LootNbtProviderType>> LOOT_NBT_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.LOOT_NBT_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<LootScoreProviderType>> LOOT_SCORE_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.LOOT_SCORE_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<FloatProviderType<?>>> FLOAT_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.FLOAT_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<IntProviderType<?>>> INT_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.INT_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<HeightProviderType<?>>> HEIGHT_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.HEIGHT_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<BlockPredicateType<?>>> BLOCK_PREDICATE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.BLOCK_PREDICATE_TYPE);
public static final MapCodecHelper<Holder<WorldCarver<?>>> CARVER = RegistryMapCodecHelper.create(BuiltInRegistries.CARVER);
public static final MapCodecHelper<Holder<Feature<?>>> FEATURE = RegistryMapCodecHelper.create(BuiltInRegistries.FEATURE);
public static final MapCodecHelper<Holder<StructurePlacementType<?>>> STRUCTURE_PLACEMENT = RegistryMapCodecHelper.create(BuiltInRegistries.STRUCTURE_PLACEMENT);
public static final MapCodecHelper<Holder<StructurePieceType>> STRUCTURE_PIECE = RegistryMapCodecHelper.create(BuiltInRegistries.STRUCTURE_PIECE);
public static final MapCodecHelper<Holder<StructureType<?>>> STRUCTURE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.STRUCTURE_TYPE);
public static final MapCodecHelper<Holder<PlacementModifierType<?>>> PLACEMENT_MODIFIER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.PLACEMENT_MODIFIER_TYPE);
public static final MapCodecHelper<Holder<BlockStateProviderType<?>>> BLOCKSTATE_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.BLOCKSTATE_PROVIDER_TYPE);
public static final MapCodecHelper<Holder<FoliagePlacerType<?>>> FOLIAGE_PLACER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.FOLIAGE_PLACER_TYPE);
public static final MapCodecHelper<Holder<TrunkPlacerType<?>>> TRUNK_PLACER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.TRUNK_PLACER_TYPE);
public static final MapCodecHelper<Holder<RootPlacerType<?>>> ROOT_PLACER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ROOT_PLACER_TYPE);
public static final MapCodecHelper<Holder<TreeDecoratorType<?>>> TREE_DECORATOR_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.TREE_DECORATOR_TYPE);
public static final MapCodecHelper<Holder<FeatureSizeType<?>>> FEATURE_SIZE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.FEATURE_SIZE_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends BiomeSource>>> BIOME_SOURCE = RegistryMapCodecHelper.create(BuiltInRegistries.BIOME_SOURCE);
public static final MapCodecHelper<Holder<MapCodec<? extends ChunkGenerator>>> CHUNK_GENERATOR = RegistryMapCodecHelper.create(BuiltInRegistries.CHUNK_GENERATOR);
public static final MapCodecHelper<Holder<MapCodec<? extends SurfaceRules.ConditionSource>>> MATERIAL_CONDITION = RegistryMapCodecHelper.create(BuiltInRegistries.MATERIAL_CONDITION);
public static final MapCodecHelper<Holder<MapCodec<? extends SurfaceRules.RuleSource>>> MATERIAL_RULE = RegistryMapCodecHelper.create(BuiltInRegistries.MATERIAL_RULE);
public static final MapCodecHelper<Holder<MapCodec<? extends DensityFunction>>> DENSITY_FUNCTION_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.DENSITY_FUNCTION_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends Block>>> BLOCK_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.BLOCK_TYPE);
public static final MapCodecHelper<Holder<StructureProcessorType<?>>> STRUCTURE_PROCESSOR = RegistryMapCodecHelper.create(BuiltInRegistries.STRUCTURE_PROCESSOR);
public static final MapCodecHelper<Holder<StructurePoolElementType<?>>> STRUCTURE_POOL_ELEMENT = RegistryMapCodecHelper.create(BuiltInRegistries.STRUCTURE_POOL_ELEMENT);
public static final MapCodecHelper<Holder<MapCodec<? extends PoolAliasBinding>>> POOL_ALIAS_BINDING_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.POOL_ALIAS_BINDING_TYPE);
public static final MapCodecHelper<Holder<CatVariant>> CAT_VARIANT = RegistryMapCodecHelper.create(BuiltInRegistries.CAT_VARIANT);
public static final MapCodecHelper<Holder<FrogVariant>> FROG_VARIANT = RegistryMapCodecHelper.create(BuiltInRegistries.FROG_VARIANT);
public static final MapCodecHelper<Holder<Instrument>> INSTRUMENT = RegistryMapCodecHelper.create(BuiltInRegistries.INSTRUMENT);
public static final MapCodecHelper<Holder<DecoratedPotPattern>> DECORATED_POT_PATTERN = RegistryMapCodecHelper.create(BuiltInRegistries.DECORATED_POT_PATTERN);
public static final MapCodecHelper<Holder<CreativeModeTab>> CREATIVE_MODE_TAB = RegistryMapCodecHelper.create(BuiltInRegistries.CREATIVE_MODE_TAB);
public static final MapCodecHelper<Holder<CriterionTrigger<?>>> TRIGGER_TYPES = RegistryMapCodecHelper.create(BuiltInRegistries.TRIGGER_TYPES);
public static final MapCodecHelper<Holder<NumberFormatType<?>>> NUMBER_FORMAT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.NUMBER_FORMAT_TYPE);
public static final MapCodecHelper<Holder<ArmorMaterial>> ARMOR_MATERIAL = RegistryMapCodecHelper.create(BuiltInRegistries.ARMOR_MATERIAL);
public static final MapCodecHelper<Holder<DataComponentType<?>>> DATA_COMPONENT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.DATA_COMPONENT_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends EntitySubPredicate>>> ENTITY_SUB_PREDICATE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE);
public static final MapCodecHelper<Holder<ItemSubPredicate.Type<?>>> ITEM_SUB_PREDICATE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ITEM_SUB_PREDICATE_TYPE);
public static final MapCodecHelper<Holder<MapDecorationType>> MAP_DECORATION_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.MAP_DECORATION_TYPE);
public static final MapCodecHelper<Holder<DataComponentType<?>>> ENCHANTMENT_EFFECT_COMPONENT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENCHANTMENT_EFFECT_COMPONENT_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends LevelBasedValue>>> ENCHANTMENT_LEVEL_BASED_VALUE_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENCHANTMENT_LEVEL_BASED_VALUE_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends EnchantmentEntityEffect>>> ENCHANTMENT_ENTITY_EFFECT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENCHANTMENT_ENTITY_EFFECT_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends EnchantmentLocationBasedEffect>>> ENCHANTMENT_LOCATION_BASED_EFFECT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENCHANTMENT_LOCATION_BASED_EFFECT_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends EnchantmentValueEffect>>> ENCHANTMENT_VALUE_EFFECT_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENCHANTMENT_VALUE_EFFECT_TYPE);
public static final MapCodecHelper<Holder<MapCodec<? extends EnchantmentProvider>>> ENCHANTMENT_PROVIDER_TYPE = RegistryMapCodecHelper.create(BuiltInRegistries.ENCHANTMENT_PROVIDER_TYPE);
// ENUMS
public static final MapCodecHelper<Rarity> ITEM_RARITY = new MapCodecHelper<>(enumerable(Rarity.class));
public static final MapCodecHelper<AttributeModifier.Operation> ATTRIBUTE_OPERATION = new MapCodecHelper<>(AttributeModifier.Operation.CODEC);
public static final MapCodecHelper<Direction> DIRECTION = new MapCodecHelper<>(enumerable(Direction.class));
public static final MapCodecHelper<Direction.Axis> AXIS = new MapCodecHelper<>(enumerable(Direction.Axis.class));
public static final MapCodecHelper<Direction.Plane> PLANE = new MapCodecHelper<>(enumerable(Direction.Plane.class));
public static final MapCodecHelper<MobCategory> MOB_CATEGORY = new MapCodecHelper<>(enumerable(MobCategory.class));
public static final MapCodecHelper<DyeColor> DYE_COLOR = new MapCodecHelper<>(enumerable(DyeColor.class));
public static final MapCodecHelper<SoundSource> SOUND_SOURCE = new MapCodecHelper<>(enumerable(SoundSource.class));
public static final MapCodecHelper<Difficulty> DIFFICULTY = new MapCodecHelper<>(enumerable(Difficulty.class));
public static final MapCodecHelper<EquipmentSlot> EQUIPMENT_SLOT = new MapCodecHelper<>(enumerable(EquipmentSlot.class));
public static final MapCodecHelper<Mirror> MIRROR = new MapCodecHelper<>(enumerable(Mirror.class));
public static final MapCodecHelper<Rotation> ROTATION = new MapCodecHelper<>(enumerable(Rotation.class));
// MINECRAFT TYPES
public static final MapCodecHelper<ResourceLocation> RESOURCE_LOCATION = new MapCodecHelper<>(ResourceLocation.CODEC);
public static final MapCodecHelper<CompoundTag> COMPOUND_TAG = new MapCodecHelper<>(CompoundTag.CODEC);
public static final MapCodecHelper<ItemStack> ITEM_STACK = new MapCodecHelper<>(ItemStack.CODEC);
public static final MapCodecHelper<ItemStack> ITEM_STACK_STRICT = new MapCodecHelper<>(ItemStack.STRICT_CODEC);
public static final MapCodecHelper<Component> TEXT = new MapCodecHelper<>(ComponentSerialization.CODEC);
public static final MapCodecHelper<BlockPos> BLOCK_POS = new MapCodecHelper<>(BlockPos.CODEC);
public static final MapCodecHelper<Ingredient> INGREDIENT = new MapCodecHelper<>(Ingredient.CODEC);
public static final MapCodecHelper<Ingredient> INGREDIENT_NONEMPTY = new MapCodecHelper<>(Ingredient.CODEC_NONEMPTY);
public static final MapCodec<BlockState> BLOCK_STATE_MAP_CODEC = Codec.mapPair(BLOCK.get().fieldOf("block"), Codec.unboundedMap(Codec.STRING, Codec.STRING).optionalFieldOf("properties")).flatXmap(MapCodecs::decodeBlockState, MapCodecs::encodeBlockState);
public static final MapCodecHelper<BlockState> BLOCK_STATE = new MapCodecHelper<>(BLOCK_STATE_MAP_CODEC.codec());
public static final MapCodecHelper<AttributeModifier> ATTRIBUTE_MODIFIER = new MapCodecHelper<>(AttributeModifier.CODEC);
public static final MapCodecHelper<MobEffectInstance> EFFECT_INSTANCE = new MapCodecHelper<>(MobEffectInstance.CODEC);
public static final MapCodecHelper<Vector3f> VECTOR_3F = new MapCodecHelper<>(ExtraCodecs.VECTOR3F);
// Bookshelf Types
public static final MapCodecHelper<ILoadCondition> LOAD_CONDITION = LoadConditions.CODEC_HELPER;
/**
* Creates a Codec that can flexibly read individual values as a list in addition to traditional lists.
*
* @param codec The codec for reading an individual value.
* @param <T> The type of value handled by the codec.
* @return A Codec that can flexibly read individual values as a list in addition to traditional lists.
*/
public static <T> Codec<List<T>> flexibleList(Codec<T> codec) {
return Codec.either(codec.listOf(), codec).xmap(either -> either.map(Function.identity(), List::of), list -> list.size() == 1 ? Either.right(list.getFirst()) : Either.left(list));
}
/**
* Creates a Codec that can flexibly read both individual values and arrays of values as a set.
*
* @param codec The Codec for reading an individual value.
* @param <T> The type of value handled by the codec.
* @return A Codec that can flexibly read both individual values and arrays of values as a set.
*/
public static <T> Codec<Set<T>> flexibleSet(Codec<T> codec) {
return flexibleList(codec).xmap(LinkedHashSet::new, ArrayList::new);
}
/**
* Creates a Codec that can flexibly read both individual values and arrays of values as an array.
*
* @param codec The Codec for reading an individual value.
* @param arrayBuilder A function that creates new arrays of the required type. The function is given the size of
* the list.
* @param <T> The type of value handled by the codec.
* @return A Codec that can flexibly read both individual values and arrays of values as an array.
*/
public static <T> Codec<T[]> flexibleArray(Codec<T> codec, IntFunction<T[]> arrayBuilder) {
return flexibleList(codec).xmap(list -> list.toArray(arrayBuilder.apply(list.size())), List::of);
}
/**
* Creates a Codec that will use a fallback value if no other value is specified. This is different from
* {@link Codec#optionalFieldOf(String, Object)} in that the fallback value is provided by a supplier.
*
* @param codec The base Codec to use.
* @param name The name of the field to read from.
* @param fallbackSupplier A supplier that produces the default value. You should probably memoize this.
* @param <T> The type of value handled by the codec.
* @return A Codec that will use a fallback value if the field is not specified.
*/
public static <T> MapCodec<T> fallback(Codec<T> codec, String name, Supplier<T> fallbackSupplier) {
return fallback(codec, name, fallbackSupplier, true);
}
/**
* Creates a Codec that handles optional values. This is different from
* {@link Codec#optionalFieldOf(String, Object)} in that it keeps the type as an Optional.
*
* @param codec The base Codec to use.
* @param name The name of the field to read from.
* @param fallback The fallback optional value.
* @param writesDefault Should the default value be written or left blank?
* @param <T> The type of the optional value handled by the coded.
* @return A Codec that handles optional values.
*/
public static <T> MapCodec<Optional<T>> optional(Codec<T> codec, String name, Optional<T> fallback, boolean writesDefault) {
return Codec.optionalField(name, codec, false).xmap(o -> o.isPresent() ? o : fallback, a -> a.isEmpty() || (Objects.equals(a.get(), fallback.orElse(null)) && !writesDefault) ? Optional.empty() : a);
}
/**
* Creates a Codec that can handle nullable values.
*
* @param codec The base Codec to use.
* @param fieldName The name of the field to read from.
* @param <T> The type of value handled by the codec.
* @return A Codec that handles nullable values.
*/
public static <T> MapCodec<T> nullable(Codec<T> codec, String fieldName) {
return Codec.optionalField(fieldName, codec, false).xmap(optional -> optional.orElse(null), Optional::ofNullable);
}
/**
* Creates a Codec that will use a fallback value if no other value is specified. This is different from
* {@link Codec#optionalFieldOf(String, Object)} in that the fallback value is provided by a supplier. It also
* allows you to control if the default value should be written when or left blank.
*
* @param codec The base Codec to use.
* @param name The name of the field to read from.
* @param fallbackSupplier A supplier that produces the default value. You should probably memoize this.
* @param writesDefault Should the default value be written or left blank?
* @param <T> The type of value handled by the codec.
* @return A Codec that will use a fallback value if the field is not specified.
*/
public static <T> MapCodec<T> fallback(Codec<T> codec, String name, Supplier<T> fallbackSupplier, boolean writesDefault) {
return Codec.optionalField(name, codec, false).xmap(value -> value.orElse(fallbackSupplier.get()), value -> {
final T fallback = fallbackSupplier.get();
return Objects.equals(value, fallback) && !writesDefault ? Optional.empty() : Optional.of(value);
});
}
private static <T extends Enum<T>> Map<String, T> getEnumsByName(Class<T> enumClass) {
if (!enumClass.isEnum()) {
throw new IllegalStateException("Class " + enumClass.getCanonicalName() + " is not an enum!");
}
final Map<String, T> valueMap = new HashMap<>();
for (T value : enumClass.getEnumConstants()) {
final String name = value.name();
if (valueMap.containsKey(name)) {
Constants.LOG.error("Duplicate name '{}' found in enum '{}'. Another mod is doing something very wrong. old='{}' new='{}'", name, enumClass.getName(), valueMap.get(name), value);
}
valueMap.put(name, value);
}
return valueMap;
}
/**
* Creates a Codec that handles enum values by using their enum constant names.
* <br>
* If the codec can not read an enum value from the provided name it will try again using an all uppercase version
* of the input. This allows users to write values in all lowercase which may feel more natural for some users and
* adds extra flexibility.
* <br>
* If the codec can not read any enum value from the provided name it will create an error. The error message will
* try to help the user by recommending a nearby match and including all possible values.
*
* @param enumClass The class of the enum to get values for.
* @param <T> The type of the enum.
* @return A codec that can read and write enum values using their enum constant name.
*/
public static <T extends Enum<T>> Codec<T> enumerable(Class<T> enumClass) {
final Map<String, T> enumValues = getEnumsByName(enumClass);
final Function<String, T> fromString = name -> {
T value = enumValues.get(name);
if (value == null) {
value = enumValues.get(name.toUpperCase(Locale.ROOT));
}
return value;
};
final UnaryOperator<String> errorMessage = name -> {
final StringJoiner message = new StringJoiner(" ");
message.add("Unable to find " + enumClass.getSimpleName() + " entry \"" + name + "\".");
final Set<String> similarMatches = TextHelper.getPossibleMatches(name, enumValues.keySet(), 2);
if (!similarMatches.isEmpty()) {
message.add("Did you mean \"" + similarMatches.stream().findFirst().get() + "\"?");
}
message.add("Available Options are " + TextHelper.formatCollection(enumValues.keySet()));
return message.toString();
};
return Codec.STRING.flatXmap(string -> Optionull.mapOrElse(fromString.apply(string), DataResult::success, () -> DataResult.error(() -> errorMessage.apply(string))), object -> DataResult.success(object.name()));
}
// INTERNAL HELPERS
@SuppressWarnings({"rawtypes", "unchecked"})
private static DataResult<BlockState> decodeBlockState(Pair<Holder<Block>, Optional<Map<String, String>>> props) {
final Block block = props.getFirst().value();
final Map<String, String> properties = props.getSecond().orElse(new HashMap<>());
BlockState state = block.defaultBlockState();
if (!properties.isEmpty()) {
final StateDefinition<Block, BlockState> definition = block.getStateDefinition();
for (Map.Entry<String, String> entry : properties.entrySet()) {
final Property<? extends Comparable<?>> property = definition.getProperty(entry.getKey());
if (property != null) {
final Optional<?> value = property.getValue(entry.getValue());
if (value.isPresent()) {
try {
state = state.setValue((Property) property, (Comparable) value.get());
}
catch (final Exception e) {
Constants.LOG.error("Failed to update state for block {} with valid value {}={}. The mod that adds this block may have a serious issue.", BuiltInRegistries.BLOCK.getKey(block), entry.getKey(), entry.getValue());
return DataResult.error(e::getMessage);
}
}
else {
return DataResult.error(() -> "\"" + entry.getValue() + "\" is not a valid value for property \"" + property.getName() + "\" on block \"" + BuiltInRegistries.BLOCK.getKey(block) + "\". Available values: " + property.getAllValues().map(propVal -> ((Property) property).getName(propVal.value())).collect(Collectors.joining()));
}
}
else {
return DataResult.error(() -> "The property \"" + entry.getKey() + "\" is not valid for block \"" + BuiltInRegistries.BLOCK.getKey(block) + "\". Available properties: " + definition.getProperties().stream().map(Property::getName).collect(Collectors.joining()));
}
}
}
return DataResult.success(state);
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static DataResult<Pair<Holder<Block>, Optional<Map<String, String>>>> encodeBlockState(BlockState state) {
final Map<String, String> propertyMap = new HashMap<>();
for (Map.Entry<Property<?>, Comparable<?>> entry : state.getValues().entrySet()) {
propertyMap.put(entry.getKey().getName(), ((Property) entry.getKey()).getName(entry.getValue()));
}
return DataResult.success(new Pair<>(state.getBlock().builtInRegistryHolder(), Optional.ofNullable(propertyMap.isEmpty() ? null : propertyMap)));
}
/**
* Creates a codec that will try two different codecs, using the first valid codec. Encoding will always use the
* first codec.
*
* @param first The first codec to try when decoding. This will be the only codec used in encoding.
* @param second The second codec to try when decoding.
* @param <T> The type of codec to create.
* @return A codec that will try two different codecs.
*/
public static <T> Codec<T> xor(Codec<T> first, Codec<T> second) {
return Codec.xor(first, second).xmap(FunctionHelper::unpack, Either::left);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/RegistryMapCodecHelper.java
================================================
package net.darkhax.bookshelf.common.api.data.codecs.map;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.RegistryFixedCodec;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
public class RegistryMapCodecHelper<T> extends MapCodecHelper<Holder<T>> {
private final MapCodecHelper<TagKey<T>> tagHelper;
private RegistryMapCodecHelper(Codec<Holder<T>> holderCodec, ResourceKey<Registry<T>> key) {
super(holderCodec);
this.tagHelper = new MapCodecHelper<>(TagKey.codec(key));
}
public MapCodecHelper<TagKey<T>> tag() {
return this.tagHelper;
}
/**
* Creates a Codec helper for a builtin registry.
*
* @param registry The registry to create a codec helper for.
* @param <T> The type of value held by the registry.
* @return A Codec helper for a builtin registry.
*/
public static <T> RegistryMapCodecHelper<T> create(Registry<T> registry) {
return new RegistryMapCodecHelper<>(registry.holderByNameCodec(), (ResourceKey<Registry<T>>) registry.key());
}
/**
* Creates a Codec helper for a datapack registry. This codec can only be used when registry access is available
* through RegistryOps.
*
* @param key The key of the registry to use.
* @param <T> The type of value held by the registry.
* @return A Codec helper for datapack entries.
*/
public static <T> RegistryMapCodecHelper<T> create(ResourceKey<Registry<T>> key) {
return new RegistryMapCodecHelper<>(RegistryFixedCodec.create(key), key);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/stream/StreamCodecs.java
================================================
package net.darkhax.bookshelf.common.api.data.codecs.stream;
import io.netty.buffer.ByteBuf;
import net.darkhax.bookshelf.common.impl.data.ingredient.FalseIngredient;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import java.util.ArrayList;
import java.util.List;
public class StreamCodecs {
public static final StreamCodec<RegistryFriendlyByteBuf, String> STRING = StreamCodec.of(FriendlyByteBuf::writeUtf, FriendlyByteBuf::readUtf);
public static final StreamCodec<RegistryFriendlyByteBuf, List<ItemStack>> ITEM_STACK_LIST = list(ItemStack.STREAM_CODEC);
public static final StreamCodec<RegistryFriendlyByteBuf, Ingredient> INGREDIENT_NON_EMPTY = StreamCodec.of(
Ingredient.CONTENTS_STREAM_CODEC,
buf -> {
final Ingredient ingredient = Ingredient.CONTENTS_STREAM_CODEC.decode(buf);
return ingredient.isEmpty() ? FalseIngredient.INSTANCE.get() : ingredient;
}
);
public static <B extends ByteBuf, V> StreamCodec<B, List<V>> list(StreamCodec<B, V> baseCodec) {
return StreamCodec.of(
(buf, val) -> {
buf.writeInt(val.size());
for (V entry : val) {
baseCodec.encode(buf, entry);
}
},
buf -> {
final int size = buf.readInt();
final List<V> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(baseCodec.decode(buf));
}
return list;
}
);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/ConditionType.java
================================================
package net.darkhax.bookshelf.common.api.data.conditions;
import com.mojang.serialization.MapCodec;
import net.minecraft.resources.ResourceLocation;
/**
* Represents a type of load condition that Bookshelf can process and test.
*
* @param id The ID of the condition type.
* @param codec The codec used to serialize the condition from data.
*/
public record ConditionType(ResourceLocation id, MapCodec<? extends ILoadCondition> codec) {
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/ILoadCondition.java
================================================
package net.darkhax.bookshelf.common.api.data.conditions;
/**
* Load conditions allow JSON entries in data/resource packs to define optional conditions in order for them to load.
* For example a recipe file can prevent loading if a required item is not registered.
*/
public interface ILoadCondition {
/**
* Tests if the condition has been met or not.
*
* @return Has the condition been met?
*/
boolean allowLoading();
/**
* Gets the type of the condition. This is required for serializing conditions.
*
* @return The type of the condition.
*/
ConditionType getType();
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/LoadConditions.java
================================================
package net.darkhax.bookshelf.common.api.data.conditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import net.darkhax.bookshelf.common.api.data.codecs.map.MapCodecHelper;
import net.darkhax.bookshelf.common.api.data.codecs.map.MapCodecs;
import net.darkhax.bookshelf.common.impl.Constants;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class LoadConditions {
private static final Map<ResourceLocation, ConditionType> CONDITION_TYPES = new HashMap<>();
private static final Codec<ConditionType> CONDITION_TYPE_CODEC = ResourceLocation.CODEC.xmap(CONDITION_TYPES::get, ConditionType::id);
public static final String LOAD_CONDITION_TAG = Constants.id("load_conditions").toString();
public static final Codec<ILoadCondition> CONDITION_CODEC = CONDITION_TYPE_CODEC.dispatch(ILoadCondition::getType, ConditionType::codec);
public static final MapCodecHelper<ILoadCondition> CODEC_HELPER = new MapCodecHelper<>(CONDITION_CODEC);
@Nullable
public static ConditionType getType(ResourceLocation id) {
return CONDITION_TYPES.get(id);
}
public static <T extends ILoadCondition> ConditionType register(ResourceLocation id, MapCodec<T> codec) {
if (CONDITION_TYPES.containsKey(id)) {
Constants.LOG.warn("JSON Load Serializer ID {} has already been assigned to {}. Replacing with {}.", id, CONDITION_TYPES.get(id).codec(), codec);
}
final ConditionType type = new ConditionType(id, codec);
CONDITION_TYPES.put(id, type);
return type;
}
/**
* Reads one or more conditions from a JSON element. If the element is an object an array of 1 will be returned.
*
* @param conditionData The condition data read from the raw JSON entry.
* @return An array of load conditions read from the data.
*/
public static ILoadCondition[] getConditions(JsonElement conditionData) {
return MapCodecs.LOAD_CONDITION.getArray().decode(JsonOps.INSTANCE, conditionData).getOrThrow().getFirst();
}
/**
* Tests if a raw JSON element can be loaded. This will search for the condition property and attempt to deserialize
* and test those conditions.
*
* @param rawJson The raw JSON data as read from the data/resource pack.
* @return Whether the JSON entry should be loaded or not.
*/
public static boolean canLoad(JsonObject rawJson) {
if (rawJson.has(LOAD_CONDITION_TAG)) {
final JsonElement conditionData = rawJson.get(LOAD_CONDITION_TAG);
for (ILoadCondition condition : getConditions(conditionData)) {
if (!condition.allowLoading()) {
return false;
}
}
}
return true;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/enchantment/EnchantmentLevel.java
================================================
package net.darkhax.bookshelf.common.api.data.enchantment;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.Holder;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import java.util.function.ToIntBiFunction;
/**
* Calculates enchantment levels using different methods.
*/
public enum EnchantmentLevel {
/**
* Returns the highest level among all matching enchantments.
*/
HIGHEST((tag, enchantments) -> {
int level = 0;
for (Object2IntMap.Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
if (entry.getKey().is(tag) && entry.getIntValue() > level) {
level = entry.getIntValue();
}
}
return level;
}),
/**
* Returns the lowest level among all matching enchantments.
*/
LOWEST((tag, enchantments) -> {
int level = Integer.MAX_VALUE;
for (Object2IntMap.Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
if (entry.getKey().is(tag) && entry.getIntValue() < level) {
level = entry.getIntValue();
}
}
return level;
}),
/**
* Returns the level of the first matching enchantment.
*/
FIRST((tag, enchantments) -> {
for (Object2IntMap.Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
if (entry.getKey().is(tag)) {
return entry.getIntValue();
}
}
return 0;
}),
/**
* Returns the combined level of all matching enchantments.
*/
CUMULATIVE((tag, enchantments) -> {
int level = 0;
for (Object2IntMap.Entry<Holder<Enchantment>> entry : enchantments.entrySet()) {
if (entry.getKey().is(tag)) {
level += entry.getIntValue();
}
}
return level;
});
private final ToIntBiFunction<TagKey<Enchantment>, ItemEnchantments> func;
EnchantmentLevel(ToIntBiFunction<TagKey<Enchantment>, ItemEnchantments> func) {
this.func = func;
}
/**
* Gets the level of matching enchantments based on the calculation type.
*
* @param enchType A tag of the enchantments to match on.
* @param stack The item to test.
* @return The level based on the calculation type.
*/
public int get(TagKey<Enchantment> enchType, ItemStack stack) {
return (!stack.isEmpty() && stack.isEnchanted()) ? this.func.applyAsInt(enchType, stack.getEnchantments()) : 0;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/ingredient/IngredientLogic.java
================================================
package net.darkhax.bookshelf.common.api.data.ingredient;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import java.util.ArrayList;
import java.util.List;
public interface IngredientLogic<T extends IngredientLogic<T>> {
boolean test(ItemStack stack);
default List<ItemStack> getAllMatchingStacks() {
final List<ItemStack> matching = new ArrayList<>();
for (Item item : BuiltInRegistries.ITEM) {
final ItemStack stack = item.getDefaultInstance();
if (this.test(stack)) {
matching.add(stack);
}
}
return matching;
}
default boolean requiresTesting() {
return true;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/loot/PoolTarget.java
================================================
package net.darkhax.bookshelf.common.api.data.loot;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.level.storage.loot.LootTable;
/**
* Represents a specific loot pool target within a loot table. This class also provides predefined constants for some of
* the commonly modified loot pools.
*
* @param table The id of the loot table to target.
* @param index The index of the pool within the loot table. This is usually based on the order pools appear in the JSON
* data.
* @param hash A hash of the pools JSON data. This can be obtained using the bookshelf debug command in a development
* environment.
*/
public record PoolTarget(ResourceLocation table, int index, int hash) {
public static final PoolTarget MINESHAFT_RARE = of(BuiltInLootTables.ABANDONED_MINESHAFT, 0, 1537257923);
public static final PoolTarget MINESHAFT_UNCOMMON = of(BuiltInLootTables.ABANDONED_MINESHAFT, 1, -444048389);
public static final PoolTarget MINESHAFT_COMMON = of(BuiltInLootTables.ABANDONED_MINESHAFT, 2, 634581377);
public static final PoolTarget SIMPLE_DUNGEON_RARE = of(BuiltInLootTables.SIMPLE_DUNGEON, 0, -66091299);
public static final PoolTarget SIMPLE_DUNGEON_UNCOMMON = of(BuiltInLootTables.SIMPLE_DUNGEON, 1, 1870100239);
public static final PoolTarget SIMPLE_DUNGEON_COMMON = of(BuiltInLootTables.SIMPLE_DUNGEON, 2, 2004993944);
public static final PoolTarget CAT_GIFT = of(BuiltInLootTables.CAT_MORNING_GIFT, 0, 234355958);
public static final PoolTarget FISHING = of(BuiltInLootTables.FISHING, 0, 1127209674);
public static final PoolTarget FISHING_FISH = of(BuiltInLootTables.FISHING_FISH, 0, -190358337);
public static final PoolTarget FISHING_JUNK = of(BuiltInLootTables.FISHING_JUNK, 0, 1154453499);
public static final PoolTarget FISHING_TREASURE = of(BuiltInLootTables.FISHING_TREASURE, 0, 1729324233);
public static final PoolTarget PIGLIN_BARTERING = of(BuiltInLootTables.PIGLIN_BARTERING, 0, 718156885);
public static final PoolTarget SNIFFER_DIGGING = of(BuiltInLootTables.SNIFFER_DIGGING, 0, 1185470198);
public static final PoolTarget ARCHAEOLOGY_PYRAMID = of(BuiltInLootTables.DESERT_PYRAMID_ARCHAEOLOGY, 0, -1867551069);
public static final PoolTarget ARCHAEOLOGY_DESERT_WELL = of(BuiltInLootTables.DESERT_WELL_ARCHAEOLOGY, 0, -1508422416);
public static final PoolTarget ARCHAEOLOGY_OCEAN_RUIN_COLD = of(BuiltInLootTables.OCEAN_RUIN_COLD_ARCHAEOLOGY, 0, -1117683719);
public static final PoolTarget ARCHAEOLOGY_OCEAN_RUIN_WARM = of(BuiltInLootTables.OCEAN_RUIN_WARM_ARCHAEOLOGY, 0, 153317912);
public static final PoolTarget ARCHAEOLOGY_TRAIL_RUINS_COMMON = of(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_COMMON, 0, 300798809);
public static final PoolTarget ARCHAEOLOGY_TRAIL_RUINS_RARE = of(BuiltInLootTables.TRAIL_RUINS_ARCHAEOLOGY_RARE, 0, 1848809003);
public static PoolTarget of(ResourceKey<LootTable> table, int index, int hash) {
return new PoolTarget(table.location(), index, hash);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/loot/modifiers/LootPoolAddition.java
================================================
package net.darkhax.bookshelf.common.api.data.loot.modifiers;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
/**
* Represents a loot pool entry that should be added to a loot pool.
*
* @param id A unique ID for the individual entry. This should be unique to each entry and is used to help identify
* and debug entry additions.
* @param entry The entry to add to the pool.
*/
public record LootPoolAddition(ResourceLocation id, LootPoolEntryContainer entry) {
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/MerchantTier.java
================================================
package net.darkhax.bookshelf.common.api.entity.villager;
public enum MerchantTier {
NOVICE(0),
APPRENTICE(10),
JOURNEYMAN(70),
EXPERT(150),
MASTER(250);
private final int requiredExp;
MerchantTier(int requiredExp) {
this.requiredExp = requiredExp;
}
public int getRequiredExp() {
return this.requiredExp;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerBuys.java
================================================
package net.darkhax.bookshelf.common.api.entity.villager.trades;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.VillagerTrades;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.trading.ItemCost;
import net.minecraft.world.item.trading.MerchantOffer;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* A simple villager trade entry that represents an item being bought by the villager.
*
* @param stackToBuy The item being bought by the villager.
* @param emeralds The amount of emeralds to award the player.
* @param maxUses The amount of times the trade can be performed before a restocking is required.
* @param villagerXp The amount of villager XP to award for performing the trade.
* @param priceMultiplier A price multiplier.
*/
public record VillagerBuys(Supplier<ItemCost> stackToBuy, int emeralds, int maxUses, int villagerXp, float priceMultiplier) implements VillagerTrades.ItemListing {
@Override
public MerchantOffer getOffer(@NotNull Entity entity, @NotNull RandomSource random) {
return new MerchantOffer(this.stackToBuy.get(), new ItemStack(Items.EMERALD, this.emeralds), this.maxUses, this.villagerXp, this.priceMultiplier);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerOffers.java
================================================
package net.darkhax.bookshelf.common.api.entity.villager.trades;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.VillagerTrades;
import net.minecraft.world.item.trading.MerchantOffer;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* A simple villager trade entry that selects a random offer from an equally weighted array of offers.
*
* @param offers An equally weighted array of offers.
*/
public record VillagerOffers(Supplier<MerchantOffer>... offers) implements VillagerTrades.ItemListing {
@SafeVarargs
public VillagerOffers {
}
@Override
public MerchantOffer getOffer(@NotNull Entity entity, @NotNull RandomSource randomSource) {
return offers[randomSource.nextInt(offers.length)].get();
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerSells.java
================================================
package net.darkhax.bookshelf.common.api.entity.villager.trades;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.VillagerTrades;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.trading.ItemCost;
import net.minecraft.world.item.trading.MerchantOffer;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* A simple villager trade entry that represents an item being sold to the player.
*
* @param itemToBuy The item being sold by the villager.
* @param emeraldCost The amount of emeralds the trade will cost.
* @param maxUses The amount of times the trade can be performed before a restocking is required.
* @param villagerXp The amount of villager XP to award for performing the trade.
* @param priceMultiplier A price multiplier.
*/
public record VillagerSells(Supplier<ItemStack> itemToBuy, int emeraldCost, int maxUses, int villagerXp, float priceMultiplier) implements VillagerTrades.ItemListing {
@Override
public MerchantOffer getOffer(@NotNull Entity villager, @NotNull RandomSource rng) {
return new MerchantOffer(new ItemCost(Items.EMERALD, this.emeraldCost), this.itemToBuy.get(), this.maxUses, this.villagerXp, this.priceMultiplier);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/CachedSupplier.java
================================================
package net.darkhax.bookshelf.common.api.function;
import net.darkhax.bookshelf.common.impl.Constants;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* A Supplier implementation that will cache the result of an internal delegate supplier.
*
* @param <T> The type that is cached by the supplier.
*/
public class CachedSupplier<T> implements Supplier<T> {
/**
* The internal Supplier responsible for producing the cached value.
*/
private final Supplier<T> delegate;
/**
* Tracks if the delegate supplier has been cached.
*/
private boolean cached = false;
/**
* The most recently cached value.
*/
@Nullable
private T cachedValue;
protected CachedSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}
@Override
public T get() {
if (!this.isCached()) {
this.cachedValue = this.delegate.get();
this.cached = true;
}
return cachedValue;
}
/**
* Invalidates the cached value. This will result in a new value being cached the next type {@link #get()} is used.
*/
public void invalidate() {
this.cached = false;
this.cachedValue = null;
}
/**
* Checks if this supplier has a cached value. This is not a substitute for null checking.
*
* @return Has the supplier cached a value.
*/
public boolean isCached() {
return this.cached;
}
/**
* Safely attempts to invoke a consumer with the cached value. If a value has not been cached the consumer will not
* be invoked and a new value will not be cached. The consumer will still be invoked if the cached value is null.
*
* @param consumer The consumer to invoke if a value has been cached.
*/
public void ifCached(Consumer<T> consumer) {
if (this.isCached()) {
consumer.accept(this.get());
}
}
/**
* Safely attempts to invoke a consumer with the cached value. If a value has not been cached, or the cached value
* is null the consumer will not be invoked and a new value will not be cached.
*
* @param consumer The consumer to invoke if a cached value is present.
*/
public void ifPresent(Consumer<T> consumer) {
if (this.cachedValue != null) {
consumer.accept(this.get());
}
}
/**
* Invokes the consumer with the cached value. This will cause a value to be cached if one has not been cached
* already.
*
* @param consumer The consumer to invoke.
*/
public void apply(Consumer<T> consumer) {
consumer.accept(this.get());
}
/**
* Performs an unsafe cast to the expected type.
*/
public <X> CachedSupplier<X> cast() {
return (CachedSupplier<X>) this;
}
/**
* Creates a cached supplier that can only produce a single value.
*
* @param singleton The only value for the cache to use.
* @param <T> The type of value held by the cache.
* @return A cached supplier that will only produce a single cached value.
*/
public static <T> CachedSupplier<T> singleton(T singleton) {
return cache(() -> singleton);
}
/**
* Creates a cached supplier that will cache a value from the supplied delegate when queried.
*
* @param delegate The delegate supplier responsible for producing the cached value. This will only be accessed when
* the cached supplier is being accessed and has not been cached already.
* @param <T> The type of value held by the cache.
* @return A supplier that will cache a value from the supplied delegate supplier.
*/
public static <T> CachedSupplier<T> cache(Supplier<T> delegate) {
return new CachedSupplier<>(delegate);
}
@SuppressWarnings("unchecked")
public static <T> CachedSupplier<T> of(ResourceKey<T> key) {
return CachedSupplier.cache(() -> {
final Registry<?> registry = BuiltInRegistries.REGISTRY.get(key.registry());
if (registry == null) {
Constants.LOG.error("Registry {} could not be found!", key.registry());
throw new IllegalStateException("Registry with name " + key.registry() + " was not found!");
}
return ((Registry<T>) registry).getOrThrow(key);
});
}
public static <T> CachedSupplier<T> of(Registry<T> registry, String namespace, String path) {
return of(registry, ResourceLocation.fromNamespaceAndPath(namespace, path));
}
public static <T> CachedSupplier<T> of(Registry<T> registry, ResourceLocation id) {
return CachedSupplier.cache(() -> registry.get(id));
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/QuadConsumer.java
================================================
package net.darkhax.bookshelf.common.api.function;
import java.util.Objects;
/**
* A consumer that accepts four parameters.
*
* @param <P1> The first parameter.
* @param <P2> The second parameter.
* @param <P3> The third parameter.
* @param <P4> The fourth parameter.
*/
@FunctionalInterface
public interface QuadConsumer<P1, P2, P3, P4> {
/**
* Consumes the parameters.
*
* @param p1 The first parameter.
* @param p2 The second parameter.
* @param p3 The third parameter.
* @param p4 The fourth parameter.
*/
void accept(P1 p1, P2 p2, P3 p3, P4 p4);
/**
* Chains another consumer on to this one.
*
* @param after The consumer to run after this one.
* @return A new consumer that chains both.
*/
default QuadConsumer<P1, P2, P3, P4> andThen(QuadConsumer<P1, P2, P3, P4> after) {
Objects.requireNonNull(after);
return (p1, p2, p3, p4) -> {
accept(p1, p2, p3, p4);
after.accept(p1, p2, p3, p4);
};
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/ReloadableCache.java
================================================
package net.darkhax.bookshelf.common.api.function;
import net.darkhax.bookshelf.common.impl.Constants;
import net.darkhax.bookshelf.common.mixin.access.level.AccessorRecipeManager;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* A cached value that is lazily loaded and will be invalidated automatically after the game has been reloaded.
*
* @param <T> The type of the cached value.
*/
public class ReloadableCache<T> implements Function<Level, T> {
/**
* A reloadable cache that will always return null. Not all empty instances will match this instance.
*/
@SuppressWarnings("rawtypes")
public static final ReloadableCache EMPTY = ReloadableCache.of(level -> null);
/**
* An internal function that is responsible for producing the value to cache.
*/
private final Function<Level, T> delegate;
/**
* A flag that tracks if a value has been cached.
*/
private boolean cached = false;
private int revision = 0;
/**
* The value that is currently cached.
*/
@Nullable
private T cachedValue;
protected ReloadableCache(Function<Level, T> delegate) {
this.delegate = delegate;
}
@Nullable
@Override
public T apply(Level level) {
if (!this.isCached() || this.revision != (level.isClientSide ? Constants.CLIENT_REVISION : Constants.SERVER_REVISION)) {
this.cachedValue = this.delegate.apply(level);
this.revision = (level.isClientSide) ? Constants.CLIENT_REVISION : Constants.SERVER_REVISION;
this.cached = true;
}
return this.cachedValue;
}
/**
* Manually invalidates the cache. This will result in a new value being cached the next time {@link #apply(Level)}
* is invoked.
*/
public void invalidate() {
this.cached = false;
this.cachedValue = null;
this.revision = -1;
}
/**
* Checks if the cache has cached a value. This is not a substitute for null checking.
*
* @return Has the supplier cached a value.
*/
public boolean isCached() {
return this.cached;
}
/**
* Invokes the consumer with the cached value. This will cause a value to be cached if one has not been cached
* already.
*
* @param level The current game level. This is used to provide context about the current state of the game.
* @param consumer The consumer to invoke.
*/
public void apply(Level level, Consumer<T> consumer) {
consumer.accept(this.apply(level));
}
/**
* Applies a function to the cached value if the value is not null.
*
* @param level The current game level. This is used to provide context about the current state of the game.
* @param consumer The consumer to invoke.
*/
public void ifPresent(Level level, Consumer<T> consumer) {
final T value = this.apply(level);
if (value != null) {
consumer.accept(value);
}
}
/**
* Maps non null cache values to a new value.
*
* @param level The current game level. This is used to provide context about the current state of the game.
* @param mapper A mapper function to map the cached value to something new. This is only used if the value is not
* null.
* @param <R> The return type.
* @return The mapped value or null.
*/
@Nullable
public <R> R map(Level level, Function<T, R> mapper) {
final T value = this.apply(level);
return value != null ? mapper.apply(value) : null;
}
/**
* Creates a cache of a value that will be recalculated when the game reloads.
*
* @param supplier The supplier used to produce the cached value.
* @param <T> The type of value held by the cache.
* @return A cache of a value that will be recalculated when the game reloads.
*/
public static <T> ReloadableCache<T> of(Supplier<T> supplier) {
return new ReloadableCache<>(level -> supplier.get());
}
/**
* Creates a cache of a value that will be recalculated when the game reloads.
*
* @param delegate A function used to produce the value to cache.
* @param <T> The type of value held by the cache.
* @return A cache of a value that will be recalculated when the game reloads.
*/
public static <T> ReloadableCache<T> of(Function<Level, T> delegate) {
return new ReloadableCache<>(delegate);
}
/**
* Creates a cache of a registry value that will be reaquired when the game reloads.
*
* @param registry The registry to look up the value in.
* @param id The ID of the value to lookup.
* @param <T> The type of value held by the cache.
* @return A cache of a registry value that will be reaquired when the game reloads.
*/
public static <T> ReloadableCache<T> of(ResourceKey<? extends Registry<T>> registry, ResourceLocation id) {
return ReloadableCache.of(level -> level.registryAccess().registryOrThrow(registry).get(id));
}
/**
* Creates a cache of recipe entries for a recipe type.
*
* @param type The type of recipe.
* @param <T> The type of the recipe.
* @return A map of recipes for the recipe type.
*/
@SuppressWarnings("unchecked")
public static <T extends Recipe<?>> ReloadableCache<Map<ResourceLocation, RecipeHolder<T>>> of(RecipeType<T> type) {
return ReloadableCache.of(level -> {
final Map<ResourceLocation, RecipeHolder<T>> byId = new HashMap<>();
if (level.getRecipeManager() instanceof AccessorRecipeManager accessor) {
final Collection<RecipeHolder<?>> recipes = accessor.bookshelf$byTypeMap().get(type);
recipes.forEach(entry -> byId.put(entry.id(), (RecipeHolder<T>) entry));
}
return byId;
});
}
/**
* Creates a cache of recipe entries for a recipe type.
*
* @param type The type of recipe.
* @param <T> The type of the recipe.
* @return A map of recipes for the recipe type.
*/
@SuppressWarnings("unchecked")
public static <T extends Recipe<?>> ReloadableCache<Map<ResourceLocation, RecipeHolder<T>>> recipes(Supplier<RecipeType<T>> type) {
return ReloadableCache.of(level -> {
final Map<ResourceLocation, RecipeHolder<T>> byId = new HashMap<>();
if (level.getRecipeManager() instanceof AccessorRecipeManager accessor) {
final Collection<RecipeHolder<?>> recipes = accessor.bookshelf$byTypeMap().get(type.get());
recipes.forEach(entry -> byId.put(entry.id(), (RecipeHolder<T>) entry));
}
return byId;
});
}
/**
* Creates a cache of an entity instance.
*
* @param entityData The data used to create the entity.
* @return A reloadable entity instance.
*/
public static ReloadableCache<Entity> entity(CompoundTag entityData) {
if (entityData == null || !entityData.contains("id", Tag.TAG_STRING)) {
throw new IllegalStateException("The provided entity data does not contain an entity ID! data=" + entityData);
}
return ReloadableCache.of(level -> {
try {
return EntityType.loadEntityRecursive(entityData, level, Function.identity());
}
catch (Exception e) {
throw new IllegalStateException("Encountered an error while constructing the target entity.", e);
}
});
}
/**
* Creates a cache of a living entity instance.
*
* @param entityData The data used to create the entity.
* @return A reloadable living entity instance.
*/
public static ReloadableCache<LivingEntity> living(CompoundTag entityData) {
final ReloadableCache<Entity> entityCache = entity(entityData);
return ReloadableCache.of(level -> {
if (entityCache.apply(level) instanceof LivingEntity living) {
return living;
}
throw new IllegalStateException("Constructed entity was not a LivingEntity type. data=" + entityData);
});
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/SidedReloadableCache.java
================================================
package net.darkhax.bookshelf.common.api.function;
import net.darkhax.bookshelf.common.mixin.access.level.AccessorRecipeManager;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class SidedReloadableCache<T> implements Function<Level, T> {
private final ReloadableCache<T> client;
private final ReloadableCache<T> server;
public SidedReloadableCache(ReloadableCache<T> client, ReloadableCache<T> server) {
this.client = client;
this.server = server;
}
public ReloadableCache<T> getCache(Level level) {
return level.isClientSide ? client : server;
}
@Nullable
@Override
public T apply(Level level) {
return getCache(level).apply(level);
}
public void invalidate(Level level) {
getCache(level).invalidate();
}
public boolean isCached(Level level) {
return getCache(level).isCached();
}
public void apply(Level level, Consumer<T> consumer) {
getCache(level).apply(level, consumer);
}
public void ifPresent(Level level, Consumer<T> consumer) {
getCache(level).ifPresent(level, consumer);
}
@Nullable
public <R> R map(Level level, Function<T, R> mapper) {
return getCache(level).map(level, mapper);
}
public static <T> SidedReloadableCache<T> of(Function<Level, T> cacheFunc) {
return new SidedReloadableCache<>(new ReloadableCache<>(cacheFunc), new ReloadableCache<>(cacheFunc));
}
@SuppressWarnings("unchecked")
public static <T extends Recipe<?>> SidedReloadableCache<Map<ResourceLocation, RecipeHolder<T>>> recipes(Supplier<RecipeType<T>> type) {
return of(level -> {
final Map<ResourceLocation, RecipeHolder<T>> byId = new HashMap<>();
if (level.getRecipeManager() instanceof AccessorRecipeManager accessor) {
final Collection<RecipeHolder<?>> recipes = accessor.bookshelf$byTypeMap().get(type.get());
recipes.forEach(entry -> byId.put(entry.id(), (RecipeHolder<T>) entry));
}
return byId;
});
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/TriConsumer.java
================================================
package net.darkhax.bookshelf.common.api.function;
import java.util.Objects;
@FunctionalInterface
public interface TriConsumer<P1, P2, P3> {
void accept(P1 p1, P2 p2, P3 p3);
default TriConsumer<P1, P2, P3> andThen(TriConsumer<P1, P2, P3> after) {
Objects.requireNonNull(after);
return (p1, p2, p3) -> {
accept(p1, p2, p3);
after.accept(p1, p2, p3);
};
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/TriFunction.java
================================================
package net.darkhax.bookshelf.common.api.function;
import java.util.Objects;
import java.util.function.Function;
@FunctionalInterface
public interface TriFunction<P1, P2, P3, R> {
R apply(P1 p1, P2 p2, P3 p3);
default TriFunction<P1, P2, P3, R> andThen(Function<? super R, ? extends R> after) {
Objects.requireNonNull(after);
return (p1, p2, p3) -> after.apply(apply(p1, p2, p3));
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/item/IItemHooks.java
================================================
package net.darkhax.bookshelf.common.api.item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import java.util.function.Consumer;
public interface IItemHooks {
default void addCreativeTabForms(CreativeModeTab tab, Consumer<ItemStack> displayItems) {
// NO-OP
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/loot/LootPoolEntryDescriber.java
================================================
package net.darkhax.bookshelf.common.api.loot;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
/**
* Describes the potential items that a loot pool entry can generate. See {@link LootPoolEntryDescriptions} for usage.
*/
@FunctionalInterface
public interface LootPoolEntryDescriber {
/**
* Describes items that may potentially be dropped by a loot pool entry.
*
* @param registries Access to the current game registries.
* @param entry The loot pool entry to be processed.
* @param collector Collects entries from the entry into the desired format.
*/
void getPotentialDrops(@NotNull RegistryAccess registries, @NotNull LootPoolEntryContainer entry, Consumer<ItemStack> collector);
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/loot/LootPoolEntryDescriptions.java
================================================
package net.darkhax.bookshelf.common.api.loot;
import com.mojang.datafixers.util.Either;
import net.darkhax.bookshelf.common.api.function.CachedSupplier;
import net.darkhax.bookshelf.common.api.service.Services;
import net.darkhax.bookshelf.common.impl.data.loot.entries.LootItemStack;
import net.darkhax.bookshelf.common.impl.registry.adapter.LootDescriptionAdapter;
import net.darkhax.bookshelf.common.mixin.access.loot.AccessorCompositeEntryBase;
import net.darkhax.bookshelf.common.mixin.access.loot.AccessorLootItem;
import net.darkhax.bookshelf.common.mixin.access.loot.AccessorLootPool;
import net.darkhax.bookshelf.common.mixin.access.loot.AccessorLootTable;
import net.darkhax.bookshelf.common.mixin.access.loot.AccessorNestedLootTable;
import net.darkhax.bookshelf.common.mixin.access.loot.AccessorTagEntry;
import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ItemLore;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.entries.DynamicLoot;
import net.minecraft.world.level.storage.loot.entries.EmptyLootItem;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryType;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Provides a system for describing what items can be dropped by a loot table.
*/
public class LootPoolEntryDescriptions {
private static final CachedSupplier<ItemStack> UNKNOWN_ITEM_DISPLAY = CachedSupplier.cache(() -> {
final ItemStack stack = new ItemStack(Items.STRUCTURE_VOID);
stack.set(DataComponents.ITEM_NAME, Component.translatable("tooltips.bookshelf.loot.unknown"));
stack.set(DataComponents.LORE, new ItemLore(List.of(), List.of(Component.translatable("tooltips.bookshelf.loot.unknown.desc").withStyle(ChatFormatting.GRAY))));
return stack;
});
private static final CachedSupplier<ItemStack> EMPTY_ITEM_DISPLAY = CachedSupplier.cache(() -> {
final ItemStack stack = new ItemStack(Items.BARRIER);
stack.set(DataComponents.ITEM_NAME, Component.translatable("tooltips.bookshelf.loot.empty"));
stack.set(DataComponents.LORE, new ItemLore(List.of(), List.of(Component.translatable("tooltips.bookshelf.loot.empty.desc").withStyle(ChatFormatting.GRAY))));
return stack;
});
private static final CachedSupplier<ItemStack> DYNAMIC_DISPLAY = CachedSupplier.cache(() -> {
final ItemStack stack = new ItemStack(Items.JIGSAW);
stack.set(DataComponents.ITEM_NAME, Component.translatable("tooltips.bookshelf.loot.dynamic"));
stack.set(DataComponents.LORE, new ItemLore(List.of(), List.of(Component.translatable("tooltips.bookshelf.loot.dynamic.desc").withStyle(ChatFormatting.GRAY))));
return stack;
});
private static final Map<LootPoolEntryType, LootPoolEntryDescriber> DESCRIBERS = new HashMap<>();
private static boolean hasInitialized = false;
public static final LootPoolEntryDescriber EMPTY = (server, entry, collector) -> {
if (entry instanceof EmptyLootItem) {
collector.accept(EMPTY_ITEM_DISPLAY.get());
}
};
public static final LootPoolEntryDescriber ITEM = (server, entry, collector) -> {
if (entry instanceof AccessorLootItem accessor) {
collector.accept(new ItemStack(accessor.bookshelf$item()));
}
};
public static final LootPoolEntryDescriber LOOT_TABLE = (server, entry, collector) -> {
if (entry instanceof AccessorNestedLootTable accessor) {
getPotentialItems(server, accessor.bookshelf$contents(), collector);
}
};
public static final LootPoolEntryDescriber DYNAMIC = (server, entry, collector) -> {
if (entry instanceof DynamicLoot) {
collector.accept(DYNAMIC_DISPLAY.get());
}
};
public static final LootPoolEntryDescriber TAG = (server, entry, collector) -> {
if (entry instanceof AccessorTagEntry tagEntry) {
getTagItems(tagEntry.bookshelf$tag(), collector);
}
};
public static final LootPoolEntryDescriber COMPOSITE = (server, entry, collector) -> {
if (entry instanceof AccessorCompositeEntryBase accessor) {
getPotentialItems(server, accessor.bookshelf$children(), collector);
}
};
public static final LootPoolEntryDescriber ITEM_STACK = (server, entry, collector) -> {
if (entry instanceof LootItemStack loot) {
collector.accept(loot.getBaseStack());
}
};
private static void bootstrap() {
if (!hasInitialized) {
final LootDescriptionAdapter register = new LootDescriptionAdapter(DESCRIBERS::put);
Services.CONTENT.get().forEach(provider -> provider.defineLootDescriptions(register));
hasInitialized = true;
}
}
/**
* Generates a list of unique items that can generate from a loot table.
*
* @param registries The current registries.
* @param table The loot table to examine.
* @return A list containing the entries.
*/
public static List<ItemStack> getUniqueItems(@NotNull RegistryAccess registries, LootTable table) {
final List<ItemStack> items = new ArrayList<>();
getPotentialItems(registries, table, stack -> addStacking(items, stack));
return items;
}
/**
* Gets potential drops for a loot table.
*
* @param registries The current registries.
* @param table The loot table to examine.
* @param consumer Collects entries in your desired format.
*/
public static void getPotentialItems(@NotNull RegistryAccess registries, Either<ResourceKey<LootTable>, LootTable> table, Consumer<ItemStack> consumer) {
final LootTable resolved = table.map(rl -> registries.registryOrThrow(Registries.LOOT_TABLE).get(rl), Function.identity());
if (resolved != null) {
getPotentialItems(registries, resolved, consumer);
}
}
/**
* Gets potential drops for a loot table.
*
* @param registries The current registries.
* @param table The loot table to examine.
* @param consumer Collects entries in your desired format.
*/
public static void getPotentialItems(@NotNull RegistryAccess registries, LootTable table, Consumer<ItemStack> consumer) {
if (table instanceof AccessorLootTable tableAccess) {
for (LootPool pool : tableAccess.bookshelf$pools()) {
if (pool instanceof AccessorLootPool poolAccess) {
getPotentialItems(registries, poolAccess.bookshelf$entries(), consumer);
}
}
}
}
/**
* Gets potential drops for a list of loot pool entries.
*
* @param registries The current registries.
* @param entries A list of entries to examine.
* @param collector Collects entries in your desired format.
*/
public static void getPotentialItems(@NotNull RegistryAccess registries, List<LootPoolEntryContainer> entries, Consumer<ItemStack> collector) {
for (LootPoolEntryContainer entry : entries) {
getPotentialItems(registries, entry, collector);
}
}
/**
* Gets potential drops from a loot pool entry.
*
* @param registries The current registries.
* @param entry The pool entry to examine.
* @param collector Collects entries in your desired format.
*/
public static void getPotentialItems(@NotNull RegistryAccess registries, LootPoolEntryContainer entry, Consumer<ItemStack> collector) {
bootstrap();
final LootPoolEntryDescriber describer = DESCRIBERS.get(entry.getType());
if (describer != null) {
describer.getPotentialDrops(registries, entry, collector);
}
else {
collector.accept(UNKNOWN_ITEM_DISPLAY.get());
}
}
/**
* Adds an ItemStack to a list, only if the item does not stack with any of the items already in the list.
*
* @param items The list to add to.
* @param toAdd The entry to add.
*/
private static void addStacking(List<ItemStack> items, ItemStack toAdd) {
for (ItemStack existing : items) {
if (Objects.equals(existing, toAdd) || ItemStack.isSameItemSameComponents(existing, toAdd)) {
return;
}
}
items.add(toAdd);
}
private static void getTagItems(TagKey<Item> tag, Consumer<ItemStack> collector) {
for (Holder<Item> item : BuiltInRegistries.ITEM.getTagOrEmpty(tag)) {
collector.accept(new ItemStack(item));
}
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/menu/data/BlockPosData.java
================================================
package net.darkhax.bookshelf.common.api.menu.data;
import net.minecraft.core.BlockPos;
import net.minecraft.world.inventory.ContainerData;
import java.util.Arrays;
/**
* Allows a block position to be kept in sync using the container system. The server should always construct this
* directly while the client should use SimpleContainerData with size of 3.
*/
public class BlockPosData implements ContainerData {
private final int[] pos;
private final boolean mutable;
public BlockPosData(BlockPos pos) {
this(pos, false);
}
public BlockPosData(BlockPos pos, boolean mutable) {
this.pos = new int[]{pos.getX(), pos.getY(), pos.getZ()};
this.mutable = mutable;
}
@Override
public int get(int slot) {
return pos[slot];
}
@Override
public void set(int slot, int value) {
if (this.mutable) {
pos[slot] = value;
}
}
@Override
public int getCount() {
return 3;
}
/**
* Gets the BlockPos currently held by the container data. This should only be called on the server.
*
* @return The BlockPos being held.
*/
public BlockPos getPos() {
return new BlockPos(pos[0], pos[1], pos[2]);
}
/**
* Reads a BlockPos from untyped container data. This should be used to read the position on the client which should
* be using a SimpleContainerData and not a BlockPosData.
*
* @param data The data to read from.
* @return The BlockPos that was ready.
*/
public static BlockPos readPos(ContainerData data) {
if (data.getCount() != 3) {
throw new IllegalStateException("Can not read BlockPos from container data. Expected 3 values, found " + data.getCount() + ". data=" + Arrays.toString(toArray(data)));
}
return new BlockPos(data.get(0), data.get(1), data.get(2));
}
private static int[] toArray(ContainerData containerData) {
final int[] data = new int[containerData.getCount()];
for (int i = 0; i < containerData.getCount(); i++) {
data[i] = containerData.get(i);
}
return data;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/menu/slot/InputSlot.java
================================================
package net.darkhax.bookshelf.common.api.menu.slot;
import com.mojang.datafixers.util.Pair;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* A basic input slot implementation.
*/
public class InputSlot extends Slot {
private final ResourceLocation emptyTexture;
private final Predicate<ItemStack> canPlace;
public InputSlot(Container container, int slot, int x, int y, ResourceLocation emptyTexture) {
this(container, slot, x, y, emptyTexture, stack -> true);
}
public InputSlot(Container container, int slot, int x, int y, ResourceLocation emptyTexture, Predicate<ItemStack> canPlace) {
super(container, slot, x, y);
this.emptyTexture = emptyTexture;
this.canPlace = canPlace;
}
@Override
public int getMaxStackSize() {
return 1;
}
@Nullable
@Override
public Pair<ResourceLocation, ResourceLocation> getNoItemIcon() {
return Pair.of(InventoryMenu.BLOCK_ATLAS, this.emptyTexture);
}
@Override
public boolean mayPlace(@NotNull ItemStack stack) {
return this.canPlace.test(stack);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/menu/slot/OutputSlot.java
================================================
package net.darkhax.bookshelf.common.api.menu.slot;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
/**
* A basic output slot implementation.
*/
public class OutputSlot extends Slot {
@Nullable
private final BiConsumer<Player, ItemStack> takeFunc;
public OutputSlot(Container potContainer, int slot, int x, int y) {
this(potContainer, slot, x, y, null);
}
public OutputSlot(Container potContainer, int slot, int x, int y, @Nullable BiConsumer<Player, ItemStack> takeFunc) {
super(potContainer, slot, x, y);
this.takeFunc = takeFunc;
}
@Override
public boolean mayPlace(@NotNull ItemStack stack) {
return false;
}
@Override
public void onTake(@NotNull Player player, @NotNull ItemStack stack) {
super.onTake(player, stack);
if (this.takeFunc != null) {
this.takeFunc.accept(player, stack);
}
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/AbstractPacket.java
================================================
package net.darkhax.bookshelf.common.api.network;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
/**
* A basic packet implementation.
*
* @param <T> The type of the payload.
*/
public abstract class AbstractPacket<T extends CustomPacketPayload> implements IPacket<T> {
/**
* The type of the payload.
*/
private final CustomPacketPayload.Type<T> type;
/**
* A codec to serialize the payload.
*/
private final StreamCodec<RegistryFriendlyByteBuf, T> codec;
/**
* The intended destination of the payload.
*/
private final Destination direction;
/**
* A packet that is sent from the server to the client.
*
* @param id The packet ID.
* @param codec The payload codec.
*/
public AbstractPacket(ResourceLocation id, StreamCodec<RegistryFriendlyByteBuf, T> codec) {
this(id, codec, Destination.SERVER_TO_CLIENT);
}
/**
* A simple packet type.
*
* @param id The packet ID.
* @param codec The payload codec.
* @param direction The intended destination of the packet.
*/
public AbstractPacket(ResourceLocation id, StreamCodec<RegistryFriendlyByteBuf, T> codec, Destination direction) {
this.type = new CustomPacketPayload.Type<>(id);
this.codec = codec;
this.direction = direction;
}
@Override
public CustomPacketPayload.Type<T> type() {
return this.type;
}
@Override
public StreamCodec<RegistryFriendlyByteBuf, T> streamCodec() {
return this.codec;
}
@Override
public Destination destination() {
return this.direction;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/Destination.java
================================================
package net.darkhax.bookshelf.common.api.network;
/**
* Determines where the packet will be resolved.
*/
public enum Destination {
/**
* Describes a situation where the server has a payload that will be sent to a client. The payload will be handled
* on the client and can use code that is only available on a dedicated client.
*/
SERVER_TO_CLIENT,
/**
* Describes a situation where the client has a payload that will be sent to a server. The payload will be handled
* by the server and can access the game state. Please keep in mind that payloads originating on the client can be
* forged and should not be trusted without an appropriate level of validation on the server.
*/
CLIENT_TO_SERVER,
/**
* Describes a situation where the packet can originate from and be handled by a client or a server. These packets
* have the limitations of both SERVER_TOL_CLIENT and CLIENT_TO_SERVER packets.
*/
BIDIRECTIONAL;
/**
* Checks if the payload can be handled on a server.
*
* @return If the payload can be handled by a server.
*/
public boolean handledByServer() {
return this == CLIENT_TO_SERVER || this == BIDIRECTIONAL;
}
/**
* Checks if the payload can be handled on a client.
*
* @return If the payload can be handled by a client.
*/
public boolean handledByClient() {
return this == SERVER_TO_CLIENT || this == BIDIRECTIONAL;
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/INetworkHandler.java
================================================
package net.darkhax.bookshelf.common.api.network;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
/**
* Provides platform specific implementations of network related code. Access using
* {@link net.darkhax.bookshelf.common.api.service.Services#NETWORK}.
*/
public interface INetworkHandler {
/**
* Registers a Bookshelf packet type to the packet registry.
*
* @param packet The packet type to register.
* @param <T> The type of the payload.
*/
<T extends CustomPacketPayload> void register(IPacket<T> packet);
/**
* Sends a payload from the client to the server.
*
* @param payload The payload to send.
* @param <T> The type of the payload.
*/
<T extends CustomPacketPayload> void sendToServer(T payload);
/**
* Sends a packet from the server to a player.
*
* @param recipient The recipient of the packet.
* @param payload The payload to send.
* @param <T> The type of the payload.
*/
<T extends CustomPacketPayload> void sendToPlayer(ServerPlayer recipient, T payload);
/**
* Tests if a payload type can be sent to a player.
*
* @param recipient The recipient of the packet.
* @param payload The payload to test.
* @return If the payload can be sent to the recipient player.
*/
default boolean canSendPacket(ServerPlayer recipient, CustomPacketPayload payload) {
return this.canSendPacket(recipient, payload.type().id());
}
/**
* Tests if a payload type can be sent to a player.
*
* @param recipient The recipient of the packet.
* @param packet The packet to test.
* @return If the payload can be sent to the recipient player.
*/
default boolean canSendPacket(ServerPlayer recipient, IPacket<?> packet) {
return this.canSendPacket(recipient, packet.type().id());
}
/**
* Tests if a payload type can be sent to a player.
*
* @param recipient The recipient of the packet.
* @param payloadId The payload type ID.
* @return If the payload can be sent to the recipient player.
*/
boolean canSendPacket(ServerPlayer recipient, ResourceLocation payloadId);
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/IPacket.java
================================================
package net.darkhax.bookshelf.common.api.network;
import net.darkhax.bookshelf.common.api.PhysicalSide;
import net.darkhax.bookshelf.common.api.annotation.OnlyFor;
import net.darkhax.bookshelf.common.api.service.Services;
import net.darkhax.bookshelf.common.impl.Constants;
import net.minecraft.client.Minecraft;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.PlayerList;
import org.jetbrains.annotations.Nullable;
/**
* Defines a custom payload packet. These packets must be registered using an
* {@link net.darkhax.bookshelf.common.api.registry.ContentProvider}.
*
* @param <T> The type of the payload.
*/
public interface IPacket<T extends CustomPacketPayload> {
/**
* Gets the payload type.
*
* @return The payload type.
*/
CustomPacketPayload.Type<T> type();
/**
* Gets a stream codec that can serialize the payload across the network.
*
* @return The stream coded used to serialize the payload.
*/
StreamCodec<RegistryFriendlyByteBuf, T> streamCodec();
/**
* Defines how the packet is meant to be sent and where it should be handled.
*
* @return The intended destination of the packet.
*/
Destination destination();
/**
* This method will be called when the custom payload is received. This method can be called on both the client and
* server, depending on the destination type defined by {@link #destination()}.
*
* @param sender The sender of the packet. This will always be null for packets handled on the client.
* @param isServer True when the packet is being handled on the server.
* @param payload The payload that was received.
*/
void handle(@Nullable ServerPlayer sender, boolean isServer, T payload);
/**
* Sends the packet from the server to a specific player.
*
* @param recipient The intended recipient of the payload.
* @param payload The payload to send.
*/
default void toPlayer(ServerPlayer recipient, T payload) {
if (!this.destination().handledByClient()) {
Constants.LOG.error("Attempted to send invalid packet {} to client! Class: {} Destination: {} Payload: {}", this.type().id(), this.getClass(), this.destination(), payload.toString());
throw new IllegalStateException("Attempted to send invalid packet " + this.type().id() + " to client!");
}
Services.NETWORK.sendToPlayer(recipient, payload);
}
/**
* Sends the packet from the server to all connected players.
*
* @param level A serverside level, used to access the player list.
* @param payload The payload to send.
*/
default void toAllPlayers(ServerLevel level, T payload) {
toAllPlayers(level.getServer(), payload);
}
/**
* Sends the packet from the server to all connected players.
*
* @param server The server instance, used to access the player list.
* @param payload The payload to send.
*/
default void toAllPlayers(MinecraftServer server, T payload) {
toAllPlayers(server.getPlayerList(), payload);
}
/**
* Sends the packet from the server to all connected players.
*
* @param playerList The player list.
* @param payload The payload to send.
*/
default void toAllPlayers(PlayerList playerList, T payload) {
for (ServerPlayer player : playerList.getPlayers()) {
toPlayer(player, payload);
}
}
/**
* Sends a packet from a client to the server.
*
* @param payload The payload to send.
*/
@OnlyFor(PhysicalSide.CLIENT)
default void toServer(T payload) {
if (!this.destination().handledByServer()) {
Constants.LOG.error("Attempted to send invalid packet {} to server! Class: {} Destination: {} Payload: {}", this.type().id(), this.getClass(), this.destination(), payload.toString());
throw new IllegalStateException("Attempted to send invalid packet " + this.type().id() + " to server!");
}
if (Minecraft.getInstance().getConnection() == null) {
Constants.LOG.error("Attempted to send packet {} before a connection to a server has been established!", this.type().id());
throw new IllegalStateException("Attempted to send packet " + this.type().id() + " before being connected to a server!");
}
Services.NETWORK.sendToServer(payload);
}
}
================================================
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/ContentProvider.java
================================================
package net.darkhax.bookshelf.common.api.registry;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.serialization.MapCodec;
import net.darkhax.bookshelf.common.api.PhysicalSide;
import net.darkhax.bookshelf.common.api.annotation.OnlyFor;
import net.darkhax.bookshelf.common.api.data.conditions.ILoadCondition;
import net.darkhax.bookshelf.common.api.registry.adapters.GameRegistryAdapter;
import net.darkhax.bookshelf.common.api.registry.adapters.GenericRegistryAdapter;
import net.darkhax.bookshelf.common.impl.registry.adapter.BlockEntityRendererAdapter;
import net.darkhax.bookshelf.common.impl.registry.adapter.BlockRegistryAdapter;
import net.darkhax.bookshelf.common.impl.registry.adapter.BlockRenderTypeAdapter;
import net.darkhax.bookshelf.common.impl.registry.adapter.CommandArgumentAdapter;
import net.darkhax.bookshelf.common.impl.registry.a
gitextract_et8g_e68/ ├── .gitattributes ├── .gitignore ├── Jenkinsfile ├── LICENSE ├── README.md ├── build.gradle ├── buildSrc/ │ ├── build.gradle │ └── src/ │ └── main/ │ └── groovy/ │ ├── build-number.gradle │ ├── git-changelog.gradle │ ├── minify-json.gradle │ ├── multiloader-common.gradle │ ├── multiloader-loader.gradle │ ├── patreon.gradle │ ├── project_validation.gradle │ ├── readme-update.gradle │ ├── secret-loader.gradle │ └── version-checker.gradle ├── common/ │ ├── build.gradle │ └── src/ │ └── main/ │ ├── java/ │ │ └── net/ │ │ └── darkhax/ │ │ └── bookshelf/ │ │ └── common/ │ │ ├── api/ │ │ │ ├── ModEntry.java │ │ │ ├── PhysicalSide.java │ │ │ ├── annotation/ │ │ │ │ ├── InternalUse.java │ │ │ │ └── OnlyFor.java │ │ │ ├── block/ │ │ │ │ └── IBlockHooks.java │ │ │ ├── commands/ │ │ │ │ ├── IEnumCommand.java │ │ │ │ ├── PermissionLevel.java │ │ │ │ └── args/ │ │ │ │ ├── ArgumentSerializer.java │ │ │ │ ├── FontArgument.java │ │ │ │ ├── SingletonArgumentInfo.java │ │ │ │ └── TagArgument.java │ │ │ ├── data/ │ │ │ │ ├── BookshelfTags.java │ │ │ │ ├── ISidedRecipeManager.java │ │ │ │ ├── codecs/ │ │ │ │ │ ├── EnumStreamCodec.java │ │ │ │ │ ├── map/ │ │ │ │ │ │ ├── MapCodecHelper.java │ │ │ │ │ │ ├── MapCodecs.java │ │ │ │ │ │ └── RegistryMapCodecHelper.java │ │ │ │ │ └── stream/ │ │ │ │ │ └── StreamCodecs.java │ │ │ │ ├── conditions/ │ │ │ │ │ ├── ConditionType.java │ │ │ │ │ ├── ILoadCondition.java │ │ │ │ │ └── LoadConditions.java │ │ │ │ ├── enchantment/ │ │ │ │ │ └── EnchantmentLevel.java │ │ │ │ ├── ingredient/ │ │ │ │ │ └── IngredientLogic.java │ │ │ │ └── loot/ │ │ │ │ ├── PoolTarget.java │ │ │ │ └── modifiers/ │ │ │ │ └── LootPoolAddition.java │ │ │ ├── entity/ │ │ │ │ └── villager/ │ │ │ │ ├── MerchantTier.java │ │ │ │ └── trades/ │ │ │ │ ├── VillagerBuys.java │ │ │ │ ├── VillagerOffers.java │ │ │ │ └── VillagerSells.java │ │ │ ├── function/ │ │ │ │ ├── CachedSupplier.java │ │ │ │ ├── QuadConsumer.java │ │ │ │ ├── ReloadableCache.java │ │ │ │ ├── SidedReloadableCache.java │ │ │ │ ├── TriConsumer.java │ │ │ │ └── TriFunction.java │ │ │ ├── item/ │ │ │ │ └── IItemHooks.java │ │ │ ├── loot/ │ │ │ │ ├── LootPoolEntryDescriber.java │ │ │ │ └── LootPoolEntryDescriptions.java │ │ │ ├── menu/ │ │ │ │ ├── data/ │ │ │ │ │ └── BlockPosData.java │ │ │ │ └── slot/ │ │ │ │ ├── InputSlot.java │ │ │ │ └── OutputSlot.java │ │ │ ├── network/ │ │ │ │ ├── AbstractPacket.java │ │ │ │ ├── Destination.java │ │ │ │ ├── INetworkHandler.java │ │ │ │ └── IPacket.java │ │ │ ├── registry/ │ │ │ │ ├── ContentProvider.java │ │ │ │ ├── RegistrationContext.java │ │ │ │ ├── RegistryReference.java │ │ │ │ └── adapters/ │ │ │ │ ├── GameRegistryAdapter.java │ │ │ │ ├── GenericRegistryAdapter.java │ │ │ │ └── RegistryAdapter.java │ │ │ ├── service/ │ │ │ │ └── Services.java │ │ │ ├── text/ │ │ │ │ ├── font/ │ │ │ │ │ ├── BuiltinFonts.java │ │ │ │ │ └── IFontEntry.java │ │ │ │ ├── format/ │ │ │ │ │ ├── IPropertyFormat.java │ │ │ │ │ └── PropertyFormat.java │ │ │ │ └── unit/ │ │ │ │ ├── IUnit.java │ │ │ │ └── Units.java │ │ │ └── util/ │ │ │ ├── CommandHelper.java │ │ │ ├── DataHelper.java │ │ │ ├── ExperienceHelper.java │ │ │ ├── FunctionHelper.java │ │ │ ├── IGameplayHelper.java │ │ │ ├── IPlatformHelper.java │ │ │ ├── IRenderHelper.java │ │ │ ├── MathsHelper.java │ │ │ ├── TextHelper.java │ │ │ └── TickAccumulator.java │ │ ├── impl/ │ │ │ ├── BookshelfContent.java │ │ │ ├── BookshelfMod.java │ │ │ ├── Constants.java │ │ │ ├── DebugContentProvider.java │ │ │ ├── command/ │ │ │ │ ├── BlockTagToItemTagCommand.java │ │ │ │ ├── DebugCommands.java │ │ │ │ ├── EnchantCommand.java │ │ │ │ ├── FontCommand.java │ │ │ │ ├── HandCommand.java │ │ │ │ ├── RenameCommand.java │ │ │ │ ├── StructureCommand.java │ │ │ │ └── TranslateCommand.java │ │ │ ├── data/ │ │ │ │ ├── conditions/ │ │ │ │ │ ├── And.java │ │ │ │ │ ├── ModLoaded.java │ │ │ │ │ ├── Not.java │ │ │ │ │ ├── OnPlatform.java │ │ │ │ │ ├── Or.java │ │ │ │ │ └── RegistryContains.java │ │ │ │ ├── criterion/ │ │ │ │ │ ├── item/ │ │ │ │ │ │ └── NamespaceItemPredicate.java │ │ │ │ │ └── trigger/ │ │ │ │ │ └── AdvancementTrigger.java │ │ │ │ ├── ingredient/ │ │ │ │ │ ├── AllOfIngredient.java │ │ │ │ │ ├── BlockTagIngredient.java │ │ │ │ │ ├── EitherIngredient.java │ │ │ │ │ ├── FalseIngredient.java │ │ │ │ │ └── ModIdIngredient.java │ │ │ │ └── loot/ │ │ │ │ ├── entries/ │ │ │ │ │ └── LootItemStack.java │ │ │ │ └── modifiers/ │ │ │ │ ├── FingerprintCodec.java │ │ │ │ ├── ILootPoolHooks.java │ │ │ │ └── LootModificationHandler.java │ │ │ ├── recipe/ │ │ │ │ └── RecipeTypeImpl.java │ │ │ ├── registry/ │ │ │ │ └── adapter/ │ │ │ │ ├── BlockEntityRendererAdapter.java │ │ │ │ ├── BlockRegistryAdapter.java │ │ │ │ ├── BlockRenderTypeAdapter.java │ │ │ │ ├── CommandArgumentAdapter.java │ │ │ │ ├── CreativeModeTabAdapter.java │ │ │ │ ├── IngredientTypeAdapter.java │ │ │ │ ├── LootDescriptionAdapter.java │ │ │ │ ├── LootEntryTypeAdapter.java │ │ │ │ ├── LootPoolAdditionAdapter.java │ │ │ │ ├── MenuScreenAdapter.java │ │ │ │ ├── MenuTypeAdapter.java │ │ │ │ ├── PacketAdapter.java │ │ │ │ ├── PotPatternAdapter.java │ │ │ │ ├── PotionBrewAdapter.java │ │ │ │ ├── RecipeTypeAdapter.java │ │ │ │ ├── SoundEventAdapter.java │ │ │ │ └── VillagerTradeAdapter.java │ │ │ └── resources/ │ │ │ └── ExtendedText.java │ │ └── mixin/ │ │ ├── access/ │ │ │ ├── block/ │ │ │ │ ├── AccessorBannerBlockEntity.java │ │ │ │ ├── AccessorBaseContainerBlockEntity.java │ │ │ │ ├── AccessorBlockEntityRenderers.java │ │ │ │ └── AccessorCropBlock.java │ │ │ ├── client/ │ │ │ │ ├── AccessorFontManager.java │ │ │ │ ├── AccessorItemBlockRenderTypes.java │ │ │ │ ├── AccessorMinecraft.java │ │ │ │ └── gui/ │ │ │ │ └── AccessorAbstractWidget.java │ │ │ ├── entity/ │ │ │ │ └── AccessorEntity.java │ │ │ ├── level/ │ │ │ │ └── AccessorRecipeManager.java │ │ │ ├── loot/ │ │ │ │ ├── AccessorCompositeEntryBase.java │ │ │ │ ├── AccessorDynamicLoot.java │ │ │ │ ├── AccessorLootItem.java │ │ │ │ ├── AccessorLootPool.java │ │ │ │ ├── AccessorLootPoolSingletonContainer.java │ │ │ │ ├── AccessorLootTable.java │ │ │ │ ├── AccessorNestedLootTable.java │ │ │ │ └── AccessorTagEntry.java │ │ │ └── particles/ │ │ │ └── AccessSimpleParticleType.java │ │ └── patch/ │ │ ├── advancement/ │ │ │ └── MixinPlayerAdvancements.java │ │ ├── block/ │ │ │ └── MixinDecoratedPotPatterns.java │ │ ├── client/ │ │ │ └── MixinClientPacketListener.java │ │ ├── entity/ │ │ │ ├── MixinLightningBolt.java │ │ │ └── MixinLivingEntity.java │ │ ├── item/ │ │ │ └── MixinCreativeModeTab.java │ │ ├── level/ │ │ │ ├── MixinRecipeManager.java │ │ │ └── MixinWalkNodeEvaluator.java │ │ ├── locale/ │ │ │ └── MixinClientLanguage.java │ │ ├── loot/ │ │ │ ├── MixinLootDataType.java │ │ │ ├── MixinLootItemKilledByPlayerCondition.java │ │ │ └── MixinLootPool.java │ │ ├── packs/ │ │ │ └── MixinSimpleJsonResourceReloadListener.java │ │ ├── potions/ │ │ │ └── MixinPotionBrewing.java │ │ └── server/ │ │ └── MixinReloadableServerResources.java │ └── resources/ │ ├── META-INF/ │ │ └── services/ │ │ └── net.darkhax.bookshelf.common.api.registry.ContentProvider │ ├── assets/ │ │ └── bookshelf/ │ │ └── lang/ │ │ ├── en_us.json │ │ ├── es_ar.json │ │ ├── ja_jp.json │ │ ├── pt_br.json │ │ └── zh_cn.json │ ├── bookshelf.mixins.json │ ├── data/ │ │ └── bookshelf/ │ │ ├── damage_type/ │ │ │ └── fake_player.json │ │ └── tags/ │ │ ├── damage_type/ │ │ │ └── fake_player.json │ │ └── item/ │ │ └── creative_tab/ │ │ └── minecraft/ │ │ ├── building_blocks.json │ │ ├── colored_blocks.json │ │ ├── combat.json │ │ ├── food_and_drinks.json │ │ ├── functional_blocks.json │ │ ├── ingredients.json │ │ ├── natural_blocks.json │ │ ├── op_blocks.json │ │ ├── redstone_blocks.json │ │ ├── spawn_eggs.json │ │ └── tools_and_utilities.json │ └── pack.mcmeta ├── fabric/ │ ├── build.gradle │ └── src/ │ └── main/ │ ├── java/ │ │ └── net/ │ │ └── darkhax/ │ │ └── bookshelf/ │ │ └── fabric/ │ │ └── impl/ │ │ ├── FabricMod.java │ │ ├── FabricModClient.java │ │ ├── data/ │ │ │ └── FabricIngredient.java │ │ ├── network/ │ │ │ └── FabricNetworkHandler.java │ │ └── util/ │ │ ├── FabricGameplayHelper.java │ │ ├── FabricPlatformHelper.java │ │ ├── FabricRegistryHelper.java │ │ └── FabricRenderHelper.java │ └── resources/ │ ├── META-INF/ │ │ └── services/ │ │ ├── net.darkhax.bookshelf.common.api.network.INetworkHandler │ │ ├── net.darkhax.bookshelf.common.api.util.IGameplayHelper │ │ ├── net.darkhax.bookshelf.common.api.util.IPlatformHelper │ │ └── net.darkhax.bookshelf.common.api.util.IRenderHelper │ ├── bookshelf.fabric.mixins.json │ └── fabric.mod.json ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── neoforge/ │ ├── build.gradle │ └── src/ │ └── main/ │ ├── java/ │ │ └── net/ │ │ └── darkhax/ │ │ └── bookshelf/ │ │ └── neoforge/ │ │ ├── impl/ │ │ │ ├── NeoForgeMod.java │ │ │ ├── data/ │ │ │ │ └── NeoForgeIngredient.java │ │ │ ├── network/ │ │ │ │ └── NeoForgeNetworkHandler.java │ │ │ └── util/ │ │ │ ├── NeoForgeGameplayHelper.java │ │ │ ├── NeoForgePlatformHelper.java │ │ │ ├── NeoForgeRegistryHelper.java │ │ │ └── NeoForgeRenderHelper.java │ │ └── mixin/ │ │ └── access/ │ │ └── gui/ │ │ └── screen/ │ │ └── AccessorMenuScreens.java │ └── resources/ │ ├── META-INF/ │ │ ├── neoforge.mods.toml │ │ └── services/ │ │ ├── net.darkhax.bookshelf.common.api.network.INetworkHandler │ │ ├── net.darkhax.bookshelf.common.api.util.IGameplayHelper │ │ ├── net.darkhax.bookshelf.common.api.util.IPlatformHelper │ │ └── net.darkhax.bookshelf.common.api.util.IRenderHelper │ └── bookshelf.neoforge.mixins.json └── settings.gradle
SYMBOL INDEX (821 symbols across 160 files)
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/PhysicalSide.java
type PhysicalSide (line 6) | public enum PhysicalSide {
method isClient (line 23) | public boolean isClient() {
method isServer (line 33) | public boolean isServer() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/block/IBlockHooks.java
type IBlockHooks (line 12) | public interface IBlockHooks {
method getPathfindingType (line 26) | @Nullable
method onLightningStrike (line 39) | default void onLightningStrike(BlockState state, Level level, BlockPos...
method onLightningStrikeIndirect (line 51) | default void onLightningStrikeIndirect(BlockState state, Level level, ...
method redirectLightningStrike (line 62) | default Direction[] redirectLightningStrike(BlockState state, Level le...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/IEnumCommand.java
type IEnumCommand (line 9) | public interface IEnumCommand extends Command<CommandSourceStack> {
method getCommandName (line 16) | String getCommandName();
method requiredPermissionLevel (line 23) | default PermissionLevel requiredPermissionLevel() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/PermissionLevel.java
type PermissionLevel (line 8) | public enum PermissionLevel implements Predicate<CommandSourceStack> {
method PermissionLevel (line 40) | PermissionLevel(int level) {
method get (line 44) | public int get() {
method test (line 48) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/ArgumentSerializer.java
class ArgumentSerializer (line 16) | public class ArgumentSerializer<T extends ArgumentType<?>, V> implements...
method ArgumentSerializer (line 23) | public ArgumentSerializer(MapCodec<V> codec, StreamCodec<FriendlyByteB...
method serializeToNetwork (line 30) | @Override
method deserializeFromNetwork (line 35) | @NotNull
method serializeToJson (line 41) | @Override
method unpack (line 46) | @NotNull
class ArgTemplate (line 52) | public static class ArgTemplate<T extends ArgumentType<?>, V> implemen...
method ArgTemplate (line 57) | protected ArgTemplate(ArgumentSerializer<T, V> type, V data) {
method instantiate (line 62) | @NotNull
method type (line 68) | @NotNull
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/FontArgument.java
class FontArgument (line 23) | public class FontArgument implements ArgumentType<ResourceLocation> {
method get (line 29) | public static ResourceLocation get(CommandContext<CommandSourceStack> ...
method get (line 33) | public static ResourceLocation get(String argName, CommandContext<Comm...
method argument (line 37) | public static RequiredArgumentBuilder<CommandSourceStack, ResourceLoca...
method argument (line 41) | public static RequiredArgumentBuilder<CommandSourceStack, ResourceLoca...
method parse (line 45) | @Override
method getExamples (line 50) | @Override
method listSuggestions (line 55) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/SingletonArgumentInfo.java
class SingletonArgumentInfo (line 19) | public final class SingletonArgumentInfo<T extends ArgumentType<?>> impl...
method of (line 29) | public static <T extends ArgumentType<?>> SingletonArgumentInfo<T> of(...
method SingletonArgumentInfo (line 35) | private SingletonArgumentInfo(Supplier<T> singletonSupplier) {
method serializeToNetwork (line 39) | @Override
method deserializeFromNetwork (line 44) | @NotNull
method serializeToJson (line 50) | @Override
method unpack (line 55) | @NotNull
class Template (line 66) | public static class Template<T extends ArgumentType<?>> implements Arg...
method Template (line 71) | protected Template(Supplier<T> supplier, ArgumentTypeInfo<T, ?> info) {
method instantiate (line 76) | @NotNull
method type (line 82) | @NotNull
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/TagArgument.java
class TagArgument (line 26) | public class TagArgument<T> implements ArgumentType<TagKey<T>> {
method makeRaw (line 41) | @SuppressWarnings({"rawtypes", "unchecked"})
method TagArgument (line 46) | private TagArgument(CommandBuildContext context, ResourceKey<? extends...
method parse (line 51) | @Override
method listSuggestions (line 57) | @Override
method getExamples (line 62) | @Override
method arg (line 67) | public static <T> TagArgument<T> arg(CommandBuildContext context, Reso...
method get (line 71) | @SuppressWarnings("unchecked")
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/BookshelfTags.java
class BookshelfTags (line 9) | public class BookshelfTags {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/ISidedRecipeManager.java
type ISidedRecipeManager (line 3) | public interface ISidedRecipeManager {
method bookshelf$setLogicalClient (line 5) | void bookshelf$setLogicalClient();
method bookshelf$setLogicalServer (line 7) | void bookshelf$setLogicalServer();
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/EnumStreamCodec.java
class EnumStreamCodec (line 7) | public class EnumStreamCodec<T extends Enum<T>> implements StreamCodec<F...
method EnumStreamCodec (line 11) | public EnumStreamCodec(Class<T> clazz) {
method decode (line 15) | @NotNull
method encode (line 21) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/MapCodecHelper.java
class MapCodecHelper (line 22) | public class MapCodecHelper<T> {
method MapCodecHelper (line 35) | @SafeVarargs
method get (line 51) | public Codec<T> get() {
method get (line 64) | public <O> RecordCodecBuilder<O, T> get(String fieldName, Function<O, ...
method get (line 79) | public <O> RecordCodecBuilder<O, T> get(String fieldName, Function<O, ...
method getArray (line 90) | public Codec<T[]> getArray() {
method getArray (line 104) | public <O> RecordCodecBuilder<O, T[]> getArray(String fieldName, Funct...
method getArray (line 119) | public <O> RecordCodecBuilder<O, T[]> getArray(String fieldName, Funct...
method getList (line 130) | public Codec<List<T>> getList() {
method getList (line 144) | public <O> RecordCodecBuilder<O, List<T>> getList(String fieldName, Fu...
method getList (line 159) | public <O> RecordCodecBuilder<O, List<T>> getList(String fieldName, Fu...
method getList (line 174) | public <O> RecordCodecBuilder<O, List<T>> getList(String fieldName, Fu...
method getSet (line 185) | public Codec<Set<T>> getSet() {
method getSet (line 199) | public <O> RecordCodecBuilder<O, Set<T>> getSet(String fieldName, Func...
method getSet (line 214) | public <O> RecordCodecBuilder<O, Set<T>> getSet(String fieldName, Func...
method getSet (line 229) | public <O> RecordCodecBuilder<O, Set<T>> getSet(String fieldName, Func...
method getOptional (line 240) | public MapCodec<Optional<T>> getOptional(String fieldName) {
method getOptional (line 253) | public <O> RecordCodecBuilder<O, Optional<T>> getOptional(String field...
method getOptional (line 268) | public <O> RecordCodecBuilder<O, Optional<T>> getOptional(String field...
method getNullable (line 279) | public MapCodec<T> getNullable(String fieldName) {
method getNullable (line 292) | public <O> RecordCodecBuilder<O, T> getNullable(String fieldName, Func...
method getWeighted (line 302) | public Codec<WeightedEntry.Wrapper<T>> getWeighted() {
method getWeighted (line 315) | public <O> RecordCodecBuilder<O, WeightedEntry.Wrapper<T>> getWeighted...
method getWeightedList (line 325) | public Codec<SimpleWeightedRandomList<T>> getWeightedList() {
method getWeightedList (line 338) | public <O> RecordCodecBuilder<O, SimpleWeightedRandomList<T>> getWeigh...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/MapCodecs.java
class MapCodecs (line 132) | @SuppressWarnings("unused")
method flexibleList (line 265) | public static <T> Codec<List<T>> flexibleList(Codec<T> codec) {
method flexibleSet (line 277) | public static <T> Codec<Set<T>> flexibleSet(Codec<T> codec) {
method flexibleArray (line 291) | public static <T> Codec<T[]> flexibleArray(Codec<T> codec, IntFunction...
method fallback (line 306) | public static <T> MapCodec<T> fallback(Codec<T> codec, String name, Su...
method optional (line 322) | public static <T> MapCodec<Optional<T>> optional(Codec<T> codec, Strin...
method nullable (line 335) | public static <T> MapCodec<T> nullable(Codec<T> codec, String fieldNam...
method fallback (line 352) | public static <T> MapCodec<T> fallback(Codec<T> codec, String name, Su...
method getEnumsByName (line 360) | private static <T extends Enum<T>> Map<String, T> getEnumsByName(Class...
method enumerable (line 389) | public static <T extends Enum<T>> Codec<T> enumerable(Class<T> enumCla...
method decodeBlockState (line 412) | @SuppressWarnings({"rawtypes", "unchecked"})
method encodeBlockState (line 461) | @SuppressWarnings({"rawtypes", "unchecked"})
method xor (line 483) | public static <T> Codec<T> xor(Codec<T> first, Codec<T> second) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/RegistryMapCodecHelper.java
class RegistryMapCodecHelper (line 10) | public class RegistryMapCodecHelper<T> extends MapCodecHelper<Holder<T>> {
method RegistryMapCodecHelper (line 14) | private RegistryMapCodecHelper(Codec<Holder<T>> holderCodec, ResourceK...
method tag (line 19) | public MapCodecHelper<TagKey<T>> tag() {
method create (line 30) | public static <T> RegistryMapCodecHelper<T> create(Registry<T> registr...
method create (line 42) | public static <T> RegistryMapCodecHelper<T> create(ResourceKey<Registr...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/stream/StreamCodecs.java
class StreamCodecs (line 14) | public class StreamCodecs {
method list (line 26) | public static <B extends ByteBuf, V> StreamCodec<B, List<V>> list(Stre...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/ILoadCondition.java
type ILoadCondition (line 7) | public interface ILoadCondition {
method allowLoading (line 14) | boolean allowLoading();
method getType (line 21) | ConditionType getType();
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/LoadConditions.java
class LoadConditions (line 17) | public class LoadConditions {
method getType (line 25) | @Nullable
method register (line 30) | public static <T extends ILoadCondition> ConditionType register(Resour...
method getConditions (line 45) | public static ILoadCondition[] getConditions(JsonElement conditionData) {
method canLoad (line 56) | public static boolean canLoad(JsonObject rawJson) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/enchantment/EnchantmentLevel.java
type EnchantmentLevel (line 15) | public enum EnchantmentLevel {
method EnchantmentLevel (line 70) | EnchantmentLevel(ToIntBiFunction<TagKey<Enchantment>, ItemEnchantments...
method get (line 81) | public int get(TagKey<Enchantment> enchType, ItemStack stack) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/ingredient/IngredientLogic.java
type IngredientLogic (line 10) | public interface IngredientLogic<T extends IngredientLogic<T>> {
method test (line 12) | boolean test(ItemStack stack);
method getAllMatchingStacks (line 14) | default List<ItemStack> getAllMatchingStacks() {
method requiresTesting (line 25) | default boolean requiresTesting() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/data/loot/PoolTarget.java
method of (line 46) | public static PoolTarget of(ResourceKey<LootTable> table, int index, int...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/MerchantTier.java
type MerchantTier (line 3) | public enum MerchantTier {
method MerchantTier (line 13) | MerchantTier(int requiredExp) {
method getRequiredExp (line 18) | public int getRequiredExp() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerBuys.java
method getOffer (line 25) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerOffers.java
method getOffer (line 22) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerSells.java
method getOffer (line 25) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/CachedSupplier.java
class CachedSupplier (line 18) | public class CachedSupplier<T> implements Supplier<T> {
method CachedSupplier (line 36) | protected CachedSupplier(Supplier<T> delegate) {
method get (line 40) | @Override
method invalidate (line 52) | public void invalidate() {
method isCached (line 62) | public boolean isCached() {
method ifCached (line 72) | public void ifCached(Consumer<T> consumer) {
method ifPresent (line 84) | public void ifPresent(Consumer<T> consumer) {
method apply (line 96) | public void apply(Consumer<T> consumer) {
method cast (line 103) | public <X> CachedSupplier<X> cast() {
method singleton (line 114) | public static <T> CachedSupplier<T> singleton(T singleton) {
method cache (line 126) | public static <T> CachedSupplier<T> cache(Supplier<T> delegate) {
method of (line 130) | @SuppressWarnings("unchecked")
method of (line 142) | public static <T> CachedSupplier<T> of(Registry<T> registry, String na...
method of (line 146) | public static <T> CachedSupplier<T> of(Registry<T> registry, ResourceL...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/QuadConsumer.java
type QuadConsumer (line 13) | @FunctionalInterface
method accept (line 24) | void accept(P1 p1, P2 p2, P3 p3, P4 p4);
method andThen (line 32) | default QuadConsumer<P1, P2, P3, P4> andThen(QuadConsumer<P1, P2, P3, ...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/ReloadableCache.java
class ReloadableCache (line 31) | public class ReloadableCache<T> implements Function<Level, T> {
method ReloadableCache (line 57) | protected ReloadableCache(Function<Level, T> delegate) {
method apply (line 61) | @Nullable
method invalidate (line 76) | public void invalidate() {
method isCached (line 87) | public boolean isCached() {
method apply (line 98) | public void apply(Level level, Consumer<T> consumer) {
method ifPresent (line 108) | public void ifPresent(Level level, Consumer<T> consumer) {
method map (line 124) | @Nullable
method of (line 137) | public static <T> ReloadableCache<T> of(Supplier<T> supplier) {
method of (line 148) | public static <T> ReloadableCache<T> of(Function<Level, T> delegate) {
method of (line 160) | public static <T> ReloadableCache<T> of(ResourceKey<? extends Registry...
method of (line 171) | @SuppressWarnings("unchecked")
method recipes (line 190) | @SuppressWarnings("unchecked")
method entity (line 208) | public static ReloadableCache<Entity> entity(CompoundTag entityData) {
method living (line 228) | public static ReloadableCache<LivingEntity> living(CompoundTag entityD...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/SidedReloadableCache.java
class SidedReloadableCache (line 18) | public class SidedReloadableCache<T> implements Function<Level, T> {
method SidedReloadableCache (line 23) | public SidedReloadableCache(ReloadableCache<T> client, ReloadableCache...
method getCache (line 28) | public ReloadableCache<T> getCache(Level level) {
method apply (line 32) | @Nullable
method invalidate (line 38) | public void invalidate(Level level) {
method isCached (line 42) | public boolean isCached(Level level) {
method apply (line 46) | public void apply(Level level, Consumer<T> consumer) {
method ifPresent (line 50) | public void ifPresent(Level level, Consumer<T> consumer) {
method map (line 54) | @Nullable
method of (line 59) | public static <T> SidedReloadableCache<T> of(Function<Level, T> cacheF...
method recipes (line 63) | @SuppressWarnings("unchecked")
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/TriConsumer.java
type TriConsumer (line 5) | @FunctionalInterface
method accept (line 8) | void accept(P1 p1, P2 p2, P3 p3);
method andThen (line 10) | default TriConsumer<P1, P2, P3> andThen(TriConsumer<P1, P2, P3> after) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/function/TriFunction.java
type TriFunction (line 6) | @FunctionalInterface
method apply (line 9) | R apply(P1 p1, P2 p2, P3 p3);
method andThen (line 11) | default TriFunction<P1, P2, P3, R> andThen(Function<? super R, ? exten...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/item/IItemHooks.java
type IItemHooks (line 8) | public interface IItemHooks {
method addCreativeTabForms (line 10) | default void addCreativeTabForms(CreativeModeTab tab, Consumer<ItemSta...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/loot/LootPoolEntryDescriber.java
type LootPoolEntryDescriber (line 13) | @FunctionalInterface
method getPotentialDrops (line 23) | void getPotentialDrops(@NotNull RegistryAccess registries, @NotNull Lo...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/loot/LootPoolEntryDescriptions.java
class LootPoolEntryDescriptions (line 46) | public class LootPoolEntryDescriptions {
method bootstrap (line 110) | private static void bootstrap() {
method getUniqueItems (line 125) | public static List<ItemStack> getUniqueItems(@NotNull RegistryAccess r...
method getPotentialItems (line 138) | public static void getPotentialItems(@NotNull RegistryAccess registrie...
method getPotentialItems (line 152) | public static void getPotentialItems(@NotNull RegistryAccess registrie...
method getPotentialItems (line 169) | public static void getPotentialItems(@NotNull RegistryAccess registrie...
method getPotentialItems (line 182) | public static void getPotentialItems(@NotNull RegistryAccess registrie...
method addStacking (line 199) | private static void addStacking(List<ItemStack> items, ItemStack toAdd) {
method getTagItems (line 208) | private static void getTagItems(TagKey<Item> tag, Consumer<ItemStack> ...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/menu/data/BlockPosData.java
class BlockPosData (line 12) | public class BlockPosData implements ContainerData {
method BlockPosData (line 17) | public BlockPosData(BlockPos pos) {
method BlockPosData (line 21) | public BlockPosData(BlockPos pos, boolean mutable) {
method get (line 26) | @Override
method set (line 31) | @Override
method getCount (line 38) | @Override
method getPos (line 48) | public BlockPos getPos() {
method readPos (line 59) | public static BlockPos readPos(ContainerData data) {
method toArray (line 66) | private static int[] toArray(ContainerData containerData) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/menu/slot/InputSlot.java
class InputSlot (line 17) | public class InputSlot extends Slot {
method InputSlot (line 22) | public InputSlot(Container container, int slot, int x, int y, Resource...
method InputSlot (line 26) | public InputSlot(Container container, int slot, int x, int y, Resource...
method getMaxStackSize (line 32) | @Override
method getNoItemIcon (line 37) | @Nullable
method mayPlace (line 43) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/menu/slot/OutputSlot.java
class OutputSlot (line 15) | public class OutputSlot extends Slot {
method OutputSlot (line 20) | public OutputSlot(Container potContainer, int slot, int x, int y) {
method OutputSlot (line 24) | public OutputSlot(Container potContainer, int slot, int x, int y, @Nul...
method mayPlace (line 29) | @Override
method onTake (line 34) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/AbstractPacket.java
class AbstractPacket (line 13) | public abstract class AbstractPacket<T extends CustomPacketPayload> impl...
method AbstractPacket (line 36) | public AbstractPacket(ResourceLocation id, StreamCodec<RegistryFriendl...
method AbstractPacket (line 47) | public AbstractPacket(ResourceLocation id, StreamCodec<RegistryFriendl...
method type (line 53) | @Override
method streamCodec (line 58) | @Override
method destination (line 63) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/Destination.java
type Destination (line 6) | public enum Destination {
method handledByServer (line 32) | public boolean handledByServer() {
method handledByClient (line 41) | public boolean handledByClient() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/INetworkHandler.java
type INetworkHandler (line 11) | public interface INetworkHandler {
method register (line 19) | <T extends CustomPacketPayload> void register(IPacket<T> packet);
method sendToServer (line 27) | <T extends CustomPacketPayload> void sendToServer(T payload);
method sendToPlayer (line 36) | <T extends CustomPacketPayload> void sendToPlayer(ServerPlayer recipie...
method canSendPacket (line 45) | default boolean canSendPacket(ServerPlayer recipient, CustomPacketPayl...
method canSendPacket (line 56) | default boolean canSendPacket(ServerPlayer recipient, IPacket<?> packe...
method canSendPacket (line 67) | boolean canSendPacket(ServerPlayer recipient, ResourceLocation payload...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/network/IPacket.java
type IPacket (line 23) | public interface IPacket<T extends CustomPacketPayload> {
method type (line 30) | CustomPacketPayload.Type<T> type();
method streamCodec (line 37) | StreamCodec<RegistryFriendlyByteBuf, T> streamCodec();
method destination (line 44) | Destination destination();
method handle (line 54) | void handle(@Nullable ServerPlayer sender, boolean isServer, T payload);
method toPlayer (line 62) | default void toPlayer(ServerPlayer recipient, T payload) {
method toAllPlayers (line 76) | default void toAllPlayers(ServerLevel level, T payload) {
method toAllPlayers (line 86) | default void toAllPlayers(MinecraftServer server, T payload) {
method toAllPlayers (line 96) | default void toAllPlayers(PlayerList playerList, T payload) {
method toServer (line 107) | @OnlyFor(PhysicalSide.CLIENT)
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/ContentProvider.java
type ContentProvider (line 54) | public interface ContentProvider {
method defineAttributes (line 61) | default void defineAttributes(GameRegistryAdapter<Attribute> registry) {
method defineBlocks (line 69) | default void defineBlocks(BlockRegistryAdapter registry) {
method defineBlockEntities (line 77) | default void defineBlockEntities(GameRegistryAdapter<BlockEntityType<?...
method defineItems (line 85) | default void defineItems(GameRegistryAdapter<Item> registry) {
method defineRecipeTypes (line 93) | default void defineRecipeTypes(RecipeTypeAdapter registry) {
method defineCreativeTabs (line 101) | default void defineCreativeTabs(CreativeModeTabAdapter registry) {
method defineCommandArguments (line 109) | default void defineCommandArguments(CommandArgumentAdapter registry) {
method defineCommands (line 120) | default void defineCommands(CommandDispatcher<CommandSourceStack> disp...
method defineIngredientTypes (line 128) | default void defineIngredientTypes(IngredientTypeAdapter registry) {
method defineTrades (line 136) | default void defineTrades(VillagerTradeAdapter registry) {
method defineMobEffects (line 144) | default void defineMobEffects(GameRegistryAdapter<MobEffect> registry) {
method defineCriteriaTriggers (line 152) | default void defineCriteriaTriggers(GameRegistryAdapter<CriterionTrigg...
method defineItemSubPredicates (line 160) | default void defineItemSubPredicates(GameRegistryAdapter<ItemSubPredic...
method defineEntities (line 168) | default void defineEntities(GameRegistryAdapter<EntityType<?>> registr...
method defineCatVariants (line 176) | default void defineCatVariants(GameRegistryAdapter<CatVariant> registr...
method definePotions (line 184) | default void definePotions(GameRegistryAdapter<Potion> registry) {
method defineBrews (line 192) | default void defineBrews(PotionBrewing.Builder registry) {
method definePotPatterns (line 200) | default void definePotPatterns(PotPatternAdapter registry) {
method defineItemComponents (line 208) | default void defineItemComponents(GameRegistryAdapter<DataComponentTyp...
method defineEnchantmentComponents (line 216) | default void defineEnchantmentComponents(GameRegistryAdapter<DataCompo...
method defineLootConditions (line 224) | default void defineLootConditions(GameRegistryAdapter<LootItemConditio...
method defineLootFunctions (line 232) | default void defineLootFunctions(GameRegistryAdapter<LootItemFunctionT...
method defineRecipeSerializers (line 240) | default void defineRecipeSerializers(GameRegistryAdapter<RecipeSeriali...
method defineLootEntryTypes (line 248) | default void defineLootEntryTypes(LootEntryTypeAdapter registry) {
method defineLootPoolAdditions (line 257) | default void defineLootPoolAdditions(LootPoolAdditionAdapter registry) {
method defineLootDescriptions (line 265) | default void defineLootDescriptions(LootDescriptionAdapter registry) {
method defineLoadConditions (line 273) | default void defineLoadConditions(GenericRegistryAdapter<MapCodec<? ex...
method defineMenuType (line 281) | default void defineMenuType(MenuTypeAdapter registry) {
method definePackets (line 289) | default void definePackets(PacketAdapter registry) {
method defineSounds (line 297) | default void defineSounds(SoundEventAdapter registry) {
method defineMenuScreens (line 306) | @OnlyFor(PhysicalSide.CLIENT)
method defineBlockRenderTypes (line 315) | @OnlyFor(PhysicalSide.CLIENT)
method defineBlockRenderers (line 324) | @OnlyFor(PhysicalSide.CLIENT)
method namespace (line 334) | String namespace();
method canLoad (line 345) | default boolean canLoad() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/RegistrationContext.java
class RegistrationContext (line 18) | public final class RegistrationContext {
method RegistrationContext (line 26) | public RegistrationContext(String namespace) {
method namespace (line 35) | public String namespace() {
method addPlaceableBlock (line 46) | public void addPlaceableBlock(RegistryReference<ResourceKey<Block>, Bl...
method getPlaceableBlocks (line 55) | public Map<RegistryReference<ResourceKey<Block>, Block>, Function<Bloc...
method addPotPatternItem (line 65) | public void addPotPatternItem(Item item, ResourceKey<DecoratedPotPatte...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/RegistryReference.java
method location (line 26) | public static <V> RegistryReference<ResourceLocation, V> location(Resour...
method resource (line 37) | public static <V> RegistryReference<ResourceKey<V>, V> resource(Resource...
method resource (line 50) | public static <V> RegistryReference<ResourceKey<V>, V> resource(Resource...
method resource (line 63) | public static <V> RegistryReference<ResourceKey<V>, V> resource(Registry...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/adapters/GameRegistryAdapter.java
class GameRegistryAdapter (line 17) | public class GameRegistryAdapter<V> implements RegistryAdapter<ResourceK...
method GameRegistryAdapter (line 34) | public GameRegistryAdapter(RegistrationContext context, ResourceKey<Re...
method add (line 40) | @Override
method id (line 53) | public final ResourceLocation id(String key) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/adapters/GenericRegistryAdapter.java
class GenericRegistryAdapter (line 16) | public class GenericRegistryAdapter<V> implements RegistryAdapter<Resour...
method GenericRegistryAdapter (line 28) | public GenericRegistryAdapter(RegistrationContext context, BiConsumer<...
method add (line 40) | public RegistryReference<ResourceLocation, V> add(ResourceLocation id,...
method add (line 53) | public RegistryReference<ResourceLocation, V> add(ResourceLocation id,...
method add (line 57) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/registry/adapters/RegistryAdapter.java
type RegistryAdapter (line 13) | public interface RegistryAdapter<K, V> {
method add (line 22) | default RegistryReference<K, V> add(String key, V value) {
method add (line 33) | RegistryReference<K, V> add(String key, Supplier<V> value);
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/service/Services.java
class Services (line 22) | public class Services {
method load (line 29) | public static <T> T load(Class<T> clazz) {
method loadMany (line 35) | public static <T> List<T> loadMany(Class<T> clazz) {
method findServices (line 48) | public static List<String> findServices(String name) throws IOException {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/text/font/BuiltinFonts.java
type BuiltinFonts (line 11) | public enum BuiltinFonts implements IFontEntry {
method BuiltinFonts (line 38) | BuiltinFonts(String path) {
method BuiltinFonts (line 42) | BuiltinFonts(ResourceLocation fontID) {
method identifier (line 46) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/text/font/IFontEntry.java
type IFontEntry (line 7) | public interface IFontEntry {
method identifier (line 14) | ResourceLocation identifier();
method displayName (line 21) | default MutableComponent displayName() {
method description (line 30) | default MutableComponent description() {
method preview (line 39) | default MutableComponent preview() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/text/format/IPropertyFormat.java
type IPropertyFormat (line 8) | public interface IPropertyFormat {
method formatKey (line 15) | ResourceLocation formatKey();
method format (line 24) | default MutableComponent format(Component property, Component value) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/text/format/PropertyFormat.java
type PropertyFormat (line 9) | public enum PropertyFormat implements IPropertyFormat {
method PropertyFormat (line 38) | PropertyFormat(String key) {
method formatKey (line 42) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/text/unit/IUnit.java
type IUnit (line 8) | public interface IUnit {
method unitKey (line 15) | ResourceLocation unitKey();
method unitName (line 22) | default MutableComponent unitName() {
method plural (line 31) | default MutableComponent plural() {
method abbreviated (line 40) | default MutableComponent abbreviated() {
method format (line 50) | default MutableComponent format(int amount) {
method format (line 61) | default MutableComponent format(int amount, PropertyFormat format) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/text/unit/Units.java
type Units (line 9) | public enum Units implements IUnit {
method Units (line 24) | Units(String key) {
method unitKey (line 28) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/CommandHelper.java
class CommandHelper (line 17) | public class CommandHelper {
method buildFromEnum (line 27) | public static <T extends Enum<T> & IEnumCommand> LiteralArgumentBuilde...
method buildFromEnum (line 41) | public static <T extends Enum<T> & IEnumCommand> void buildFromEnum(Ar...
method getLowestLevel (line 59) | public static <T extends Enum<T> & IEnumCommand> PermissionLevel getLo...
method hasArgument (line 75) | @Deprecated
method hasArgument (line 80) | public static <T, C> boolean hasArgument(String argument, CommandConte...
method getArgument (line 89) | public static <T, C> T getArgument(String argument, CommandContext<C> ...
method getEntity (line 93) | public static Entity getEntity(String argName, CommandContext<CommandS...
method getEntityOrSender (line 97) | public static Entity getEntityOrSender(String argName, CommandContext<...
method getBooleanArg (line 101) | public static boolean getBooleanArg(String argName, CommandContext<Com...
method getBooleanArg (line 105) | public static boolean getBooleanArg(String argName, CommandContext<Com...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/DataHelper.java
class DataHelper (line 23) | public class DataHelper {
method getTagOrEmpty (line 25) | public static <T> HolderSet<T> getTagOrEmpty(@Nullable HolderLookup.Pr...
method subList (line 44) | public static ListTag subList(ListTag list, int from, int to) {
method containerSubList (line 65) | public static ListTag containerSubList(ListTag list, Predicate<Integer...
method optionalStream (line 86) | public static <B extends ByteBuf, V> StreamCodec<B, Optional<V>> optio...
method recipeSerializer (line 109) | public static <T extends Recipe<?>> RecipeSerializer<T> recipeSerializ...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/ExperienceHelper.java
class ExperienceHelper (line 5) | public final class ExperienceHelper {
method chargeExperiencePoints (line 15) | public static boolean chargeExperiencePoints(Player player, int cost) {
method getExperiencePoints (line 52) | public static int getExperiencePoints(Player player) {
method getPointForLevel (line 70) | public static int getPointForLevel(int level) {
method getPointsForLevel (line 101) | public static int getPointsForLevel(int startingLevel, int targetLevel) {
method getTotalPointsForLevel (line 135) | public static int getTotalPointsForLevel(int level) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/FunctionHelper.java
class FunctionHelper (line 9) | public class FunctionHelper {
method test (line 19) | public static <T> boolean test(Optional<T> input, Predicate<T> test) {
method unpack (line 30) | public static <T> T unpack(Either<T, T> either) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/IGameplayHelper.java
type IGameplayHelper (line 23) | public interface IGameplayHelper {
method getCraftingRemainder (line 34) | default ItemStack getCraftingRemainder(ItemStack input) {
method inventoryInsert (line 56) | default ItemStack inventoryInsert(ServerLevel level, BlockPos pos, Dir...
method getContainer (line 72) | @Nullable
method addItem (line 94) | default ItemStack addItem(ItemStack stack, NonNullList<ItemStack> inve...
method blockEntityBuilder (line 123) | <T extends BlockEntity> BlockEntityType.Builder<T> blockEntityBuilder(...
method dropRemainders (line 132) | default void dropRemainders(Level level, BlockPos pos, ItemStack old) {
method tabBuilder (line 141) | CreativeModeTab.Builder tabBuilder();
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/IPlatformHelper.java
type IPlatformHelper (line 13) | public interface IPlatformHelper {
method getGamePath (line 20) | Path getGamePath();
method getGameDirectory (line 27) | default File getGameDirectory() {
method getConfigPath (line 36) | Path getConfigPath();
method getConfigDirectory (line 43) | default File getConfigDirectory() {
method getModsPath (line 52) | Path getModsPath();
method getModsDirectory (line 59) | default File getModsDirectory() {
method isModLoaded (line 69) | boolean isModLoaded(String modId);
method isDevelopmentEnvironment (line 76) | boolean isDevelopmentEnvironment();
method getPhysicalSide (line 83) | PhysicalSide getPhysicalSide();
method isPhysicalClient (line 90) | default boolean isPhysicalClient() {
method getLoadedMods (line 99) | Set<ModEntry> getLoadedMods();
method isTestingEnvironment (line 106) | boolean isTestingEnvironment();
method getName (line 113) | String getName();
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/IRenderHelper.java
type IRenderHelper (line 17) | public interface IRenderHelper {
method blockSprite (line 20) | default TextureAtlasSprite blockSprite(ResourceLocation texturePath) {
method renderFluidBox (line 24) | void renderFluidBox(PoseStack pose, FluidState fluidState, Level level...
method unpackARGB (line 26) | default int[] unpackARGB(int color) {
method renderBox (line 30) | default void renderBox(VertexConsumer builder, PoseStack stack, Textur...
method renderBox (line 34) | default void renderBox(VertexConsumer builder, PoseStack stack, Textur...
method renderBox (line 38) | default void renderBox(VertexConsumer builder, Matrix4f pos, TextureAt...
method renderFace (line 47) | default void renderFace(VertexConsumer builder, Matrix4f pos, TextureA...
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/MathsHelper.java
class MathsHelper (line 20) | public class MathsHelper {
method inRange (line 45) | public static boolean inRange(double min, double max, double value) {
method distance (line 56) | public static double distance(Vec3 first, Vec3 second) {
method round (line 70) | public static double round(double value, int places) {
method nextInt (line 83) | public static int nextInt(Random rng, int min, int max) {
method nextInt (line 96) | public static int nextInt(RandomSource rng, int min, int max) {
method percentChance (line 106) | public static boolean percentChance(double chance) {
method average (line 116) | public static float average(int... values) {
method percentage (line 127) | public static float percentage(int value, int total) {
method pixelSize (line 138) | public static double pixelSize(int pixels) {
method boundsForPixels (line 153) | public static AABB boundsForPixels(int minX, int minY, int minZ, int m...
method createHorizontalShapes (line 168) | public static Map<Direction, VoxelShape> createHorizontalShapes(double...
method rotateShape (line 188) | public static VoxelShape rotateShape(Direction facing, double x1, doub...
method randomOffsetHorizontal (line 207) | public static BlockPos randomOffsetHorizontal(BlockPos startPos, Rando...
method randomOffset (line 221) | public static BlockPos randomOffset(BlockPos startPos, RandomSource rn...
method encodeBytesToInt (line 237) | public static int[] encodeBytesToInt(byte[] bytes) {
method decodeBytesFromInt (line 262) | public static byte[] decodeBytesFromInt(int[] data) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/TextHelper.java
class TextHelper (line 37) | public class TextHelper {
method fromResourceLocation (line 48) | public static MutableComponent fromResourceLocation(@Nullable String p...
method formatDuration (line 67) | public static MutableComponent formatDuration(int ticks) {
method formatDuration (line 80) | public static MutableComponent formatDuration(int ticks, Level level) {
method formatDuration (line 93) | public static MutableComponent formatDuration(int ticks, boolean inclu...
method formatDuration (line 105) | public static MutableComponent formatDuration(int ticks, boolean showT...
method withHover (line 120) | public static MutableComponent withHover(Component base, Component hov...
method withHover (line 131) | public static MutableComponent withHover(Component base, Entity hover) {
method withHover (line 142) | public static MutableComponent withHover(Component base, ItemStack hov...
method withHover (line 153) | public static MutableComponent withHover(Component base, HoverEvent ho...
method hoverEvent (line 164) | public static HoverEvent hoverEvent(Entity entity) {
method mutable (line 178) | public static MutableComponent mutable(Component component) {
method applyFont (line 189) | public static Component applyFont(Component text, ResourceLocation fon...
method lookupTranslationWithAlias (line 209) | @Nullable
method lookupTranslationWithAlias (line 229) | @Nullable
method lookupTranslation (line 248) | @Nullable
method lookupTranslation (line 262) | @Nullable
method lookupTranslation (line 277) | @Nullable
method copyText (line 292) | public static MutableComponent copyText(String text) {
method setCopyText (line 303) | public static MutableComponent setCopyText(MutableComponent component,...
method join (line 314) | public static MutableComponent join(Component separator, Component... ...
method join (line 325) | public static MutableComponent join(Component separator, Collection<Co...
method joinUnique (line 337) | public static MutableComponent joinUnique(Component separator, Collect...
method addUnique (line 352) | public static boolean addUnique(Collection<Component> components, Comp...
method join (line 369) | public static MutableComponent join(Component separator, Iterator<Comp...
method getPossibleMatches (line 395) | public static Set<String> getPossibleMatches(String input, Iterable<St...
method getPossibleMatches (line 416) | public static Set<String> getPossibleMatches(String input, Iterable<St...
method formatCollection (line 441) | public static <T> String formatCollection(Collection<T> collection) {
method formatCollection (line 455) | public static <T> String formatCollection(Collection<T> collection, Fu...
method getRegisteredFonts (line 459) | @OnlyFor(PhysicalSide.CLIENT)
method getTagName (line 479) | public static String getTagName(TagKey<?> tag) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/api/util/TickAccumulator.java
class TickAccumulator (line 10) | public class TickAccumulator {
method TickAccumulator (line 20) | public TickAccumulator(float defaultValue) {
method tickUp (line 30) | public void tickUp(Level level) {
method tickDown (line 39) | public void tickDown(Level level) {
method tick (line 48) | public void tick(float amount) {
method getTicks (line 57) | public float getTicks() {
method setTicks (line 66) | public void setTicks(float ticks) {
method reset (line 73) | public void reset() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/BookshelfContent.java
class BookshelfContent (line 49) | public class BookshelfContent implements ContentProvider {
method defineIngredientTypes (line 51) | @Override
method defineCommands (line 60) | @Override
method defineCommandArguments (line 76) | @Override
method defineLoadConditions (line 82) | @Override
method defineItemSubPredicates (line 95) | @Override
method defineCriteriaTriggers (line 100) | @Override
method defineLootEntryTypes (line 105) | @Override
method defineLootDescriptions (line 110) | @Override
method namespace (line 123) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/BookshelfMod.java
class BookshelfMod (line 8) | public class BookshelfMod {
method init (line 13) | public void init() {
method runStartupChecks (line 23) | private void runStartupChecks() {
method detectInvalidContentProviders (line 30) | @Deprecated
method getInstance (line 53) | public static BookshelfMod getInstance() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/Constants.java
class Constants (line 12) | public class Constants {
method id (line 19) | public static ResourceLocation id(String path) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/DebugContentProvider.java
class DebugContentProvider (line 22) | public class DebugContentProvider implements ContentProvider {
method defineBlocks (line 24) | @Override
method defineItems (line 30) | @Override
method defineCreativeTabs (line 35) | @Override
method defineTrades (line 43) | @Override
method defineIngredientTypes (line 50) | @Override
method namespace (line 55) | @Override
method canLoad (line 60) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/BlockTagToItemTagCommand.java
class BlockTagToItemTagCommand (line 27) | public class BlockTagToItemTagCommand {
method build (line 29) | public static LiteralArgumentBuilder<CommandSourceStack> build(Command...
method tagJson (line 46) | private static <T> JsonObject tagJson(Collection<T> entries, Function<...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/DebugCommands.java
type DebugCommands (line 34) | public enum DebugCommands implements IEnumCommand {
method printTables (line 41) | private static void printTables(MinecraftServer server, StringJoiner o...
method findMissingTagNames (line 50) | private static void findMissingTagNames(MinecraftServer server, String...
method findMissingBlockDrops (line 68) | private static void findMissingBlockDrops(MinecraftServer server, Stri...
method findLootTableHashes (line 79) | private static void findLootTableHashes(MinecraftServer server, String...
method build (line 97) | public static LiteralArgumentBuilder<CommandSourceStack> build(Command...
method DebugCommands (line 103) | DebugCommands(DebugTask task) {
method getCommandName (line 107) | @Override
method run (line 112) | @Override
method requiredPermissionLevel (line 132) | @Override
type DebugTask (line 137) | @FunctionalInterface
method getDebugOutput (line 139) | void getDebugOutput(MinecraftServer server, StringJoiner output);
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/EnchantCommand.java
class EnchantCommand (line 22) | public class EnchantCommand {
method build (line 24) | public static LiteralArgumentBuilder<CommandSourceStack> build(Command...
method enchantItem (line 31) | private static int enchantItem(CommandContext<CommandSourceStack> ctx)...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/FontCommand.java
class FontCommand (line 33) | public class FontCommand {
method build (line 35) | public static LiteralArgumentBuilder<CommandSourceStack> build() {
method speakWithFont (line 48) | private static int speakWithFont(CommandContext<CommandSourceStack> co...
method renameItemWithFont (line 56) | private static int renameItemWithFont(CommandContext<CommandSourceStac...
method renameBlockWithFont (line 74) | private static int renameBlockWithFont(CommandContext<CommandSourceSta...
method applySignFont (line 99) | private static UnaryOperator<SignText> applySignFont(ResourceLocation ...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/HandCommand.java
type HandCommand (line 33) | public enum HandCommand implements IEnumCommand {
method HandCommand (line 55) | HandCommand(ItemFormat format) {
method run (line 59) | @Override
method getFormattedResults (line 68) | private Component getFormattedResults(ServerLevel level, ItemStack sta...
method json (line 81) | private static <T> ItemFormat json(Codec<T> codec, BiFunction<ItemStac...
method nbt (line 85) | private static <T> ItemFormat nbt(Codec<T> codec, BiFunction<ItemStack...
method fromCodec (line 89) | private static <T, D> ItemFormat fromCodec(DynamicOps<D> ops, Function...
method unsafeEncode (line 97) | @SuppressWarnings({"rawtypes", "unchecked"})
method getCommandName (line 102) | @Override
method build (line 107) | public static LiteralArgumentBuilder<CommandSourceStack> build(Command...
type ItemFormat (line 111) | interface ItemFormat {
method formatItem (line 112) | Component formatItem(ItemStack stack, ServerLevel level);
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/RenameCommand.java
class RenameCommand (line 14) | public class RenameCommand {
method build (line 16) | public static LiteralArgumentBuilder<CommandSourceStack> build(Command...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/StructureCommand.java
class StructureCommand (line 24) | public class StructureCommand {
method build (line 26) | public static LiteralArgumentBuilder<CommandSourceStack> build() {
method getUniqueStructuresAt (line 33) | private static Set<ResourceLocation> getUniqueStructuresAt(CommandCont...
method structureAt (line 39) | private static int structureAt(CommandContext<CommandSourceStack> cont...
method withPosition (line 50) | private static Command<CommandSourceStack> withPosition(BiFunction<Com...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/command/TranslateCommand.java
class TranslateCommand (line 12) | public class TranslateCommand {
method build (line 13) | public static LiteralArgumentBuilder<CommandSourceStack> build(Command...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/And.java
class And (line 17) | public class And implements ILoadCondition {
method And (line 25) | private And(List<ILoadCondition> conditions) {
method getConditions (line 30) | public List<ILoadCondition> getConditions() {
method allowLoading (line 35) | @Override
method getType (line 45) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/ModLoaded.java
class ModLoaded (line 19) | public class ModLoaded implements ILoadCondition {
method ModLoaded (line 27) | private ModLoaded(Set<String> requiredMods) {
method allowLoading (line 32) | @Override
method getRequiredMods (line 42) | public Set<String> getRequiredMods() {
method getType (line 46) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/Not.java
class Not (line 17) | public class Not implements ILoadCondition {
method Not (line 25) | private Not(List<ILoadCondition> conditions) {
method getConditions (line 29) | public List<ILoadCondition> getConditions() {
method allowLoading (line 33) | @Override
method getType (line 43) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/OnPlatform.java
class OnPlatform (line 17) | public class OnPlatform implements ILoadCondition {
method OnPlatform (line 25) | private OnPlatform(String requiredPlatform) {
method allowLoading (line 29) | @Override
method getRequiredPlatform (line 34) | public String getRequiredPlatform() {
method getType (line 38) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/Or.java
class Or (line 17) | public class Or implements ILoadCondition {
method Or (line 25) | private Or(List<ILoadCondition> conditions) {
method getConditions (line 29) | public List<ILoadCondition> getConditions() {
method allowLoading (line 33) | @Override
method getType (line 43) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/RegistryContains.java
class RegistryContains (line 16) | public class RegistryContains<T> implements ILoadCondition {
method of (line 28) | public static <RT> MapCodec<RegistryContains<RT>> of(ResourceLocation ...
method RegistryContains (line 34) | private RegistryContains(ResourceLocation typeId, Registry<T> registry...
method allowLoading (line 40) | @Override
method getRequiredEntries (line 50) | public Set<ResourceLocation> getRequiredEntries() {
method getType (line 54) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/criterion/item/NamespaceItemPredicate.java
method matches (line 14) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/criterion/trigger/AdvancementTrigger.java
class AdvancementTrigger (line 17) | public class AdvancementTrigger extends SimpleCriterionTrigger<Advanceme...
method codec (line 25) | @Override
method trigger (line 31) | public void trigger(ServerPlayer player, AdvancementHolder advancement) {
method player (line 37) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/AllOfIngredient.java
class AllOfIngredient (line 14) | public class AllOfIngredient implements IngredientLogic<AllOfIngredient> {
method AllOfIngredient (line 21) | public AllOfIngredient(List<Ingredient> ingredients) {
method test (line 25) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/BlockTagIngredient.java
class BlockTagIngredient (line 18) | public class BlockTagIngredient implements IngredientLogic<BlockTagIngre...
method BlockTagIngredient (line 31) | public BlockTagIngredient(List<TagKey<Block>> blockTags) {
method getAllMatchingStacks (line 35) | @Override
method test (line 51) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/EitherIngredient.java
class EitherIngredient (line 14) | public class EitherIngredient implements IngredientLogic<EitherIngredien...
method EitherIngredient (line 21) | public EitherIngredient(List<Ingredient> ingredients) {
method test (line 25) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/FalseIngredient.java
class FalseIngredient (line 13) | public class FalseIngredient implements IngredientLogic<FalseIngredient> {
method test (line 25) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/ModIdIngredient.java
class ModIdIngredient (line 15) | public class ModIdIngredient implements IngredientLogic<ModIdIngredient> {
method ModIdIngredient (line 22) | public ModIdIngredient(List<String> modIds) {
method test (line 26) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/entries/LootItemStack.java
class LootItemStack (line 24) | public class LootItemStack extends LootPoolSingletonContainer {
method LootItemStack (line 34) | private LootItemStack(ItemStack baseStack, int weight, int quality, Li...
method getBaseStack (line 39) | public ItemStack getBaseStack() {
method createItemStack (line 43) | @Override
method getType (line 48) | @NotNull
method of (line 54) | public static LootItemStack of(ItemStack baseStack, int weight) {
method of (line 58) | public static LootItemStack of(ItemStack baseStack, int weight, int qu...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/modifiers/FingerprintCodec.java
class FingerprintCodec (line 18) | public class FingerprintCodec<T> implements Codec<T> {
method FingerprintCodec (line 22) | public FingerprintCodec(Codec<T> delegate) {
method decode (line 26) | @Override
method encode (line 39) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/modifiers/ILootPoolHooks.java
type ILootPoolHooks (line 8) | public interface ILootPoolHooks {
method bookshelf$setHash (line 10) | void bookshelf$setHash(int fingerprint);
method bookshelf$getHash (line 12) | @Nullable
method bookshelf$matches (line 15) | default boolean bookshelf$matches(int toMatch) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/modifiers/LootModificationHandler.java
class LootModificationHandler (line 29) | public class LootModificationHandler {
method addPoolEntry (line 39) | private void addPoolEntry(ResourceLocation tableId, int poolIndex, int...
method processLootTable (line 48) | public void processLootTable(ResourceLocation tableId, LootTable table) {
method findPool (line 70) | @Nullable
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/recipe/RecipeTypeImpl.java
method toString (line 10) | @NotNull
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/BlockEntityRendererAdapter.java
method bind (line 12) | public <T extends BlockEntity> void bind(BlockEntityType<T> type, BlockE...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/BlockRegistryAdapter.java
class BlockRegistryAdapter (line 19) | public class BlockRegistryAdapter extends GameRegistryAdapter<Block> {
method BlockRegistryAdapter (line 21) | public BlockRegistryAdapter(RegistrationContext context, ResourceKey<R...
method addPlaceable (line 33) | public RegistryReference<ResourceKey<Block>, Block> addPlaceable(Strin...
method addPlaceable (line 46) | public RegistryReference<ResourceKey<Block>, Block> addPlaceable(Strin...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/BlockRenderTypeAdapter.java
method add (line 10) | public void add(Block block, RenderType type) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/CommandArgumentAdapter.java
class CommandArgumentAdapter (line 12) | public class CommandArgumentAdapter extends GenericRegistryAdapter<Comma...
method CommandArgumentAdapter (line 14) | public CommandArgumentAdapter(RegistrationContext context, BiConsumer<...
method add (line 18) | @SuppressWarnings({"rawtypes", "unchecked"})
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/CreativeModeTabAdapter.java
class CreativeModeTabAdapter (line 16) | public class CreativeModeTabAdapter extends GameRegistryAdapter<Creative...
method CreativeModeTabAdapter (line 18) | public CreativeModeTabAdapter(RegistrationContext context, ResourceKey...
method add (line 29) | public void add(String key, Supplier<ItemStack> icon, CreativeModeTab....
method add (line 43) | public void add(String key, Consumer<CreativeModeTab.Builder> builderF...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/IngredientTypeAdapter.java
class IngredientTypeAdapter (line 18) | @SuppressWarnings("rawtypes")
method IngredientTypeAdapter (line 21) | public IngredientTypeAdapter(RegistrationContext context, BiConsumer<R...
method add (line 34) | public <T extends IngredientLogic<T>> RegistryReference<ResourceLocati...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/LootEntryTypeAdapter.java
class LootEntryTypeAdapter (line 14) | public class LootEntryTypeAdapter extends GameRegistryAdapter<LootPoolEn...
method LootEntryTypeAdapter (line 15) | public LootEntryTypeAdapter(RegistrationContext context, ResourceKey<R...
method add (line 19) | public <T extends LootPoolEntryContainer> void add(String key, MapCode...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/LootPoolAdditionAdapter.java
method add (line 24) | public void add(String id, PoolTarget pool, ItemStack item, int weight) {
method add (line 28) | public void add(String id, PoolTarget pool, Item item, int weight) {
method add (line 32) | public void add(String id, ResourceKey<LootTable> tableId, int poolIndex...
method add (line 36) | public void add(String id, ResourceLocation tableId, int poolIndex, int ...
method add (line 40) | public void add(String id, ResourceKey<LootTable> tableId, int poolIndex...
method add (line 44) | public void add(String id, ResourceLocation tableId, int poolIndex, int ...
method add (line 48) | public void add(String id, PoolTarget pool, LootPoolEntryContainer addit...
method add (line 52) | public void add(String id, ResourceKey<LootTable> tableId, int poolIndex...
method add (line 56) | public void add(String id, ResourceLocation tableId, int poolIndex, int ...
method id (line 60) | private ResourceLocation id(String id) {
type RegisterFunc (line 64) | @FunctionalInterface
method register (line 66) | void register(ResourceLocation tableId, int poolIndex, int poolHash, L...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/MenuScreenAdapter.java
method bind (line 15) | public <M extends AbstractContainerMenu, U extends Screen & MenuAccess<M...
type ScreenFactory (line 19) | @FunctionalInterface
method create (line 21) | U create(T menu, Inventory playerInv, Component title);
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/MenuTypeAdapter.java
class MenuTypeAdapter (line 12) | public class MenuTypeAdapter extends GenericRegistryAdapter<MenuTypeAdap...
method MenuTypeAdapter (line 14) | public MenuTypeAdapter(RegistrationContext context, BiConsumer<Resourc...
type ClientMenuFactory (line 18) | public interface ClientMenuFactory<T extends AbstractContainerMenu> {
method create (line 19) | T create(int containerId, Inventory playerInventory);
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/PacketAdapter.java
method add (line 10) | public <T extends CustomPacketPayload> IPacket<T> add(IPacket<T> packet) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/PotPatternAdapter.java
class PotPatternAdapter (line 17) | public final class PotPatternAdapter extends GameRegistryAdapter<Decorat...
method PotPatternAdapter (line 19) | public PotPatternAdapter(RegistrationContext context, ResourceKey<Regi...
method add (line 29) | public RegistryReference<ResourceKey<DecoratedPotPattern>, DecoratedPo...
method addWithItem (line 40) | public RegistryReference<ResourceKey<DecoratedPotPattern>, DecoratedPo...
method addWithItem (line 53) | public RegistryReference<ResourceKey<DecoratedPotPattern>, DecoratedPo...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/PotionBrewAdapter.java
class PotionBrewAdapter (line 3) | public class PotionBrewAdapter {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/RecipeTypeAdapter.java
class RecipeTypeAdapter (line 15) | public class RecipeTypeAdapter extends GameRegistryAdapter<RecipeType<?>> {
method RecipeTypeAdapter (line 17) | public RecipeTypeAdapter(RegistrationContext context, ResourceKey<Regi...
method add (line 21) | public RegistryReference<ResourceKey<RecipeType<?>>, RecipeType<?>> ad...
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/SoundEventAdapter.java
class SoundEventAdapter (line 12) | public class SoundEventAdapter extends GameRegistryAdapter<SoundEvent> {
method SoundEventAdapter (line 14) | public SoundEventAdapter(RegistrationContext context, ResourceKey<Regi...
method fixedRange (line 18) | public void fixedRange(String id, float range) {
method variableRange (line 22) | public void variableRange(String id) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/VillagerTradeAdapter.java
class VillagerTradeAdapter (line 15) | public final class VillagerTradeAdapter {
method addTrade (line 28) | public void addTrade(VillagerProfession profession, int tier, Villager...
method addTrade (line 39) | public void addTrade(VillagerProfession profession, MerchantTier tier,...
method addWanderingTrade (line 49) | public void addWanderingTrade(VillagerTrades.ItemListing trade, boolea...
method addCommonWanderingTrade (line 58) | public void addCommonWanderingTrade(VillagerTrades.ItemListing trade) {
method addRareWanderingTrade (line 67) | public void addRareWanderingTrade(VillagerTrades.ItemListing trade) {
method getVillagerTrades (line 76) | public Map<VillagerProfession, Multimap<Integer, VillagerTrades.ItemLi...
method getRareWanderingTrades (line 85) | public List<VillagerTrades.ItemListing> getRareWanderingTrades() {
method getCommonWanderingTrades (line 94) | public List<VillagerTrades.ItemListing> getCommonWanderingTrades() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/impl/resources/ExtendedText.java
class ExtendedText (line 14) | public class ExtendedText {
method ExtendedText (line 19) | private ExtendedText() {
method has (line 34) | public boolean has(String key) {
method get (line 38) | public String get(String key) {
method register (line 42) | private void register(String key, Supplier<String> value) {
method getProperty (line 46) | private static String getProperty(String propertyName) {
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorBannerBlockEntity.java
type AccessorBannerBlockEntity (line 8) | @Mixin(BannerBlockEntity.class)
method setName (line 11) | @Accessor("name")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorBaseContainerBlockEntity.java
type AccessorBaseContainerBlockEntity (line 8) | @Mixin(BaseContainerBlockEntity.class)
method bookshelf$name (line 11) | @Accessor("name")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorBlockEntityRenderers.java
type AccessorBlockEntityRenderers (line 9) | @Mixin(BlockEntityRenderers.class)
method bookshelf$register (line 12) | @Invoker("register")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorCropBlock.java
type AccessorCropBlock (line 8) | @Mixin(CropBlock.class)
method bookshelf$getSeed (line 11) | @Invoker("getBaseSeedId")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/AccessorFontManager.java
type AccessorFontManager (line 11) | @Mixin(FontManager.class)
method bookshelf$getFonts (line 14) | @Accessor("fontSets")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/AccessorItemBlockRenderTypes.java
type AccessorItemBlockRenderTypes (line 11) | @Mixin(ItemBlockRenderTypes.class)
method bookshelf$getBlockTypes (line 14) | @Accessor("TYPE_BY_BLOCK")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/AccessorMinecraft.java
type AccessorMinecraft (line 8) | @Mixin(Minecraft.class)
method bookshelf$getFontManager (line 11) | @Accessor("fontManager")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/gui/AccessorAbstractWidget.java
type AccessorAbstractWidget (line 10) | @Mixin(AbstractWidget.class)
method bookshelf$renderScrollingString (line 13) | @Invoker("renderScrollingString")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/entity/AccessorEntity.java
type AccessorEntity (line 8) | @Mixin(Entity.class)
method bookshelf$createHoverEvent (line 11) | @Invoker("createHoverEvent")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/level/AccessorRecipeManager.java
type AccessorRecipeManager (line 10) | @Mixin(RecipeManager.class)
method bookshelf$byTypeMap (line 13) | @Accessor("byType")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorCompositeEntryBase.java
type AccessorCompositeEntryBase (line 10) | @Mixin(CompositeEntryBase.class)
method bookshelf$children (line 13) | @Accessor("children")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorDynamicLoot.java
type AccessorDynamicLoot (line 8) | @Mixin(DynamicLoot.class)
method bookshelf$name (line 11) | @Accessor("name")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootItem.java
type AccessorLootItem (line 14) | @Mixin(LootItem.class)
method bookshelf$create (line 17) | @Invoker("<init>")
method bookshelf$item (line 22) | @Accessor("item")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootPool.java
type AccessorLootPool (line 14) | @Mixin(LootPool.class)
method bookshelf$entries (line 17) | @Accessor("entries")
method bookshelf$setEntries (line 20) | @Accessor("entries")
method bookshelf$conditions (line 24) | @Accessor("conditions")
method functions (line 27) | @Accessor("functions")
method bookshelf$rolls (line 30) | @Accessor("rolls")
method bookshelf$bonusRolls (line 33) | @Accessor("bonusRolls")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootPoolSingletonContainer.java
type AccessorLootPoolSingletonContainer (line 7) | @Mixin(LootPoolSingletonContainer.class)
method bookshelf$weight (line 10) | @Accessor("weight")
method bookshelf$quality (line 13) | @Accessor("quality")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootTable.java
type AccessorLootTable (line 13) | @Mixin(LootTable.class)
method bookshelf$randomSequence (line 16) | @Accessor("randomSequence")
method bookshelf$pools (line 19) | @Accessor("pools")
method bookshelf$functions (line 22) | @Accessor("functions")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorNestedLootTable.java
type AccessorNestedLootTable (line 10) | @Mixin(NestedLootTable.class)
method bookshelf$contents (line 13) | @Accessor("contents")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorTagEntry.java
type AccessorTagEntry (line 9) | @Mixin(TagEntry.class)
method bookshelf$tag (line 12) | @Accessor("tag")
method bookshelf$expand (line 15) | @Accessor("expand")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/access/particles/AccessSimpleParticleType.java
type AccessSimpleParticleType (line 7) | @Mixin(SimpleParticleType.class)
method init (line 10) | @Invoker("<init>")
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/advancement/MixinPlayerAdvancements.java
class MixinPlayerAdvancements (line 14) | @Mixin(PlayerAdvancements.class)
method getOrStartProgress (line 20) | @Shadow
method onAward (line 23) | @Inject(method = "award(Lnet/minecraft/advancements/AdvancementHolder;...
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/block/MixinDecoratedPotPatterns.java
class MixinDecoratedPotPatterns (line 13) | @Mixin(DecoratedPotPatterns.class)
method getResourceKey (line 16) | @Inject(method = "getPatternFromItem", at = @At("TAIL"), cancellable =...
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/client/MixinClientPacketListener.java
class MixinClientPacketListener (line 16) | @Mixin(value = ClientPacketListener.class, priority = 1005)
method onInit (line 23) | @Inject(method = "<init>", at = @At("TAIL"))
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/entity/MixinLightningBolt.java
class MixinLightningBolt (line 16) | @Mixin(LightningBolt.class)
method onLightningStrike (line 19) | @Inject(method = "powerLightningRod", at = @At("RETURN"))
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/entity/MixinLivingEntity.java
class MixinLivingEntity (line 13) | @Mixin(LivingEntity.class)
method updateFakePlayerDamageTimes (line 27) | @Inject(method = "hurt", at = @At("HEAD"))
method MixinLivingEntity (line 35) | private MixinLivingEntity() {
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/item/MixinCreativeModeTab.java
class MixinCreativeModeTab (line 26) | @Mixin(CreativeModeTab.class)
method buildContents (line 41) | @Inject(method = "buildContents(Lnet/minecraft/world/item/CreativeMode...
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/level/MixinRecipeManager.java
class MixinRecipeManager (line 19) | @Mixin(RecipeManager.class)
method onReload (line 28) | @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/res...
method onRecipesUpdated (line 35) | @Inject(method = "replaceRecipes", at = @At("RETURN"))
method bookshelf$setLogicalClient (line 42) | @Override
method bookshelf$setLogicalServer (line 48) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/level/MixinWalkNodeEvaluator.java
class MixinWalkNodeEvaluator (line 15) | @Mixin(WalkNodeEvaluator.class)
method getBlockPathTypeRaw (line 22) | @Inject(method = "getPathTypeFromState(Lnet/minecraft/world/level/Bloc...
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/locale/MixinClientLanguage.java
class MixinClientLanguage (line 10) | @Mixin(ClientLanguage.class)
method getOrDefault (line 13) | @Inject(method = "getOrDefault", at = @At("HEAD"), cancellable = true)
method has (line 20) | @Inject(method = "has", at = @At("HEAD"), cancellable = true)
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/loot/MixinLootDataType.java
class MixinLootDataType (line 21) | @Mixin(LootDataType.class)
method onDeserialize (line 24) | @Inject(method = "deserialize(Lnet/minecraft/resources/ResourceLocatio...
method bookshelf$getLootTable (line 44) | @Nullable
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/loot/MixinLootItemKilledByPlayerCondition.java
class MixinLootItemKilledByPlayerCondition (line 13) | @Mixin(LootItemKilledByPlayerCondition.class)
method test (line 20) | @Inject(method = "test(Lnet/minecraft/world/level/storage/loot/LootCon...
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/loot/MixinLootPool.java
class MixinLootPool (line 16) | @Mixin(LootPool.class)
method onClassInit (line 27) | @Inject(method = "<clinit>", at = @At("RETURN"))
method bookshelf$setHash (line 32) | @Override
method bookshelf$getHash (line 37) | @Override
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/packs/MixinSimpleJsonResourceReloadListener.java
class MixinSimpleJsonResourceReloadListener (line 17) | @Mixin(SimpleJsonResourceReloadListener.class)
method prepare (line 24) | @Inject(method = "prepare(Lnet/minecraft/server/packs/resources/Resour...
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/potions/MixinPotionBrewing.java
class MixinPotionBrewing (line 10) | @Mixin(PotionBrewing.class)
method onBootstrap (line 13) | @Inject(method = "addVanillaMixes", at = @At("RETURN"))
FILE: common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/server/MixinReloadableServerResources.java
class MixinReloadableServerResources (line 16) | @Mixin(ReloadableServerResources.class)
method onInit (line 21) | @Inject(method = "<init>", at = @At("RETURN"))
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/FabricMod.java
class FabricMod (line 14) | public class FabricMod implements ModInitializer {
method onInitialize (line 16) | @Override
method checkForUpdates (line 23) | private static void checkForUpdates() {
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/FabricModClient.java
class FabricModClient (line 5) | public class FabricModClient implements ClientModInitializer {
method onInitializeClient (line 6) | @Override
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/data/FabricIngredient.java
class FabricIngredient (line 15) | public class FabricIngredient<T extends IngredientLogic<T>> implements C...
method FabricIngredient (line 20) | public FabricIngredient(T logic, Supplier<CustomIngredientSerializer<?...
method test (line 25) | @Override
method getMatchingStacks (line 30) | @Override
method requiresTesting (line 35) | @Override
method getSerializer (line 40) | @Override
method make (line 45) | public static <T extends IngredientLogic<T>> CustomIngredientSerialize...
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/network/FabricNetworkHandler.java
class FabricNetworkHandler (line 18) | public class FabricNetworkHandler implements INetworkHandler {
method register (line 22) | @Override
method sendToServer (line 43) | @Override
method sendToPlayer (line 57) | @Override
method canSendPacket (line 67) | @Override
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricGameplayHelper.java
class FabricGameplayHelper (line 21) | public class FabricGameplayHelper implements IGameplayHelper {
method inventoryInsert (line 23) | @Override
method blockEntityBuilder (line 48) | @Override
method tabBuilder (line 54) | @Override
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricPlatformHelper.java
class FabricPlatformHelper (line 17) | public class FabricPlatformHelper implements IPlatformHelper {
method getGamePath (line 24) | @Override
method getConfigPath (line 29) | @Override
method getModsPath (line 34) | @Override
method isModLoaded (line 39) | @Override
method isDevelopmentEnvironment (line 44) | @Override
method getPhysicalSide (line 49) | @Override
method getLoadedMods (line 54) | @Override
method isTestingEnvironment (line 59) | @Override
method getName (line 64) | @Override
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricRegistryHelper.java
class FabricRegistryHelper (line 53) | public final class FabricRegistryHelper {
method FabricRegistryHelper (line 58) | public FabricRegistryHelper(ContentProvider content) {
method registerContent (line 74) | private void registerContent() {
method registerClient (line 102) | @SuppressWarnings({"rawtypes", "unchecked"})
method registerVillagerTrades (line 110) | private void registerVillagerTrades() {
method registerCommands (line 135) | private void registerCommands() {
method registerCommandArgument (line 140) | @SuppressWarnings({"rawtypes", "unchecked"})
method adaptType (line 145) | @SuppressWarnings({"rawtypes", "unchecked"})
method adapt (line 150) | private static <T> BiConsumer<ResourceKey<T>, Supplier<T>> adapt(Regis...
FILE: fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricRenderHelper.java
class FabricRenderHelper (line 14) | public class FabricRenderHelper implements IRenderHelper {
method renderFluidBox (line 16) | @Override
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/NeoForgeMod.java
class NeoForgeMod (line 11) | @Mod(Constants.MOD_ID)
method NeoForgeMod (line 14) | public NeoForgeMod(IEventBus eventBus) {
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/data/NeoForgeIngredient.java
class NeoForgeIngredient (line 17) | public class NeoForgeIngredient<T extends IngredientLogic<T>> implements...
method NeoForgeIngredient (line 22) | public NeoForgeIngredient(T logic, Supplier<IngredientType<?>> type) {
method test (line 27) | @Override
method getItems (line 32) | @NotNull
method isSimple (line 38) | @Override
method getType (line 43) | @NotNull
method makeIngredientType (line 49) | public static <T extends IngredientLogic<T>> IngredientType<NeoForgeIn...
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/network/NeoForgeNetworkHandler.java
class NeoForgeNetworkHandler (line 22) | public class NeoForgeNetworkHandler implements INetworkHandler {
method register (line 27) | @Override
method registerPayloadHandlers (line 33) | public void registerPayloadHandlers(RegisterPayloadHandlersEvent event) {
method sendToServer (line 50) | @Override
method sendToPlayer (line 64) | @Override
method canSendPacket (line 74) | @Override
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/util/NeoForgeGameplayHelper.java
class NeoForgeGameplayHelper (line 20) | public class NeoForgeGameplayHelper implements IGameplayHelper {
method getCraftingRemainder (line 22) | @Override
method inventoryInsert (line 28) | @Override
method blockEntityBuilder (line 34) | @Override
method tabBuilder (line 40) | @Override
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/util/NeoForgePlatformHelper.java
class NeoForgePlatformHelper (line 18) | public class NeoForgePlatformHelper implements IPlatformHelper {
method getGamePath (line 22) | @Override
method getConfigPath (line 27) | @Override
method getModsPath (line 32) | @Override
method isModLoaded (line 37) | @Override
method isDevelopmentEnvironment (line 42) | @Override
method getPhysicalSide (line 47) | @Override
method getLoadedMods (line 52) | @Override
method isTestingEnvironment (line 57) | @Override
method getName (line 62) | @Override
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/util/NeoForgeRegistryHelper.java
class NeoForgeRegistryHelper (line 62) | public final class NeoForgeRegistryHelper {
method NeoForgeRegistryHelper (line 68) | public NeoForgeRegistryHelper(ContentProvider content) {
method registerContent (line 88) | private void registerContent(RegisterEvent event) {
method setupCommandRegistration (line 123) | private void setupCommandRegistration() {
method setupTradeRegistration (line 127) | private void setupTradeRegistration() {
method bindMenuScreens (line 148) | @SuppressWarnings({"unchecked", "rawtypes"})
method registerRenderers (line 154) | private void registerRenderers(EntityRenderersEvent.RegisterRenderers ...
method adaptRegistry (line 158) | private <T> void adaptRegistry(RegisterEvent event, ResourceKey<Regist...
method adaptRegistry (line 162) | private <T, A extends GameRegistryAdapter<T>> void adaptRegistry(Regis...
method adapt (line 166) | private static <T> BiConsumer<ResourceKey<T>, Supplier<T>> adapt(Regis...
method adaptGeneric (line 170) | private static <T> BiConsumer<ResourceLocation, Supplier<T>> adaptGene...
method adaptType (line 174) | @SuppressWarnings({"rawtypes", "unchecked"})
method registerCommandArgument (line 179) | @SuppressWarnings({"rawtypes", "unchecked"})
method getModBus (line 185) | private static IEventBus getModBus(String modid) {
type GameRegistryAdapterFactory (line 197) | @FunctionalInterface
method build (line 199) | A build(RegistrationContext context, ResourceKey<Registry<T>> regist...
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/impl/util/NeoForgeRenderHelper.java
class NeoForgeRenderHelper (line 13) | public class NeoForgeRenderHelper implements IRenderHelper {
method renderFluidBox (line 14) | @Override
FILE: neoforge/src/main/java/net/darkhax/bookshelf/neoforge/mixin/access/gui/screen/AccessorMenuScreens.java
type AccessorMenuScreens (line 11) | @Mixin(MenuScreens.class)
method register (line 14) | @Invoker("register")
Condensed preview — 225 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (604K chars).
[
{
"path": ".gitattributes",
"chars": 231,
"preview": "* text eol=lf\n*.bat text eol=crlf\n*.patch text eol=lf\n*.java text eol=lf\n*.gradle text eol=crlf\n*.png binary\n*.gif binar"
},
{
"path": ".gitignore",
"chars": 184,
"preview": "# eclipse\nbin\n*.launch\n.settings\n.metadata\n.classpath\n.project\n\n# idea\nout\n*.ipr\n*.iws\n*.iml\n.idea/*\n!.idea/scopes\n\n# gr"
},
{
"path": "Jenkinsfile",
"chars": 897,
"preview": "#!/usr/bin/env groovy\n\npipeline {\n\n agent any\n\n tools {\n jdk \"jdk-21\"\n }\n\n stages {\n\n stage('S"
},
{
"path": "LICENSE",
"chars": 26466,
"preview": " GNU LESSER GENERAL PUBLIC LICENSE\n Version 2.1, February 1999\n\nCopyright (C) 199"
},
{
"path": "README.md",
"chars": 3245,
"preview": "<!-- name-start -->\n# Bookshelf [\r\n}\r\n\r\ndependencies {\r\n implementati"
},
{
"path": "buildSrc/src/main/groovy/build-number.gradle",
"chars": 568,
"preview": "// This script attempts to append the build number to the project version.\r\n// The build number is read from an environm"
},
{
"path": "buildSrc/src/main/groovy/git-changelog.gradle",
"chars": 1354,
"preview": "project.ext.mod_changelog = 'No changelog was provided. Please refer to the project page for more information.'\r\n\r\ntry {"
},
{
"path": "buildSrc/src/main/groovy/minify-json.gradle",
"chars": 1526,
"preview": "// This script will minify JSON files as the project is built. This is\r\n// done by removing unused whitespace and newlin"
},
{
"path": "buildSrc/src/main/groovy/multiloader-common.gradle",
"chars": 5130,
"preview": "plugins {\r\n id 'java-library'\r\n id 'maven-publish'\r\n id 'minify-json'\r\n}\r\n\r\nbase {\r\n archivesName = \"${mod_i"
},
{
"path": "buildSrc/src/main/groovy/multiloader-loader.gradle",
"chars": 1060,
"preview": "plugins {\r\n id 'multiloader-common'\r\n}\r\n\r\nconfigurations {\r\n commonJava{\r\n canBeResolved = true\r\n }\r\n "
},
{
"path": "buildSrc/src/main/groovy/patreon.gradle",
"chars": 4400,
"preview": "import groovy.json.JsonSlurper\r\n\r\nproject.ext.patreon = [\r\n pledgeNames : '',\r\n campaignUrl : "
},
{
"path": "buildSrc/src/main/groovy/project_validation.gradle",
"chars": 1136,
"preview": "import javax.imageio.ImageIO\r\nimport java.awt.image.BufferedImage\r\n\r\ngradle.taskGraph.whenReady { graph ->\r\n\r\n // Val"
},
{
"path": "buildSrc/src/main/groovy/readme-update.gradle",
"chars": 4297,
"preview": "task updateReadme {\r\n var readme = rootProject.file('README.md')\r\n if (!readme.exists()) {\r\n throw new Grad"
},
{
"path": "buildSrc/src/main/groovy/secret-loader.gradle",
"chars": 1471,
"preview": "// Loads properties from a file containing environmental secrets.\r\nimport groovy.json.JsonSlurper\r\n\r\n// Auto detects a s"
},
{
"path": "buildSrc/src/main/groovy/version-checker.gradle",
"chars": 1989,
"preview": "// This plugin adds a task that can update the latest version on Jared's\r\n// update checker API. This is a private servi"
},
{
"path": "common/build.gradle",
"chars": 1035,
"preview": "plugins {\r\n id 'multiloader-common'\r\n id 'net.neoforged.moddev'\r\n}\r\n\r\nneoForge {\r\n neoFormVersion = neo_form_ve"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/ModEntry.java",
"chars": 133,
"preview": "package net.darkhax.bookshelf.common.api;\n\npublic record ModEntry(String modId, String name, String description, String "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/PhysicalSide.java",
"chars": 771,
"preview": "package net.darkhax.bookshelf.common.api;\n\n/**\n * Represents a physical location in the client/server network diagram.\n "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/annotation/InternalUse.java",
"chars": 332,
"preview": "package net.darkhax.bookshelf.common.api.annotation;\n\n/**\n * A visual indicator for members that may be visible for tech"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/annotation/OnlyFor.java",
"chars": 388,
"preview": "package net.darkhax.bookshelf.common.api.annotation;\n\nimport net.darkhax.bookshelf.common.api.PhysicalSide;\n\n/**\n * A vi"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/block/IBlockHooks.java",
"chars": 2661,
"preview": "package net.darkhax.bookshelf.common.api.block;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/commands/IEnumCommand.java",
"chars": 683,
"preview": "package net.darkhax.bookshelf.common.api.commands;\n\nimport com.mojang.brigadier.Command;\nimport net.minecraft.commands.C"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/commands/PermissionLevel.java",
"chars": 1474,
"preview": "package net.darkhax.bookshelf.common.api.commands;\n\nimport net.minecraft.commands.CommandSourceStack;\nimport net.minecra"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/ArgumentSerializer.java",
"chars": 2534,
"preview": "package net.darkhax.bookshelf.common.api.commands.args;\n\nimport com.google.gson.JsonObject;\nimport com.mojang.brigadier."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/FontArgument.java",
"chars": 2665,
"preview": "package net.darkhax.bookshelf.common.api.commands.args;\n\nimport com.mojang.brigadier.StringReader;\nimport com.mojang.bri"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/SingletonArgumentInfo.java",
"chars": 2934,
"preview": "package net.darkhax.bookshelf.common.api.commands.args;\n\nimport com.google.gson.JsonObject;\nimport com.mojang.brigadier."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/commands/args/TagArgument.java",
"chars": 3544,
"preview": "package net.darkhax.bookshelf.common.api.commands.args;\n\nimport com.mojang.brigadier.StringReader;\nimport com.mojang.bri"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/BookshelfTags.java",
"chars": 484,
"preview": "package net.darkhax.bookshelf.common.api.data;\n\nimport net.darkhax.bookshelf.common.impl.Constants;\nimport net.minecraft"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/ISidedRecipeManager.java",
"chars": 169,
"preview": "package net.darkhax.bookshelf.common.api.data;\n\npublic interface ISidedRecipeManager {\n\n void bookshelf$setLogicalCli"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/EnumStreamCodec.java",
"chars": 597,
"preview": "package net.darkhax.bookshelf.common.api.data.codecs;\n\nimport net.minecraft.network.FriendlyByteBuf;\nimport net.minecraf"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/MapCodecHelper.java",
"chars": 14891,
"preview": "package net.darkhax.bookshelf.common.api.data.codecs.map;\n\nimport com.mojang.serialization.Codec;\nimport com.mojang.seri"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/MapCodecs.java",
"chars": 34978,
"preview": "package net.darkhax.bookshelf.common.api.data.codecs.map;\n\nimport com.mojang.datafixers.util.Either;\nimport com.mojang.d"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/map/RegistryMapCodecHelper.java",
"chars": 1679,
"preview": "package net.darkhax.bookshelf.common.api.data.codecs.map;\n\nimport com.mojang.serialization.Codec;\nimport net.minecraft.c"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/codecs/stream/StreamCodecs.java",
"chars": 1841,
"preview": "package net.darkhax.bookshelf.common.api.data.codecs.stream;\n\nimport io.netty.buffer.ByteBuf;\nimport net.darkhax.bookshe"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/ConditionType.java",
"chars": 448,
"preview": "package net.darkhax.bookshelf.common.api.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport net.minecraf"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/ILoadCondition.java",
"chars": 632,
"preview": "package net.darkhax.bookshelf.common.api.data.conditions;\n\n/**\n * Load conditions allow JSON entries in data/resource pa"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/conditions/LoadConditions.java",
"chars": 2991,
"preview": "package net.darkhax.bookshelf.common.api.data.conditions;\n\nimport com.google.gson.JsonElement;\nimport com.google.gson.Js"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/enchantment/EnchantmentLevel.java",
"chars": 2671,
"preview": "package net.darkhax.bookshelf.common.api.data.enchantment;\n\nimport it.unimi.dsi.fastutil.objects.Object2IntMap;\nimport n"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/ingredient/IngredientLogic.java",
"chars": 775,
"preview": "package net.darkhax.bookshelf.common.api.data.ingredient;\n\nimport net.minecraft.core.registries.BuiltInRegistries;\nimpor"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/loot/PoolTarget.java",
"chars": 3180,
"preview": "package net.darkhax.bookshelf.common.api.data.loot;\n\nimport net.minecraft.resources.ResourceKey;\nimport net.minecraft.re"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/data/loot/modifiers/LootPoolAddition.java",
"chars": 565,
"preview": "package net.darkhax.bookshelf.common.api.data.loot.modifiers;\n\nimport net.minecraft.resources.ResourceLocation;\nimport n"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/MerchantTier.java",
"chars": 371,
"preview": "package net.darkhax.bookshelf.common.api.entity.villager;\n\npublic enum MerchantTier {\n\n NOVICE(0),\n APPRENTICE(10)"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerBuys.java",
"chars": 1372,
"preview": "package net.darkhax.bookshelf.common.api.entity.villager.trades;\n\nimport net.minecraft.util.RandomSource;\nimport net.min"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerOffers.java",
"chars": 845,
"preview": "package net.darkhax.bookshelf.common.api.entity.villager.trades;\n\nimport net.minecraft.util.RandomSource;\nimport net.min"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/entity/villager/trades/VillagerSells.java",
"chars": 1370,
"preview": "package net.darkhax.bookshelf.common.api.entity.villager.trades;\n\nimport net.minecraft.util.RandomSource;\nimport net.min"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/function/CachedSupplier.java",
"chars": 5010,
"preview": "package net.darkhax.bookshelf.common.api.function;\n\nimport net.darkhax.bookshelf.common.impl.Constants;\nimport net.minec"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/function/QuadConsumer.java",
"chars": 1038,
"preview": "package net.darkhax.bookshelf.common.api.function;\n\nimport java.util.Objects;\n\n/**\n * A consumer that accepts four param"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/function/ReloadableCache.java",
"chars": 8968,
"preview": "package net.darkhax.bookshelf.common.api.function;\n\nimport net.darkhax.bookshelf.common.impl.Constants;\nimport net.darkh"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/function/SidedReloadableCache.java",
"chars": 2523,
"preview": "package net.darkhax.bookshelf.common.api.function;\n\nimport net.darkhax.bookshelf.common.mixin.access.level.AccessorRecip"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/function/TriConsumer.java",
"chars": 422,
"preview": "package net.darkhax.bookshelf.common.api.function;\n\nimport java.util.Objects;\n\n@FunctionalInterface\npublic interface Tri"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/function/TriFunction.java",
"chars": 416,
"preview": "package net.darkhax.bookshelf.common.api.function;\n\nimport java.util.Objects;\nimport java.util.function.Function;\n\n@Func"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/item/IItemHooks.java",
"chars": 327,
"preview": "package net.darkhax.bookshelf.common.api.item;\n\nimport net.minecraft.world.item.CreativeModeTab;\nimport net.minecraft.wo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/loot/LootPoolEntryDescriber.java",
"chars": 925,
"preview": "package net.darkhax.bookshelf.common.api.loot;\n\nimport net.minecraft.core.RegistryAccess;\nimport net.minecraft.world.ite"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/loot/LootPoolEntryDescriptions.java",
"chars": 9450,
"preview": "package net.darkhax.bookshelf.common.api.loot;\n\nimport com.mojang.datafixers.util.Either;\nimport net.darkhax.bookshelf.c"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/menu/data/BlockPosData.java",
"chars": 2177,
"preview": "package net.darkhax.bookshelf.common.api.menu.data;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.world.inve"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/menu/slot/InputSlot.java",
"chars": 1421,
"preview": "package net.darkhax.bookshelf.common.api.menu.slot;\n\nimport com.mojang.datafixers.util.Pair;\nimport net.minecraft.resour"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/menu/slot/OutputSlot.java",
"chars": 1168,
"preview": "package net.darkhax.bookshelf.common.api.menu.slot;\n\nimport net.minecraft.world.Container;\nimport net.minecraft.world.en"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/network/AbstractPacket.java",
"chars": 1843,
"preview": "package net.darkhax.bookshelf.common.api.network;\n\nimport net.minecraft.network.RegistryFriendlyByteBuf;\nimport net.mine"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/network/Destination.java",
"chars": 1492,
"preview": "package net.darkhax.bookshelf.common.api.network;\n\n/**\n * Determines where the packet will be resolved.\n */\npublic enum "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/network/INetworkHandler.java",
"chars": 2347,
"preview": "package net.darkhax.bookshelf.common.api.network;\n\nimport net.minecraft.network.protocol.common.custom.CustomPacketPaylo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/network/IPacket.java",
"chars": 4749,
"preview": "package net.darkhax.bookshelf.common.api.network;\n\nimport net.darkhax.bookshelf.common.api.PhysicalSide;\nimport net.dark"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/registry/ContentProvider.java",
"chars": 12275,
"preview": "package net.darkhax.bookshelf.common.api.registry;\n\nimport com.mojang.brigadier.CommandDispatcher;\nimport com.mojang.ser"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/registry/RegistrationContext.java",
"chars": 2917,
"preview": "package net.darkhax.bookshelf.common.api.registry;\n\nimport net.darkhax.bookshelf.common.impl.Constants;\nimport net.minec"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/registry/RegistryReference.java",
"chars": 2856,
"preview": "package net.darkhax.bookshelf.common.api.registry;\n\nimport net.darkhax.bookshelf.common.api.function.CachedSupplier;\nimp"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/registry/adapters/GameRegistryAdapter.java",
"chars": 2056,
"preview": "package net.darkhax.bookshelf.common.api.registry.adapters;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/registry/adapters/GenericRegistryAdapter.java",
"chars": 2325,
"preview": "package net.darkhax.bookshelf.common.api.registry.adapters;\n\nimport net.darkhax.bookshelf.common.api.function.CachedSupp"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/registry/adapters/RegistryAdapter.java",
"chars": 1220,
"preview": "package net.darkhax.bookshelf.common.api.registry.adapters;\n\nimport net.darkhax.bookshelf.common.api.registry.RegistryRe"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/service/Services.java",
"chars": 3032,
"preview": "package net.darkhax.bookshelf.common.api.service;\n\nimport net.darkhax.bookshelf.common.api.function.CachedSupplier;\nimpo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/text/font/BuiltinFonts.java",
"chars": 1264,
"preview": "package net.darkhax.bookshelf.common.api.text.font;\n\nimport net.minecraft.resources.ResourceLocation;\n\nimport java.util."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/text/font/IFontEntry.java",
"chars": 1125,
"preview": "package net.darkhax.bookshelf.common.api.text.font;\n\nimport net.darkhax.bookshelf.common.api.util.TextHelper;\nimport net"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/text/format/IPropertyFormat.java",
"chars": 924,
"preview": "package net.darkhax.bookshelf.common.api.text.format;\n\nimport net.darkhax.bookshelf.common.api.util.TextHelper;\nimport n"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/text/format/PropertyFormat.java",
"chars": 1147,
"preview": "package net.darkhax.bookshelf.common.api.text.format;\n\nimport net.darkhax.bookshelf.common.impl.Constants;\nimport net.mi"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/text/unit/IUnit.java",
"chars": 2162,
"preview": "package net.darkhax.bookshelf.common.api.text.unit;\n\nimport net.darkhax.bookshelf.common.api.text.format.PropertyFormat;"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/text/unit/Units.java",
"chars": 671,
"preview": "package net.darkhax.bookshelf.common.api.text.unit;\n\nimport net.darkhax.bookshelf.common.impl.Constants;\nimport net.mine"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/CommandHelper.java",
"chars": 4903,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport com.mojang.brigadier.arguments.BoolArgumentType;\nimport com.mojan"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/DataHelper.java",
"chars": 4609,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport com.mojang.serialization.MapCodec;\nimport io.netty.buffer.ByteBuf"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/ExperienceHelper.java",
"chars": 5074,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport net.minecraft.world.entity.player.Player;\n\npublic final class Exp"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/FunctionHelper.java",
"chars": 1034,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport com.mojang.datafixers.util.Either;\n\nimport java.util.Optional;\nim"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/IGameplayHelper.java",
"chars": 6014,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/IPlatformHelper.java",
"chars": 2933,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport net.darkhax.bookshelf.common.api.ModEntry;\nimport net.darkhax.boo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/IRenderHelper.java",
"chars": 8465,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport com.mojang.blaze3d.ve"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/MathsHelper.java",
"chars": 10823,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport net.minecraft.core.BlockPos;\nimport net.minecraft.core.Direction;"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/TextHelper.java",
"chars": 22211,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport net.darkhax.bookshelf.common.api.PhysicalSide;\nimport net.darkhax"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/api/util/TickAccumulator.java",
"chars": 1944,
"preview": "package net.darkhax.bookshelf.common.api.util;\n\nimport net.minecraft.world.level.Level;\n\n/**\n * While the current tick r"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/BookshelfContent.java",
"chars": 7319,
"preview": "package net.darkhax.bookshelf.common.impl;\n\nimport com.mojang.brigadier.CommandDispatcher;\nimport com.mojang.brigadier.b"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/BookshelfMod.java",
"chars": 2023,
"preview": "package net.darkhax.bookshelf.common.impl;\n\nimport net.darkhax.bookshelf.common.api.service.Services;\n\nimport java.io.IO"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/Constants.java",
"chars": 963,
"preview": "package net.darkhax.bookshelf.common.impl;\n\nimport com.google.gson.Gson;\nimport com.google.gson.GsonBuilder;\nimport net."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/DebugContentProvider.java",
"chars": 3454,
"preview": "package net.darkhax.bookshelf.common.impl;\n\nimport net.darkhax.bookshelf.common.api.entity.villager.MerchantTier;\nimport"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/BlockTagToItemTagCommand.java",
"chars": 2505,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.google.gson.JsonArray;\nimport com.google.gson.JsonObject;"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/DebugCommands.java",
"chars": 6602,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.builder.LiteralArgumentBuilder;\nimport c"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/EnchantCommand.java",
"chars": 2545,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.arg"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/FontCommand.java",
"chars": 5940,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.builder.LiteralArgumentBuilder;\nimport c"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/HandCommand.java",
"chars": 5105,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.bui"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/RenameCommand.java",
"chars": 1228,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.bui"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/StructureCommand.java",
"chars": 2961,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.bui"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/command/TranslateCommand.java",
"chars": 931,
"preview": "package net.darkhax.bookshelf.common.impl.command;\n\nimport com.mojang.brigadier.Command;\nimport com.mojang.brigadier.arg"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/And.java",
"chars": 1671,
"preview": "package net.darkhax.bookshelf.common.impl.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojang."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/ModLoaded.java",
"chars": 1783,
"preview": "package net.darkhax.bookshelf.common.impl.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojang."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/Not.java",
"chars": 1669,
"preview": "package net.darkhax.bookshelf.common.impl.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojang."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/OnPlatform.java",
"chars": 1679,
"preview": "package net.darkhax.bookshelf.common.impl.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojang."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/Or.java",
"chars": 1671,
"preview": "package net.darkhax.bookshelf.common.impl.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojang."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/conditions/RegistryContains.java",
"chars": 2298,
"preview": "package net.darkhax.bookshelf.common.impl.data.conditions;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojang."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/criterion/item/NamespaceItemPredicate.java",
"chars": 873,
"preview": "package net.darkhax.bookshelf.common.impl.data.criterion.item;\n\nimport com.mojang.serialization.Codec;\nimport com.mojang"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/criterion/trigger/AdvancementTrigger.java",
"chars": 1790,
"preview": "package net.darkhax.bookshelf.common.impl.data.criterion.trigger;\n\nimport com.mojang.serialization.Codec;\nimport com.moj"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/AllOfIngredient.java",
"chars": 1367,
"preview": "package net.darkhax.bookshelf.common.impl.data.ingredient;\n\nimport com.mojang.serialization.MapCodec;\nimport net.darkhax"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/BlockTagIngredient.java",
"chars": 2415,
"preview": "package net.darkhax.bookshelf.common.impl.data.ingredient;\n\nimport com.mojang.serialization.MapCodec;\nimport net.darkhax"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/EitherIngredient.java",
"chars": 1373,
"preview": "package net.darkhax.bookshelf.common.impl.data.ingredient;\n\nimport com.mojang.serialization.MapCodec;\nimport net.darkhax"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/FalseIngredient.java",
"chars": 1298,
"preview": "package net.darkhax.bookshelf.common.impl.data.ingredient;\n\nimport com.google.gson.JsonObject;\nimport com.mojang.seriali"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/ingredient/ModIdIngredient.java",
"chars": 1413,
"preview": "package net.darkhax.bookshelf.common.impl.data.ingredient;\n\nimport com.mojang.serialization.Codec;\nimport com.mojang.ser"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/entries/LootItemStack.java",
"chars": 2549,
"preview": "package net.darkhax.bookshelf.common.impl.data.loot.entries;\n\nimport com.mojang.serialization.MapCodec;\nimport com.mojan"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/modifiers/FingerprintCodec.java",
"chars": 1609,
"preview": "package net.darkhax.bookshelf.common.impl.data.loot.modifiers;\n\nimport com.google.gson.JsonElement;\nimport com.mojang.da"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/modifiers/ILootPoolHooks.java",
"chars": 449,
"preview": "package net.darkhax.bookshelf.common.impl.data.loot.modifiers;\n\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * Inter"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/data/loot/modifiers/LootModificationHandler.java",
"chars": 5025,
"preview": "package net.darkhax.bookshelf.common.impl.data.loot.modifiers;\n\nimport net.darkhax.bookshelf.common.api.data.loot.modifi"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/recipe/RecipeTypeImpl.java",
"chars": 445,
"preview": "package net.darkhax.bookshelf.common.impl.recipe;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.minecraft"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/BlockEntityRendererAdapter.java",
"chars": 624,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.minecraft.client.renderer.blockentity.BlockEntit"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/BlockRegistryAdapter.java",
"chars": 2495,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/BlockRenderTypeAdapter.java",
"chars": 378,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.minecraft.client.renderer.RenderType;\nimport net"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/CommandArgumentAdapter.java",
"chars": 1139,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport com.mojang.brigadier.arguments.ArgumentType;\nimport "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/CreativeModeTabAdapter.java",
"chars": 2128,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/IngredientTypeAdapter.java",
"chars": 2229,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport com.mojang.serialization.MapCodec;\nimport net.darkha"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/LootDescriptionAdapter.java",
"chars": 351,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.loot.LootPoolEntryD"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/LootEntryTypeAdapter.java",
"chars": 1045,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport com.mojang.serialization.MapCodec;\nimport net.darkha"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/LootPoolAdditionAdapter.java",
"chars": 3047,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.data.loot.PoolTarge"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/MenuScreenAdapter.java",
"chars": 913,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.minecraft.client.gui.screens.Screen;\nimport net."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/MenuTypeAdapter.java",
"chars": 932,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/PacketAdapter.java",
"chars": 539,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.network.IPacket;\nim"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/PotPatternAdapter.java",
"chars": 2563,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/PotionBrewAdapter.java",
"chars": 96,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\npublic class PotionBrewAdapter {\n}\n"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/RecipeTypeAdapter.java",
"chars": 1133,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/SoundEventAdapter.java",
"chars": 975,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport net.darkhax.bookshelf.common.api.registry.Registrati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/registry/adapter/VillagerTradeAdapter.java",
"chars": 3670,
"preview": "package net.darkhax.bookshelf.common.impl.registry.adapter;\n\nimport com.google.common.collect.ArrayListMultimap;\nimport "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/impl/resources/ExtendedText.java",
"chars": 2029,
"preview": "package net.darkhax.bookshelf.common.impl.resources;\n\nimport net.darkhax.bookshelf.common.api.ModEntry;\nimport net.darkh"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorBannerBlockEntity.java",
"chars": 396,
"preview": "package net.darkhax.bookshelf.common.mixin.access.block;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecr"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorBaseContainerBlockEntity.java",
"chars": 423,
"preview": "package net.darkhax.bookshelf.common.mixin.access.block;\n\nimport net.minecraft.network.chat.Component;\nimport net.minecr"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorBlockEntityRenderers.java",
"chars": 614,
"preview": "package net.darkhax.bookshelf.common.mixin.access.block;\n\nimport net.minecraft.client.renderer.blockentity.BlockEntityRe"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/block/AccessorCropBlock.java",
"chars": 369,
"preview": "package net.darkhax.bookshelf.common.mixin.access.block;\n\nimport net.minecraft.world.level.ItemLike;\nimport net.minecraf"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/AccessorFontManager.java",
"chars": 469,
"preview": "package net.darkhax.bookshelf.common.mixin.access.client;\n\nimport net.minecraft.client.gui.font.FontManager;\nimport net."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/AccessorItemBlockRenderTypes.java",
"chars": 585,
"preview": "package net.darkhax.bookshelf.common.mixin.access.client;\n\nimport net.minecraft.client.renderer.ItemBlockRenderTypes;\nim"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/AccessorMinecraft.java",
"chars": 377,
"preview": "package net.darkhax.bookshelf.common.mixin.access.client;\n\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.c"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/client/gui/AccessorAbstractWidget.java",
"chars": 679,
"preview": "package net.darkhax.bookshelf.common.mixin.access.client.gui;\n\nimport net.minecraft.client.gui.Font;\nimport net.minecraf"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/entity/AccessorEntity.java",
"chars": 373,
"preview": "package net.darkhax.bookshelf.common.mixin.access.entity;\n\nimport net.minecraft.network.chat.HoverEvent;\nimport net.mine"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/level/AccessorRecipeManager.java",
"chars": 520,
"preview": "package net.darkhax.bookshelf.common.mixin.access.level;\n\nimport com.google.common.collect.Multimap;\nimport net.minecraf"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorCompositeEntryBase.java",
"chars": 488,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.world.level.storage.loot.entries.Composite"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorDynamicLoot.java",
"chars": 393,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.min"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootItem.java",
"chars": 830,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.core.Holder;\nimport net.minecraft.world.it"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootPool.java",
"chars": 1111,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.world.level.storage.loot.LootPool;\nimport "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootPoolSingletonContainer.java",
"chars": 435,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.world.level.storage.loot.entries.LootPoolS"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorLootTable.java",
"chars": 730,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.resources.ResourceLocation;\nimport net.min"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorNestedLootTable.java",
"chars": 533,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport com.mojang.datafixers.util.Either;\nimport net.minecraft."
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/loot/AccessorTagEntry.java",
"chars": 458,
"preview": "package net.darkhax.bookshelf.common.mixin.access.loot;\n\nimport net.minecraft.tags.TagKey;\nimport net.minecraft.world.it"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/access/particles/AccessSimpleParticleType.java",
"chars": 446,
"preview": "package net.darkhax.bookshelf.common.mixin.access.particles;\n\nimport net.minecraft.core.particles.SimpleParticleType;\nim"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/advancement/MixinPlayerAdvancements.java",
"chars": 1229,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.advancement;\n\nimport net.darkhax.bookshelf.common.impl.data.criterion.t"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/block/MixinDecoratedPotPatterns.java",
"chars": 1008,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.block;\n\nimport net.darkhax.bookshelf.common.api.registry.RegistrationCo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/client/MixinClientPacketListener.java",
"chars": 1142,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.client;\n\nimport net.darkhax.bookshelf.common.api.data.ISidedRecipeManag"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/entity/MixinLightningBolt.java",
"chars": 1848,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.entity;\n\nimport com.llamalad7.mixinextras.sugar.Local;\nimport net.darkh"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/entity/MixinLivingEntity.java",
"chars": 1499,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.entity;\n\nimport net.darkhax.bookshelf.common.api.data.BookshelfTags;\nim"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/item/MixinCreativeModeTab.java",
"chars": 3012,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.item;\n\nimport net.darkhax.bookshelf.common.api.item.IItemHooks;\nimport "
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/level/MixinRecipeManager.java",
"chars": 1931,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.level;\n\nimport com.google.gson.JsonElement;\nimport net.darkhax.bookshel"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/level/MixinWalkNodeEvaluator.java",
"chars": 1699,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.level;\n\nimport net.darkhax.bookshelf.common.api.block.IBlockHooks;\nimpo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/locale/MixinClientLanguage.java",
"chars": 1028,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.locale;\n\nimport net.darkhax.bookshelf.common.impl.resources.ExtendedTex"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/loot/MixinLootDataType.java",
"chars": 2834,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.loot;\n\nimport com.google.gson.JsonObject;\nimport com.mojang.serializati"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/loot/MixinLootItemKilledByPlayerCondition.java",
"chars": 1404,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.loot;\n\nimport net.darkhax.bookshelf.common.api.data.BookshelfTags;\nimpo"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/loot/MixinLootPool.java",
"chars": 1304,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.loot;\n\nimport com.mojang.serialization.Codec;\nimport net.darkhax.booksh"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/packs/MixinSimpleJsonResourceReloadListener.java",
"chars": 1455,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.packs;\n\nimport com.google.gson.JsonElement;\nimport com.google.gson.Json"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/potions/MixinPotionBrewing.java",
"chars": 684,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.potions;\n\nimport net.darkhax.bookshelf.common.api.service.Services;\nimp"
},
{
"path": "common/src/main/java/net/darkhax/bookshelf/common/mixin/patch/server/MixinReloadableServerResources.java",
"chars": 1137,
"preview": "package net.darkhax.bookshelf.common.mixin.patch.server;\n\nimport net.darkhax.bookshelf.common.api.data.ISidedRecipeManag"
},
{
"path": "common/src/main/resources/META-INF/services/net.darkhax.bookshelf.common.api.registry.ContentProvider",
"chars": 50,
"preview": "net.darkhax.bookshelf.common.impl.BookshelfContent"
},
{
"path": "common/src/main/resources/assets/bookshelf/lang/en_us.json",
"chars": 14057,
"preview": "{\n \"__formatting\": \"\",\n \"format.bookshelf.right\": \"%s: %s\",\n \"format.bookshelf.center\": \"%s : %s\",\n \"format.bookshel"
},
{
"path": "common/src/main/resources/assets/bookshelf/lang/es_ar.json",
"chars": 14781,
"preview": "{\n \"__formatting\": \"\",\n \"format.bookshelf.right\": \"%s: %s\",\n \"format.bookshelf.center\": \"%s : %s\",\n \"format.bookshel"
},
{
"path": "common/src/main/resources/assets/bookshelf/lang/ja_jp.json",
"chars": 12223,
"preview": "{\n \"__formatting\": \"\",\n \"format.bookshelf.right\": \"%s:%s\",\n \"format.bookshelf.center\": \"%s:%s\",\n \"format.bookshelf.l"
},
{
"path": "common/src/main/resources/assets/bookshelf/lang/pt_br.json",
"chars": 14557,
"preview": "{\n \"__formatting\": \"\",\n \"format.bookshelf.right\": \"%s: %s\",\n \"format.bookshelf.center\": \"%s : %s\",\n \"format.bookshel"
},
{
"path": "common/src/main/resources/assets/bookshelf/lang/zh_cn.json",
"chars": 3414,
"preview": "{\n \"__formatting\": \"\",\n \"format.bookshelf.right\": \"%s: %s\",\n \"format.bookshelf.center\": \"%s : %s\",\n \"format.bookshel"
},
{
"path": "common/src/main/resources/bookshelf.mixins.json",
"chars": 1731,
"preview": "{\n \"required\": true,\n \"minVersion\": \"0.8\",\n \"package\": \"net.darkhax.bookshelf.common.mixin\",\n \"refmap\": \"${mod_id}.r"
},
{
"path": "common/src/main/resources/data/bookshelf/damage_type/fake_player.json",
"chars": 98,
"preview": "{\n \"exhaustion\": 0.1,\n \"message_id\": \"player\",\n \"scaling\": \"when_caused_by_living_non_player\"\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/damage_type/fake_player.json",
"chars": 393,
"preview": "{\n \"comments\": [\n \"Damage types in this tag are considered fake player damage. Fake player \",\n \"damage acts like"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/building_blocks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/colored_blocks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/combat.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/food_and_drinks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/functional_blocks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/ingredients.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/natural_blocks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/op_blocks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/redstone_blocks.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/spawn_eggs.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/data/bookshelf/tags/item/creative_tab/minecraft/tools_and_utilities.json",
"chars": 21,
"preview": "{\n \"values\": [\n ]\n}"
},
{
"path": "common/src/main/resources/pack.mcmeta",
"chars": 86,
"preview": "{\n \"pack\": {\n \"description\": \"${mod_name}\",\n \"pack_format\": 8\n }\n}"
},
{
"path": "fabric/build.gradle",
"chars": 3783,
"preview": "plugins {\r\n id 'multiloader-loader'\r\n id 'fabric-loom'\r\n id 'net.darkhax.curseforgegradle'\r\n id 'com.modrint"
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/FabricMod.java",
"chars": 1327,
"preview": "package net.darkhax.bookshelf.fabric.impl;\n\nimport net.darkhax.bookshelf.common.api.service.Services;\nimport net.darkhax"
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/FabricModClient.java",
"chars": 214,
"preview": "package net.darkhax.bookshelf.fabric.impl;\n\nimport net.fabricmc.api.ClientModInitializer;\n\npublic class FabricModClient "
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/data/FabricIngredient.java",
"chars": 2452,
"preview": "package net.darkhax.bookshelf.fabric.impl.data;\n\nimport com.mojang.serialization.MapCodec;\nimport net.darkhax.bookshelf."
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/network/FabricNetworkHandler.java",
"chars": 3330,
"preview": "package net.darkhax.bookshelf.fabric.impl.network;\n\nimport net.darkhax.bookshelf.common.api.network.INetworkHandler;\nimp"
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricGameplayHelper.java",
"chars": 2448,
"preview": "package net.darkhax.bookshelf.fabric.impl.util;\n\nimport net.darkhax.bookshelf.common.api.util.IGameplayHelper;\nimport ne"
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricPlatformHelper.java",
"chars": 2094,
"preview": "package net.darkhax.bookshelf.fabric.impl.util;\n\nimport net.darkhax.bookshelf.common.api.ModEntry;\nimport net.darkhax.bo"
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricRegistryHelper.java",
"chars": 10867,
"preview": "package net.darkhax.bookshelf.fabric.impl.util;\n\nimport com.google.common.collect.Multimap;\nimport it.unimi.dsi.fastutil"
},
{
"path": "fabric/src/main/java/net/darkhax/bookshelf/fabric/impl/util/FabricRenderHelper.java",
"chars": 1431,
"preview": "package net.darkhax.bookshelf.fabric.impl.util;\n\nimport com.mojang.blaze3d.vertex.PoseStack;\nimport net.darkhax.bookshel"
},
{
"path": "fabric/src/main/resources/META-INF/services/net.darkhax.bookshelf.common.api.network.INetworkHandler",
"chars": 62,
"preview": "net.darkhax.bookshelf.fabric.impl.network.FabricNetworkHandler"
},
{
"path": "fabric/src/main/resources/META-INF/services/net.darkhax.bookshelf.common.api.util.IGameplayHelper",
"chars": 59,
"preview": "net.darkhax.bookshelf.fabric.impl.util.FabricGameplayHelper"
}
]
// ... and 25 more files (download for full content)
About this extraction
This page contains the full source code of the Darkhax-Minecraft/Bookshelf GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 225 files (544.4 KB), approximately 136.0k tokens, and a symbol index with 821 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.