Compare commits

...
33 Commits
Author SHA1 Message Date
LexManos 4f2f5c02a0 1.19.2 RB 2022-08-17 14:58:14 -07:00
agnor99 7a6843fa4a Added ItemDecorator API (#8794) 2022-08-17 23:39:56 +02:00
한현빈 f0ecf16c6b [1.19.x] Custom usage animations for items (#8932) 2022-08-17 23:08:13 +02:00
Take Weiland 8998fa71b2 Allow registering custom ColorResolvers (#8880) 2022-08-17 22:51:05 +02:00
Dennis C 4e677a7558 [1.19] Allow custom outline rendering on EntityRenderers and BlockEntityRenderers (#8938) 2022-08-17 00:01:33 +02:00
sciwhiz12 07254b36d7 Redirect checks for entity selector use to a permission (#8947)
This allows greater flexibility for configuring servers with
operator-like permissions to user groups through the permissions API and
their permissions handler of choice without needing to grant the
vanilla operator permission to any player.

The new permission is "forge:use_entity_selectors", which is granted by
default to players with permission level 2 (GAMEMASTERS) and above.

The hook falls back to checking the permission level if the source of
the command is not a ServerPlayer, such as for command blocks and
functions.
2022-08-16 14:11:54 -07:00
Brennan Ward a51b8d256d Allow FakePlayer to report its position (#8963) 2022-08-16 14:09:09 -07:00
Sara Freimer 75fcd9448e Add alternate version of renderEntityInInventory to allow for directly specifying the angles (#8961) 2022-08-16 13:57:30 -07:00
eerussianguy 6b45999702 Add cancellable ToastAddEvent (#8952) 2022-08-16 13:48:55 -07:00
eerussianguy a4f52f4057 Modify ScreenEvent.RenderInventoryMobEffects to allow moving the effect stack left or right (#8951) 2022-08-16 13:47:57 -07:00
Brennan Ward b8b3201372 Fix Enchantment#doPostHurt and Enchantment#doPostAttack being called twice for players. Fixes MC-248272 (#8948) 2022-08-16 13:40:10 -07:00
LexManos 41deadc1e2 Remove reflective implementation of ICustomPacket. (#8973)
Make vanilla custom packets able to be sent multiple times. Closes #8969
2022-08-16 13:17:25 -07:00
LexManos 82e8d06e54 Filter name spaces to directories only. Closes #8413 2022-08-14 12:22:38 -07:00
Marc Hermans 51db5f2ff7 Fix a corner case where the UMLB can not extract a version from a library. (#8967) 2022-08-14 12:18:22 -07:00
Alex O'Neill 2ec9e515ff Fix worlds with removed dimension types unable to load. (#8959) Closes #8800 2022-08-14 12:17:22 -07:00
Alex O'Neill 0579572148 Fix issue where unknown chunk generators would cause DFU to fail. (#8957) 2022-08-10 23:13:44 -07:00
TheMuso 83f4e6353c Fix comments and documentation that were missed during the review of #8712 (#8945) 2022-08-09 12:49:00 -07:00
Luis 130953e519 Make AnvilUpdateEvent fire even if the second input is empty, which means it fires even if only changing the item name. (#8905) 2022-08-09 12:48:46 -07:00
Sirttas 7981093591 Fix LivingEntity#isBlocking to use ToolActions#SHIELD_BLOCK instead of UseAnim#BLOCK (#8933) 2022-08-09 12:27:26 -07:00
Joseph B 79112d6208 Add Custom HolderSet Types allowing for logical combining of sets. (#8928) 2022-08-09 12:25:12 -07:00
Sara Freimer a3eb6263f4 Add values to VersionSupportMatrix to support loading mods that restrict versions to 1.19.1 on 1.19.2 (#8946) 2022-08-09 12:15:58 -07:00
Redstone_Dubstep d91bc9c73d Fix certain particles not updating their bounding box when their position changes (#8925) 2022-08-08 15:09:13 +02:00
LexManos c807665ab9 Update EventBus to address concurrency issue in ModLauncher Factory. Closes #8924 2022-08-07 17:35:15 -07:00
LexManos 7b97c181b9 1.19.2 2022-08-05 16:35:02 -07:00
Brennan Ward c42b0847d2 Remove calls to getStepHeight in Player#maybeBackOffFromEdge (#8927) 2022-08-05 11:35:47 -07:00
Sirttas f182cb00c1 Add forge tags for tools and armors, these DO NOT replace ToolActions, and are designed just for Recipes. (#8914) 2022-08-05 11:32:53 -07:00
J.T. McQuigg 3181b5da23 Add Biomes.BEACH to Tags (#8892) 2022-08-05 11:31:32 -07:00
Mysticdrew 983c119477 Let NetworkInstance.isRemotePresent check minecraft:register for channel IDs. (#8921) 2022-08-05 11:31:11 -07:00
Sara Freimer 874ff1bba2 Add an event for when the chunk ticket level is updated (#8909) 2022-08-05 11:21:14 -07:00
TheMuso 06d9d89f98 Re-add PotentialSpawns event (#8712) 2022-08-05 09:29:02 -07:00
Dennis C c713bad8c3 Fix misplaced patch in ItemEntityRenderer breaking ItemEntityRenderer#shouldBob() (#8919) 2022-08-04 22:14:28 -07:00
Marc Hermans fe19491822 [1.19] [HotFix] Fix the dedicated server not having access to the JiJ filesystems. (#8931) 2022-08-03 22:32:32 +01:00
SizableShrimp c80e8a1aca Match Mojang's action bar fix for MC-72687 (#8917) 2022-07-29 01:09:33 -07:00
119 changed files with 2569 additions and 240 deletions

No files matched your search

+8 -6
View File
@@ -36,14 +36,14 @@ ext {
]
}
MAPPING_CHANNEL = 'official'
MAPPING_VERSION = '1.19.1'
MC_VERSION = '1.19.1'
MAPPING_VERSION = '1.19.2'
MC_VERSION = '1.19.2'
MC_NEXT_VERSION = '1.20'
MCP_VERSION = '20220727.212338'
MCP_VERSION = '20220805.130853'
SPI_VERSION = '6.0.0'
ACCESSTRANSFORMERS_VERSION = '8.0.4'
COREMODS_VERSION = '5.0.1'
EVENTBUS_VERSION = '6.0.0'
EVENTBUS_VERSION = '6.0.3'
MODLAUNCHER_VERSION = '10.0.8'
SECUREJARHANDLER_VERSION = '2.1.4'
BOOTSTRAPLAUNCHER_VERSION = '1.1.2'
@@ -66,7 +66,7 @@ ext {
APACHE_COMMONS_LANG3_VERSION = '3.12.0'
JOPT_SIMPLE_VERSION = '5.0.4'
COMMONS_IO_VERSION = '2.11.0'
JARJAR_VERSION = '0.3.9'
JARJAR_VERSION = '0.3.16'
GIT_INFO = gradleutils.gitInfo
VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, '[0-9]', MC_VERSION)
@@ -262,6 +262,7 @@ def sharedDeps = {
moduleonly "org.ow2.asm:asm-util:${ASM_VERSION}"
moduleonly "org.ow2.asm:asm-analysis:${ASM_VERSION}"
moduleonly "cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}"
moduleonly "net.minecraftforge:JarJarFileSystems:${JARJAR_VERSION}"
installer "cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}"
installer "org.ow2.asm:asm:${ASM_VERSION}"
@@ -285,7 +286,8 @@ def sharedDeps = {
installer "org.jline:jline-terminal:${JLINE_VERSION}" // Dep of TerminalConsoleAppender
installer "org.spongepowered:mixin:${MIXIN_VERSION}"
installer 'org.openjdk.nashorn:nashorn-core:15.3'
installer "net.minecraftforge:JarJar:${JARJAR_VERSION}"
installer "net.minecraftforge:JarJarSelector:${JARJAR_VERSION}"
installer "net.minecraftforge:JarJarMetadata:${JARJAR_VERSION}"
/*
installer 'org.lwjgl:lwjgl:3.2.2'
+2 -2
View File
@@ -2,8 +2,8 @@
MinecraftForge
=============
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.19-&query=$.promos["1.19-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)](https://files.minecraftforge.net)
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.19-&query=$.promos["1.19-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.19-&query=$.promos["1.19.2-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)](https://files.minecraftforge.net)
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.19.2-&query=$.promos["1.19.2-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
)](https://files.minecraftforge.net) [![Discord](https://img.shields.io/discord/313125603924639766.svg?color=%237289da&label=Discord&logo=discord&logoColor=%237289da)](https://discord.gg/UvedJ9m) [![Support](https://img.shields.io/badge/Patreon-Support-orange.svg?logo=Patreon)](https://www.patreon.com/LexManos)
Forge is a free, open-source modding API all of your favourite mods use!
+2 -1
View File
@@ -28,7 +28,8 @@ dependencies {
api("cpw.mods:modlauncher:${MODLAUNCHER_VERSION}")
api("net.minecraftforge:coremods:${COREMODS_VERSION}")
api("com.mojang:logging:${MOJANG_LOGGING_VERSION}")
api "net.minecraftforge:JarJar:${JARJAR_VERSION}"
api "net.minecraftforge:JarJarSelector:${JARJAR_VERSION}"
api "net.minecraftforge:JarJarMetadata:${JARJAR_VERSION}"
implementation("net.sf.jopt-simple:jopt-simple:${JOPT_SIMPLE_VERSION}")
implementation("cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}")
@@ -106,16 +106,17 @@ public class UniqueModListBuilder
if (modInfoList.size() > 1) {
LOGGER.debug("Found {} mods for first modid {}, selecting most recent based on version data", modInfoList.size(), fullList.getKey());
modInfoList.sort(Comparator.comparing(this::getVersion).reversed());
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.get(0).getFileName(), fullList.getKey(), modInfoList.get(0).getModInfos().get(0).getVersion());
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.get(0).getFileName(), fullList.getKey(), this.getVersion(modInfoList.get(0)));
}
return modInfoList.get(0);
}
private ArtifactVersion getVersion(final ModFile mf)
{
if (mf.getModFileInfo() == null) {
if (mf.getModFileInfo() == null || mf.getModInfos() == null || mf.getModInfos().isEmpty()) {
return mf.getJarVersion();
}
return mf.getModInfos().get(0).getVersion();
}
@@ -5,6 +5,7 @@
package net.minecraftforge.fml.loading;
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
@@ -18,16 +19,12 @@ public class VersionSupportMatrix {
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
static {
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
// if (MavenVersionAdapter.createFromVersionSpec("[1.16.4,1.16.5]").containsVersion(version)) {
// // 1.16.4 is Compatible with 1.16.3
// add("languageloader.javafml", "34");
// add("mod.minecraft", "1.16.3");
// add("mod.forge", "34.1.42");
// // 1.16.5 is Compatible with 1.16.4, and thus 1.16.3
// add("languageloader.javafml", "35");
// add("mod.minecraft", "1.16.4");
// add("mod.forge", "35.1.37");
// }
if (MavenVersionAdapter.createFromVersionSpec("[1.19.2]").containsVersion(version)) {
// 1.19.2 is Compatible with 1.19.1
add("languageloader.javafml", "42");
add("mod.minecraft", "1.19.1");
add("mod.forge", "42.0.9");
}
}
private static void add(String key, String value) {
overrideVersions.computeIfAbsent(key, k -> new ArrayList<>()).add(new DefaultArtifactVersion(value));
@@ -46,7 +46,6 @@ public class JarInJarDependencyLocator extends AbstractJarFileDependencyLocator
final List<IModFile> sources = Lists.newArrayList();
loadedMods.forEach(sources::add);
final List<IModFile> dependenciesToLoad = JarSelector.detectAndSelect(sources, this::loadResourceFromModFile, this::loadModFileFrom, this::identifyMod, this::exception);
if (dependenciesToLoad.isEmpty())
@@ -38,7 +38,7 @@ public class FMLModContainer extends ModContainer
LOGGER.debug(LOADING,"Creating FMLModContainer instance for {}", className);
this.scanResults = modFileScanResults;
activityMap.put(ModLoadingStage.CONSTRUCT, this::constructMod);
this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).build();
this.eventBus = BusBuilder.builder().setExceptionHandler(this::onEventFailed).setTrackPhases(false).markerType(IModBusEvent.class).useModLauncher().build();
this.configHandler = Optional.of(ce->this.eventBus.post(ce.self()));
final FMLJavaModLoadingContext contextExtension = new FMLJavaModLoadingContext(this);
this.contextExtension = () -> contextExtension;
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/Minecraft.java
+++ b/net/minecraft/client/Minecraft.java
@@ -243,7 +_,7 @@
@@ -244,7 +_,7 @@
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
@@ -9,7 +9,7 @@
static Minecraft f_90981_;
private static final Logger f_90982_ = LogUtils.getLogger();
public static final boolean f_91002_ = Util.m_137581_() == Util.OS.OSX;
@@ -397,7 +_,7 @@
@@ -398,7 +_,7 @@
this.f_91029_ = p_91084_.f_101908_.f_101928_;
this.f_90986_ = p_91084_.f_101905_.f_101944_;
this.f_91037_ = new ClientPackSource(new File(this.f_91069_, "server-resource-packs"), p_91084_.f_101907_.m_101925_());
@@ -18,7 +18,7 @@
this.f_91030_ = p_91084_.f_101905_.f_101945_;
this.f_231338_ = new YggdrasilAuthenticationService(this.f_91030_);
this.f_91048_ = this.f_231338_.createMinecraftSessionService();
@@ -405,7 +_,6 @@
@@ -406,7 +_,6 @@
this.f_231339_ = SignatureValidator.m_216358_(this.f_231338_.getServicesKey());
this.f_90998_ = p_91084_.f_101905_.f_101942_;
f_90982_.info("Setting user: {}", (Object)this.f_90998_.m_92546_());
@@ -26,7 +26,7 @@
this.f_91033_ = p_91084_.f_101908_.f_101926_;
this.f_91034_ = !p_91084_.f_101908_.f_101929_;
this.f_91035_ = !p_91084_.f_101908_.f_101930_;
@@ -457,7 +_,7 @@
@@ -458,7 +_,7 @@
this.f_90990_.m_85380_(this.f_91066_.m_232035_().m_231551_());
this.f_91067_ = new MouseHandler(this);
@@ -35,7 +35,7 @@
this.f_91068_ = new KeyboardHandler(this);
this.f_91068_.m_90887_(this.f_90990_.m_85439_());
RenderSystem.m_69580_(this.f_91066_.f_92035_, false);
@@ -465,6 +_,7 @@
@@ -466,6 +_,7 @@
this.f_91042_.m_83931_(0.0F, 0.0F, 0.0F, 0.0F);
this.f_91042_.m_83954_(f_91002_);
this.f_91036_ = new ReloadableResourceManager(PackType.CLIENT_RESOURCES);
@@ -43,7 +43,7 @@
this.f_91038_.m_10506_();
this.f_91066_.m_92145_(this.f_91038_);
this.f_91039_ = new LanguageManager(this.f_91066_.f_92075_);
@@ -509,10 +_,12 @@
@@ -510,10 +_,12 @@
this.f_91063_ = new GameRenderer(this, this.f_90994_.m_234586_(), this.f_91036_, this.f_90993_);
this.f_91036_.m_7217_(this.f_91063_);
this.f_91060_ = new LevelRenderer(this, this.f_90994_, this.f_167845_, this.f_90993_);
@@ -56,7 +56,7 @@
this.f_91036_.m_7217_(this.f_91061_);
this.f_91053_ = new PaintingTextureManager(this.f_90987_);
this.f_91036_.m_7217_(this.f_91053_);
@@ -521,7 +_,9 @@
@@ -522,7 +_,9 @@
this.f_91047_ = new GpuWarnlistManager();
this.f_91036_.m_7217_(this.f_91047_);
this.f_91036_.m_7217_(this.f_205120_);
@@ -67,7 +67,7 @@
this.f_91064_ = new DebugRenderer(this);
this.f_238717_ = new RealmsDataFetcher(RealmsClient.m_239151_(this));
RenderSystem.m_69900_(this::m_91113_);
@@ -540,6 +_,19 @@
@@ -541,6 +_,21 @@
TinyFileDialogs.tinyfd_messageBox("Minecraft", stringbuilder.toString(), "ok", "error", false);
}
@@ -83,11 +83,13 @@
+ net.minecraftforge.client.gui.overlay.GuiOverlayManager.init();
+ net.minecraftforge.client.DimensionSpecialEffectsManager.init();
+ net.minecraftforge.client.NamedRenderTypeManager.init();
+ net.minecraftforge.client.ColorResolverManager.init();
+ net.minecraftforge.client.ItemDecoratorHandler.init();
+
this.f_90990_.m_85409_(this.f_91066_.m_231817_().m_231551_());
this.f_90990_.m_85424_(this.f_91066_.m_232123_().m_231551_());
this.f_90990_.m_85426_();
@@ -562,23 +_,23 @@
@@ -563,23 +_,23 @@
}
this.f_167847_.m_168556_();
@@ -126,7 +128,7 @@
}
@@ -621,6 +_,8 @@
@@ -622,6 +_,8 @@
private UserApiService m_193585_(YggdrasilAuthenticationService p_193586_, GameConfig p_193587_) {
try {
@@ -135,7 +137,7 @@
return p_193586_.createUserApiService(p_193587_.f_101905_.f_101942_.m_92547_());
} catch (AuthenticationException authenticationexception) {
f_90982_.error("Failed to verify authentication", (Throwable)authenticationexception);
@@ -633,7 +_,7 @@
@@ -634,7 +_,7 @@
}
private void m_91239_(Throwable p_91240_) {
@@ -144,7 +146,7 @@
this.m_91241_(p_91240_, (Component)null);
} else {
Util.m_137559_(p_91240_);
@@ -791,13 +_,13 @@
@@ -792,13 +_,13 @@
Bootstrap.m_135875_(p_91333_.m_127526_());
if (p_91333_.m_127527_() != null) {
Bootstrap.m_135875_("#@!@# Game crashed! Crash report saved to: #@!@# " + p_91333_.m_127527_());
@@ -161,7 +163,7 @@
}
}
@@ -921,10 +_,6 @@
@@ -922,10 +_,6 @@
f_90982_.error("setScreen called from non-game thread");
}
@@ -172,7 +174,7 @@
if (p_91153_ == null && this.f_91073_ == null) {
p_91153_ = new TitleScreen();
} else if (p_91153_ == null && this.f_91074_.m_21224_()) {
@@ -935,6 +_,19 @@
@@ -936,6 +_,19 @@
}
}
@@ -192,7 +194,7 @@
this.f_91080_ = p_91153_;
BufferUploader.m_166835_();
if (p_91153_ != null) {
@@ -1078,11 +_,14 @@
@@ -1079,11 +_,14 @@
RenderSystem.m_69481_();
this.f_91026_.m_7238_();
if (!this.f_91079_) {
@@ -207,7 +209,7 @@
}
if (this.f_91056_ != null) {
@@ -1209,10 +_,12 @@
@@ -1210,10 +_,12 @@
this.f_90990_.m_85378_((double)i);
if (this.f_91080_ != null) {
this.f_91080_.m_6574_(this, this.f_90990_.m_85445_(), this.f_90990_.m_85446_());
@@ -220,7 +222,7 @@
this.f_91063_.m_109097_(this.f_90990_.m_85441_(), this.f_90990_.m_85442_());
this.f_91067_.m_91599_();
}
@@ -1490,6 +_,7 @@
@@ -1491,6 +_,7 @@
}
public void m_91395_() {
@@ -228,7 +230,7 @@
this.f_91019_ = false;
}
@@ -1519,10 +_,18 @@
@@ -1520,10 +_,18 @@
if (p_91387_ && this.f_91077_ != null && this.f_91077_.m_6662_() == HitResult.Type.BLOCK) {
BlockHitResult blockhitresult = (BlockHitResult)this.f_91077_;
BlockPos blockpos = blockhitresult.m_82425_();
@@ -250,7 +252,7 @@
this.f_91074_.m_6674_(InteractionHand.MAIN_HAND);
}
}
@@ -1547,14 +_,20 @@
@@ -1548,14 +_,20 @@
return false;
} else {
boolean flag = false;
@@ -269,22 +271,22 @@
BlockHitResult blockhitresult = (BlockHitResult)this.f_91077_;
BlockPos blockpos = blockhitresult.m_82425_();
- if (!this.f_91073_.m_8055_(blockpos).m_60795_()) {
+ if (!this.f_91073_.m_46859_(blockpos)) {
+ if (!this.f_91073_.m_46859_(blockpos)) {
this.f_91072_.m_105269_(blockpos, blockhitresult.m_82434_());
if (this.f_91073_.m_8055_(blockpos).m_60795_()) {
flag = true;
@@ -1567,8 +_,10 @@
@@ -1568,8 +_,10 @@
}
this.f_91074_.m_36334_();
+ net.minecraftforge.common.ForgeHooks.onEmptyLeftClick(this.f_91074_);
+ net.minecraftforge.common.ForgeHooks.onEmptyLeftClick(this.f_91074_);
}
+ if (inputEvent.shouldSwingHand())
this.f_91074_.m_6674_(InteractionHand.MAIN_HAND);
return flag;
}
@@ -1583,6 +_,11 @@
@@ -1584,6 +_,11 @@
}
for(InteractionHand interactionhand : InteractionHand.values()) {
@@ -296,31 +298,32 @@
ItemStack itemstack = this.f_91074_.m_21120_(interactionhand);
if (this.f_91077_ != null) {
switch (this.f_91077_.m_6662_()) {
@@ -1593,6 +_,7 @@
@@ -1594,13 +_,14 @@
return;
}
+ if(!this.f_91074_.canInteractWith(entityhitresult.m_82443_(), 0)) return; //Forge: Entity may be traced via attack range, but the player may not have sufficient reach. No padding in client code.
+ if(!this.f_91074_.canInteractWith(entityhitresult.m_82443_(), 0)) return; //Forge: Entity may be traced via attack range, but the player may not have sufficient reach. No padding in client code.
InteractionResult interactionresult = this.f_91072_.m_105230_(this.f_91074_, entity, entityhitresult, interactionhand);
if (!interactionresult.m_19077_()) {
interactionresult = this.f_91072_.m_105226_(this.f_91074_, entity, interactionhand);
@@ -1600,6 +_,7 @@
}
if (interactionresult.m_19077_()) {
if (interactionresult.m_19080_()) {
+ if (inputEvent.shouldSwingHand())
- if (interactionresult.m_19080_()) {
+ if (interactionresult.m_19080_() && inputEvent.shouldSwingHand()) {
this.f_91074_.m_6674_(interactionhand);
}
@@ -1612,6 +_,7 @@
@@ -1612,7 +_,7 @@
int i = itemstack.m_41613_();
InteractionResult interactionresult1 = this.f_91072_.m_233732_(this.f_91074_, interactionhand, blockhitresult);
if (interactionresult1.m_19077_()) {
if (interactionresult1.m_19080_()) {
+ if (inputEvent.shouldSwingHand())
- if (interactionresult1.m_19080_()) {
+ if (interactionresult1.m_19080_() && inputEvent.shouldSwingHand()) {
this.f_91074_.m_6674_(interactionhand);
if (!itemstack.m_41619_() && (itemstack.m_41613_() != i || this.f_91072_.m_105290_())) {
this.f_91063_.f_109055_.m_109320_(interactionhand);
@@ -1627,6 +_,9 @@
@@ -1628,6 +_,9 @@
}
}
@@ -330,7 +333,7 @@
if (!itemstack.m_41619_()) {
InteractionResult interactionresult2 = this.f_91072_.m_233721_(this.f_91074_, interactionhand);
if (interactionresult2.m_19077_()) {
@@ -1653,6 +_,8 @@
@@ -1654,6 +_,8 @@
--this.f_91011_;
}
@@ -339,7 +342,7 @@
this.f_91026_.m_6180_("gui");
this.f_240378_.m_240688_();
this.f_91065_.m_193832_(this.f_91012_);
@@ -1782,6 +_,8 @@
@@ -1783,6 +_,8 @@
this.f_91026_.m_6182_("keyboard");
this.f_91068_.m_90931_();
this.f_91026_.m_7238_();
@@ -348,7 +351,7 @@
}
private boolean m_91278_() {
@@ -1976,6 +_,7 @@
@@ -1978,6 +_,7 @@
}
public void m_91156_(ClientLevel p_91157_) {
@@ -356,7 +359,7 @@
ProgressScreen progressscreen = new ProgressScreen(true);
progressscreen.m_6309_(Component.m_237115_("connect.joining"));
this.m_91362_(progressscreen);
@@ -2009,10 +_,12 @@
@@ -2011,10 +_,12 @@
IntegratedServer integratedserver = this.f_91007_;
this.f_91007_ = null;
this.f_91063_.m_109150_();
@@ -369,7 +372,7 @@
if (integratedserver != null) {
this.f_91026_.m_6180_("waitForServer");
@@ -2027,6 +_,7 @@
@@ -2029,6 +_,7 @@
this.f_91065_.m_93089_();
this.f_91008_ = null;
this.f_91010_ = false;
@@ -377,7 +380,7 @@
this.f_91004_.m_90740_();
}
@@ -2122,6 +_,7 @@
@@ -2124,6 +_,7 @@
private void m_91280_() {
if (this.f_91077_ != null && this.f_91077_.m_6662_() != HitResult.Type.MISS) {
@@ -385,7 +388,7 @@
boolean flag = this.f_91074_.m_150110_().f_35937_;
BlockEntity blockentity = null;
HitResult.Type hitresult$type = this.f_91077_.m_6662_();
@@ -2134,10 +_,7 @@
@@ -2136,10 +_,7 @@
}
Block block = blockstate.m_60734_();
@@ -397,7 +400,7 @@
if (flag && Screen.m_96637_() && blockstate.m_155947_()) {
blockentity = this.f_91073_.m_7702_(blockpos);
@@ -2148,7 +_,7 @@
@@ -2150,7 +_,7 @@
}
Entity entity = ((EntityHitResult)this.f_91077_).m_82443_();
@@ -406,7 +409,7 @@
if (itemstack == null) {
return;
}
@@ -2686,8 +_,8 @@
@@ -2688,8 +_,8 @@
return this.f_90993_;
}
@@ -417,7 +420,7 @@
Supplier<PackResources> supplier = p_167937_;
if (i <= 3) {
supplier = m_91330_(p_167937_);
@@ -2697,7 +_,7 @@
@@ -2699,7 +_,7 @@
supplier = m_91352_(supplier);
}
@@ -426,10 +429,12 @@
}
private static Supplier<PackResources> m_91330_(Supplier<PackResources> p_91331_) {
@@ -2716,6 +_,14 @@
this.f_91051_.m_119410_(p_91313_);
}
@@ -2716,6 +_,19 @@
public void m_91312_(int p_91313_) {
this.f_91051_.m_119410_(p_91313_);
+ }
+
+ public ItemColors getItemColors() {
+ return this.f_91041_;
+ }
@@ -438,18 +443,9 @@
+ return this.f_90997_;
+ }
+
public EntityModelSet m_167973_() {
return this.f_167844_;
}
@@ -2789,4 +_,11 @@
public abstract boolean m_142594_(boolean p_168035_);
}
+
+ // FORGE START
+ private float realPartialTick;
+ public float getPartialTick() {
+ return realPartialTick;
+ }
+ // FORGE END
}
}
public EntityModelSet m_167973_() {
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/gui/components/toasts/ToastComponent.java
+++ b/net/minecraft/client/gui/components/toasts/ToastComponent.java
@@ -103,6 +_,7 @@
}
public void m_94922_(Toast p_94923_) {
+ if (net.minecraftforge.client.ForgeHooksClient.onToastAdd(p_94923_)) return;
this.f_94916_.add(p_94923_);
}
@@ -1,12 +1,13 @@
--- a/net/minecraft/client/gui/screens/inventory/EffectRenderingInventoryScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/EffectRenderingInventoryScreen.java
@@ -42,12 +_,16 @@
@@ -42,12 +_,17 @@
if (!collection.isEmpty() && j >= 32) {
RenderSystem.m_157429_(1.0F, 1.0F, 1.0F, 1.0F);
boolean flag = j >= 120;
+ var event = net.minecraftforge.client.ForgeHooksClient.onScreenPotionSize(this, j, !flag);
+ if (event == 0) return; // 0 = cancel rendering
+ flag = event == 2; // 2 = full-size / 1 = compact
+ var event = net.minecraftforge.client.ForgeHooksClient.onScreenPotionSize(this, j, !flag, i);
+ if (event.isCanceled()) return;
+ flag = !event.isCompact();
+ i = event.getHorizontalOffset();
int k = 33;
if (collection.size() > 5) {
k = 132 / (collection.size() - 1);
@@ -0,0 +1,14 @@
--- a/net/minecraft/client/gui/screens/inventory/InventoryScreen.java
+++ b/net/minecraft/client/gui/screens/inventory/InventoryScreen.java
@@ -100,6 +_,11 @@
public static void m_98850_(int p_98851_, int p_98852_, int p_98853_, float p_98854_, float p_98855_, LivingEntity p_98856_) {
float f = (float)Math.atan((double)(p_98854_ / 40.0F));
float f1 = (float)Math.atan((double)(p_98855_ / 40.0F));
+ renderEntityInInventoryRaw(p_98851_, p_98852_, p_98853_, f, f1, p_98856_);
+ }
+ public static void renderEntityInInventoryRaw(int p_98851_, int p_98852_, int p_98853_, float angleXComponent, float angleYComponent, LivingEntity p_98856_) {
+ float f = angleXComponent;
+ float f1 = angleYComponent;
PoseStack posestack = RenderSystem.m_157191_();
posestack.m_85836_();
posestack.m_85837_((double)p_98851_, (double)p_98852_, 1050.0D);
@@ -0,0 +1,60 @@
--- a/net/minecraft/client/model/HumanoidModel.java
+++ b/net/minecraft/client/model/HumanoidModel.java
@@ -264,6 +_,8 @@
case TOOT_HORN:
this.f_102811_.f_104203_ = Mth.m_14036_(this.f_102808_.f_104203_, -1.2F, 1.2F) - 1.4835298F;
this.f_102811_.f_104204_ = this.f_102808_.f_104204_ - ((float)Math.PI / 6F);
+ default:
+ this.f_102816_.applyTransform(this, p_102876_, net.minecraft.world.entity.HumanoidArm.RIGHT);
}
}
@@ -304,6 +_,8 @@
case TOOT_HORN:
this.f_102812_.f_104203_ = Mth.m_14036_(this.f_102808_.f_104203_, -1.2F, 1.2F) - 1.4835298F;
this.f_102812_.f_104204_ = this.f_102808_.f_104204_ + ((float)Math.PI / 6F);
+ default:
+ this.f_102815_.applyTransform(this, p_102879_, net.minecraft.world.entity.HumanoidArm.LEFT);
}
}
@@ -396,7 +_,7 @@
}
@OnlyIn(Dist.CLIENT)
- public static enum ArmPose {
+ public static enum ArmPose implements net.minecraftforge.common.IExtensibleEnum {
EMPTY(false),
ITEM(false),
BLOCK(false),
@@ -411,10 +_,30 @@
private ArmPose(boolean p_102896_) {
this.f_102890_ = p_102896_;
+ this.forgeArmPose = null;
}
public boolean m_102897_() {
return this.f_102890_;
}
+ // FORGE START
+ @javax.annotation.Nullable
+ private final net.minecraftforge.client.IArmPoseTransformer forgeArmPose;
+
+ private ArmPose(boolean twoHanded, @javax.annotation.Nonnull net.minecraftforge.client.IArmPoseTransformer forgeArmPose) {
+ this.f_102890_ = twoHanded;
+ com.google.common.base.Preconditions.checkNotNull(forgeArmPose, "Cannot create new ArmPose with null transformer!");
+ this.forgeArmPose = forgeArmPose;
+ }
+
+ public static ArmPose create(String name, boolean twoHanded, @javax.annotation.Nonnull net.minecraftforge.client.IArmPoseTransformer forgeArmPose) {
+ throw new IllegalStateException("Enum not extended");
+ }
+
+ public <T extends LivingEntity> void applyTransform(HumanoidModel<T> model, T entity, net.minecraft.world.entity.HumanoidArm arm) {
+ com.google.common.base.Preconditions.checkNotNull(this.forgeArmPose, "applyTransform() must not be called on a vanilla ArmPose!");
+ this.forgeArmPose.applyTransform(model, entity, arm);
+ }
+ // FORGE END
}
}
@@ -1,6 +1,13 @@
--- a/net/minecraft/client/multiplayer/ClientLevel.java
+++ b/net/minecraft/client/multiplayer/ClientLevel.java
@@ -121,6 +_,8 @@
@@ -115,12 +_,15 @@
p_194170_.put(BiomeColors.f_108791_, new BlockTintCache((p_194168_) -> {
return this.m_104762_(p_194168_, BiomeColors.f_108791_);
}));
+ net.minecraftforge.client.ColorResolverManager.registerBlockTintCaches(ClientLevel.this, p_194170_);
});
private final ClientChunkCache f_104559_;
private final Deque<Runnable> f_194122_ = Queues.newArrayDeque();
private int f_194123_;
private final BlockStatePredictionHandler f_233599_ = new BlockStatePredictionHandler();
private static final Set<Item> f_194124_ = Set.of(Items.f_42127_, Items.f_151033_);
@@ -1,6 +1,6 @@
--- a/net/minecraft/client/multiplayer/PlayerInfo.java
+++ b/net/minecraft/client/multiplayer/PlayerInfo.java
@@ -84,6 +_,7 @@
@@ -82,6 +_,7 @@
}
protected void m_105317_(GameType p_105318_) {
@@ -1,11 +1,11 @@
--- a/net/minecraft/client/multiplayer/ProfileKeyPairManager.java
+++ b/net/minecraft/client/multiplayer/ProfileKeyPairManager.java
@@ -70,6 +_,8 @@
@@ -76,6 +_,8 @@
this.m_233776_(profilekeypair);
return Optional.of(profilekeypair);
} catch (CryptException | MinecraftClientException | IOException ioexception) {
+ // Forge: The offline user api service always returns a null profile key pair, so let's hide this useless exception if in dev
+ if (net.minecraftforge.fml.loading.FMLLoader.isProduction() || p_233781_ != UserApiService.OFFLINE)
+ if (net.minecraftforge.fml.loading.FMLLoader.isProduction() || this.f_243348_ != UserApiService.OFFLINE)
f_233765_.error("Failed to retrieve profile key pair", (Throwable)ioexception);
this.m_233776_((ProfileKeyPair)null);
return optional;
return p_243401_;
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/particle/EnchantmentTableParticle.java
+++ b/net/minecraft/client/particle/EnchantmentTableParticle.java
@@ -73,6 +_,7 @@
this.f_107212_ = this.f_106461_ + this.f_107215_ * (double)f;
this.f_107213_ = this.f_106462_ + this.f_107216_ * (double)f - (double)(f1 * 1.2F);
this.f_107214_ = this.f_106460_ + this.f_107217_ * (double)f;
+ this.m_107264_(this.f_107212_, this.f_107213_, this.f_107214_); // FORGE: update the particle's bounding box
}
}
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/particle/PortalParticle.java
+++ b/net/minecraft/client/particle/PortalParticle.java
@@ -75,6 +_,7 @@
this.f_107212_ = this.f_107548_ + this.f_107215_ * (double)f2;
this.f_107213_ = this.f_107549_ + this.f_107216_ * (double)f2 + (double)(1.0F - f);
this.f_107214_ = this.f_107547_ + this.f_107217_ * (double)f2;
+ this.m_107264_(this.f_107212_, this.f_107213_, this.f_107214_); // FORGE: update the particle's bounding box
}
}
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/particle/ReversePortalParticle.java
+++ b/net/minecraft/client/particle/ReversePortalParticle.java
@@ -29,6 +_,7 @@
this.f_107212_ += this.f_107215_ * (double)f;
this.f_107213_ += this.f_107216_ * (double)f;
this.f_107214_ += this.f_107217_ * (double)f;
+ this.m_107264_(this.f_107212_, this.f_107213_, this.f_107214_); // FORGE: update the particle's bounding box
}
}
@@ -0,0 +1,10 @@
--- a/net/minecraft/client/particle/VibrationSignalParticle.java
+++ b/net/minecraft/client/particle/VibrationSignalParticle.java
@@ -100,6 +_,7 @@
this.f_107212_ = Mth.m_14139_(d0, this.f_107212_, vec3.m_7096_());
this.f_107213_ = Mth.m_14139_(d0, this.f_107213_, vec3.m_7098_());
this.f_107214_ = Mth.m_14139_(d0, this.f_107214_, vec3.m_7094_());
+ this.m_107264_(this.f_107212_, this.f_107213_, this.f_107214_); // FORGE: update the particle's bounding box
this.f_172460_ = this.f_172462_;
this.f_172462_ = (float)Mth.m_14136_(this.f_107212_ - vec3.m_7096_(), this.f_107214_ - vec3.m_7094_());
}
@@ -24,6 +24,14 @@
boolean flag1 = CrossbowItem.m_40932_(p_109377_);
boolean flag2 = humanoidarm == HumanoidArm.RIGHT;
int i = flag2 ? 1 : -1;
@@ -384,6 +_,7 @@
this.m_109322_(p_109372_, p_109377_, flag2 ? ItemTransforms.TransformType.FIRST_PERSON_RIGHT_HAND : ItemTransforms.TransformType.FIRST_PERSON_LEFT_HAND, !flag2, p_109379_, p_109380_, p_109381_);
} else {
boolean flag3 = humanoidarm == HumanoidArm.RIGHT;
+ if (!net.minecraftforge.client.extensions.common.IClientItemExtensions.of(p_109377_).applyForgeHandTransform(p_109379_, f_109299_.f_91074_, humanoidarm, p_109377_, p_109373_, p_109378_, p_109376_)) // FORGE: Allow items to define custom arm animation
if (p_109372_.m_6117_() && p_109372_.m_21212_() > 0 && p_109372_.m_7655_() == p_109375_) {
int k = flag3 ? 1 : -1;
switch (p_109377_.m_41780_()) {
@@ -487,8 +_,16 @@
this.f_109304_ = Mth.m_14036_(this.f_109304_ - 0.4F, 0.0F, 1.0F);
} else {
@@ -51,6 +51,16 @@
++this.f_109439_;
if (entity.f_19797_ == 0) {
entity.f_19790_ = entity.m_20185_();
@@ -1206,6 +_,9 @@
int i1 = i & 255;
outlinebuffersource.m_109929_(k, l, i1, 255);
} else {
+ if (this.m_109817_() && entity.hasCustomOutlineRendering(this.f_109461_.f_91074_)) { // FORGE: allow custom outline rendering
+ flag3 = true;
+ }
multibuffersource = multibuffersource$buffersource;
}
@@ -1226,6 +_,7 @@
List<BlockEntity> list = levelrenderer$renderchunkinfo.f_109839_.m_112835_().m_112773_();
if (!list.isEmpty()) {
@@ -59,7 +69,17 @@
BlockPos blockpos4 = blockentity1.m_58899_();
MultiBufferSource multibuffersource1 = multibuffersource$buffersource;
p_109600_.m_85836_();
@@ -1251,6 +_,7 @@
@@ -1242,6 +_,9 @@
};
}
}
+ if (this.m_109817_() && blockentity1.hasCustomOutlineRendering(this.f_109461_.f_91074_)) { // FORGE: allow custom outline rendering
+ flag3 = true;
+ }
this.f_172946_.m_112267_(blockentity1, p_109601_, p_109600_, multibuffersource1);
p_109600_.m_85849_();
@@ -1251,9 +_,13 @@
synchronized(this.f_109468_) {
for(BlockEntity blockentity : this.f_109468_) {
@@ -67,6 +87,12 @@
BlockPos blockpos3 = blockentity.m_58899_();
p_109600_.m_85836_();
p_109600_.m_85837_((double)blockpos3.m_123341_() - d0, (double)blockpos3.m_123342_() - d1, (double)blockpos3.m_123343_() - d2);
+ if (this.m_109817_() && blockentity.hasCustomOutlineRendering(this.f_109461_.f_91074_)) { // FORGE: allow custom outline rendering
+ flag3 = true;
+ }
this.f_172946_.m_112267_(blockentity, p_109601_, p_109600_, multibuffersource$buffersource);
p_109600_.m_85849_();
}
@@ -1290,7 +_,8 @@
p_109600_.m_85837_((double)blockpos2.m_123341_() - d0, (double)blockpos2.m_123342_() - d1, (double)blockpos2.m_123343_() - d2);
PoseStack.Pose posestack$pose = p_109600_.m_85850_();
@@ -1,11 +1,12 @@
--- a/net/minecraft/client/renderer/entity/ItemEntityRenderer.java
+++ b/net/minecraft/client/renderer/entity/ItemEntityRenderer.java
@@ -62,17 +_,14 @@
@@ -61,18 +_,15 @@
boolean flag = bakedmodel.m_7539_();
int j = this.m_115042_(itemstack);
float f = 0.25F;
float f1 = Mth.m_14031_(((float)p_115036_.m_32059_() + p_115038_) / 10.0F + p_115036_.f_31983_) * 0.1F + 0.1F;
- float f2 = bakedmodel.m_7442_().m_111808_(ItemTransforms.TransformType.GROUND).f_111757_.m_122260_();
+ float f2 = shouldBob() ? bakedmodel.m_7442_().m_111808_(ItemTransforms.TransformType.GROUND).f_111757_.m_122260_() : 0;
- float f1 = Mth.m_14031_(((float)p_115036_.m_32059_() + p_115038_) / 10.0F + p_115036_.f_31983_) * 0.1F + 0.1F;
+ float f1 = shouldBob() ? Mth.m_14031_(((float)p_115036_.m_32059_() + p_115038_) / 10.0F + p_115036_.f_31983_) * 0.1F + 0.1F : 0;
float f2 = bakedmodel.m_7442_().m_111808_(ItemTransforms.TransformType.GROUND).f_111757_.m_122260_();
p_115039_.m_85837_(0.0D, (double)(f1 + 0.25F * f2), 0.0D);
float f3 = p_115036_.m_32008_(p_115038_);
p_115039_.m_85845_(Vector3f.f_122225_.m_122270_(f3));
@@ -60,6 +60,14 @@
crashreportcategory.m_128165_("Item Damage", () -> {
return String.valueOf(p_174237_.m_41773_());
});
@@ -362,6 +_,7 @@
RenderSystem.m_69482_();
}
+ net.minecraftforge.client.ItemDecoratorHandler.of(p_115176_).render(p_115175_, p_115176_, p_115177_, p_115178_, f_115093_);
}
}
@@ -377,5 +_,9 @@
public void m_6213_(ResourceManager p_115105_) {
@@ -10,7 +10,7 @@
}
public Vec3 m_7860_(AbstractClientPlayer p_117785_, float p_117786_) {
@@ -126,7 +_,7 @@
@@ -126,10 +_,13 @@
if (useanim == UseAnim.TOOT_HORN) {
return HumanoidModel.ArmPose.TOOT_HORN;
}
@@ -19,6 +19,12 @@
return HumanoidModel.ArmPose.CROSSBOW_HOLD;
}
+ HumanoidModel.ArmPose forgeArmPose = net.minecraftforge.client.extensions.common.IClientItemExtensions.of(itemstack).getArmPose(p_117795_, p_117796_, itemstack);
+ if (forgeArmPose != null) return forgeArmPose;
+
return HumanoidModel.ArmPose.ITEM;
}
}
@@ -161,10 +_,12 @@
}
@@ -0,0 +1,11 @@
--- a/net/minecraft/commands/arguments/EntityArgument.java
+++ b/net/minecraft/commands/arguments/EntityArgument.java
@@ -115,7 +_,7 @@
if (s instanceof SharedSuggestionProvider sharedsuggestionprovider) {
StringReader stringreader = new StringReader(p_91483_.getInput());
stringreader.setCursor(p_91483_.getStart());
- EntitySelectorParser entityselectorparser = new EntitySelectorParser(stringreader, sharedsuggestionprovider.m_6761_(2));
+ EntitySelectorParser entityselectorparser = new EntitySelectorParser(stringreader, net.minecraftforge.common.ForgeHooks.canUseEntitySelectors(sharedsuggestionprovider));
try {
entityselectorparser.m_121377_();
@@ -0,0 +1,11 @@
--- a/net/minecraft/commands/arguments/MessageArgument.java
+++ b/net/minecraft/commands/arguments/MessageArgument.java
@@ -134,7 +_,7 @@
}
Component m_232196_(CommandSourceStack p_232197_) throws CommandSyntaxException {
- return this.m_96849_(p_232197_, p_232197_.m_6761_(2));
+ return this.m_96849_(p_232197_, net.minecraftforge.common.ForgeHooks.canUseEntitySelectors(p_232197_));
}
public Component m_96849_(CommandSourceStack p_96850_, boolean p_96851_) throws CommandSyntaxException {
@@ -0,0 +1,11 @@
--- a/net/minecraft/commands/arguments/selector/EntitySelector.java
+++ b/net/minecraft/commands/arguments/selector/EntitySelector.java
@@ -87,7 +_,7 @@
}
private void m_121168_(CommandSourceStack p_121169_) throws CommandSyntaxException {
- if (this.f_121123_ && !p_121169_.m_6761_(2)) {
+ if (this.f_121123_ && !net.minecraftforge.common.ForgeHooks.canUseEntitySelectors(p_121169_)) {
throw EntityArgument.f_91441_.create();
}
}
@@ -0,0 +1,33 @@
--- a/net/minecraft/core/HolderSet.java
+++ b/net/minecraft/core/HolderSet.java
@@ -14,7 +_,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public interface HolderSet<T> extends Iterable<Holder<T>> {
+public interface HolderSet<T> extends Iterable<Holder<T>>, net.minecraftforge.common.extensions.IForgeHolderSet<T> {
Stream<Holder<T>> m_203614_();
int m_203632_();
@@ -120,6 +_,9 @@
public void m_205835_(List<Holder<T>> p_205836_) {
this.f_205830_ = List.copyOf(p_205836_);
+ for (Runnable runnable : this.invalidationCallbacks) {
+ runnable.run(); // FORGE: invalidate listeners when tags rebind
+ }
}
public TagKey<T> m_205839_() {
@@ -144,6 +_,11 @@
public boolean m_207277_(Registry<T> p_211049_) {
return this.f_211044_ == p_211049_;
+ }
+ // FORGE: Keep a list of invalidation callbacks so they can be run when tags rebind
+ private List<Runnable> invalidationCallbacks = new java.util.ArrayList<>();
+ public void addInvalidationListener(Runnable runnable) {
+ invalidationCallbacks.add(runnable);
}
}
}
@@ -25,7 +25,7 @@
}
public ClientboundCustomPayloadPacket(FriendlyByteBuf p_178836_) {
@@ -43,6 +_,7 @@
@@ -43,15 +_,17 @@
} else {
throw new IllegalArgumentException("Payload may not be larger than 1048576 bytes");
}
@@ -33,7 +33,10 @@
}
public void m_5779_(FriendlyByteBuf p_132044_) {
@@ -52,6 +_,7 @@
p_132044_.m_130085_(this.f_132029_);
- p_132044_.writeBytes(this.f_132030_.copy());
+ p_132044_.writeBytes(this.f_132030_.slice()); // Use Slice instead of copy, to not update the read index, allowing packet to be sent multiple times.
}
public void m_5797_(ClientGamePacketListener p_132041_) {
p_132041_.m_7413_(this);
@@ -41,3 +44,12 @@
}
public ResourceLocation m_132042_() {
@@ -61,4 +_,8 @@
public FriendlyByteBuf m_132045_() {
return new FriendlyByteBuf(this.f_132030_.copy());
}
+
+ @Override public int getIndex() { return Integer.MAX_VALUE; }
+ @Override public ResourceLocation getName() { return m_132042_(); }
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return this.f_132030_; }
}
@@ -14,7 +14,16 @@
public void m_5779_(FriendlyByteBuf p_133994_) {
p_133994_.m_130085_(this.f_133980_);
- p_133994_.writeBytes((ByteBuf)this.f_133981_);
+ p_133994_.writeBytes((ByteBuf)this.f_133981_.copy()); //This may be access multiple times, from multiple threads, lets be safe like the S->C packet
+ p_133994_.writeBytes((ByteBuf)this.f_133981_.slice()); // Use Slice instead of copy, to not update the read index, allowing packet to be sent multiple times.
}
public void m_5797_(ServerGamePacketListener p_133992_) {
@@ -43,4 +_,8 @@
public FriendlyByteBuf m_179590_() {
return this.f_133981_;
}
+
+ @Override public int getIndex() { return Integer.MAX_VALUE; }
+ @Override public ResourceLocation getName() { return m_179589_(); }
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return m_179590_(); }
}
@@ -9,3 +9,21 @@
private static final int f_179804_ = 1048576;
private final int f_134745_;
private final ResourceLocation f_134746_;
@@ -30,7 +_,7 @@
public void m_5779_(FriendlyByteBuf p_134757_) {
p_134757_.m_130130_(this.f_134745_);
p_134757_.m_130085_(this.f_134746_);
- p_134757_.writeBytes(this.f_134747_.copy());
+ p_134757_.writeBytes(this.f_134747_.slice()); // Use Slice instead of copy, to not update the read index, allowing packet to be sent multiple times.
}
public void m_5797_(ClientLoginPacketListener p_134754_) {
@@ -48,4 +_,8 @@
public FriendlyByteBuf m_179812_() {
return this.f_134747_;
}
+
+ @Override public int getIndex() { return m_134755_(); }
+ @Override public ResourceLocation getName() { return m_179811_(); }
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return m_179812_(); }
}
@@ -10,3 +10,12 @@
private static final int f_179821_ = 1048576;
private final int f_134825_;
@Nullable
@@ -46,4 +_,8 @@
public FriendlyByteBuf m_179825_() {
return this.f_134826_;
}
+
+ @Override public int getIndex() { return m_179824_(); }
+ @Override public net.minecraft.resources.ResourceLocation getName() { return net.minecraftforge.network.LoginWrapper.WRAPPER; }
+ @org.jetbrains.annotations.Nullable @Override public FriendlyByteBuf getInternalData() { return m_179825_(); }
}
@@ -0,0 +1,45 @@
--- a/net/minecraft/resources/HolderSetCodec.java
+++ b/net/minecraft/resources/HolderSetCodec.java
@@ -20,6 +_,8 @@
private final Codec<Holder<E>> f_206656_;
private final Codec<List<Holder<E>>> f_206657_;
private final Codec<Either<TagKey<E>, List<Holder<E>>>> f_206658_;
+ private final Codec<net.minecraftforge.registries.holdersets.ICustomHolderSet<E>> forgeDispatchCodec;
+ private final Codec<Either<net.minecraftforge.registries.holdersets.ICustomHolderSet<E>, Either<TagKey<E>, List<Holder<E>>>>> combinedCodec;
private static <E> Codec<List<Holder<E>>> m_206667_(Codec<Holder<E>> p_206668_, boolean p_206669_) {
Function<List<Holder<E>>, DataResult<List<Holder<E>>>> function = ExtraCodecs.m_203984_(Holder::m_203376_);
@@ -42,6 +_,10 @@
this.f_206656_ = p_206661_;
this.f_206657_ = m_206667_(p_206661_, p_206662_);
this.f_206658_ = Codec.either(TagKey.m_203886_(p_206660_), this.f_206657_);
+ // FORGE: make registry-specific dispatch codec and make forge-or-vanilla either codec
+ this.forgeDispatchCodec = ExtraCodecs.m_184415_(() -> net.minecraftforge.registries.ForgeRegistries.HOLDER_SET_TYPES.get().getCodec())
+ .dispatch(net.minecraftforge.registries.holdersets.ICustomHolderSet::type, type -> type.makeCodec(p_206660_, p_206661_, p_206662_));
+ this.combinedCodec = new ExtraCodecs.EitherCodec<>(this.forgeDispatchCodec, this.f_206658_);
}
public <T> DataResult<Pair<HolderSet<E>, T>> decode(DynamicOps<T> p_206696_, T p_206697_) {
@@ -49,9 +_,10 @@
Optional<? extends Registry<E>> optional = registryops.m_206826_(this.f_206655_);
if (optional.isPresent()) {
Registry<E> registry = optional.get();
- return this.f_206658_.decode(p_206696_, p_206697_).map((p_206682_) -> {
+ // FORGE: use the wrapped codec to decode custom/tag/list instead of just tag/list
+ return this.combinedCodec.decode(p_206696_, p_206697_).map((p_206682_) -> {
return p_206682_.mapFirst((p_206679_) -> {
- return p_206679_.map(registry::m_203561_, HolderSet::m_205800_);
+ return p_206679_.map(java.util.function.Function.identity(), tagOrList -> tagOrList.map(registry::m_203561_, HolderSet::m_205800_));
});
});
}
@@ -68,6 +_,9 @@
return DataResult.error("HolderSet " + p_206674_ + " is not valid in current registry set");
}
+ // FORGE: use the dispatch codec to encode custom holdersets, otherwise fall back to vanilla tag/list
+ if (p_206674_ instanceof net.minecraftforge.registries.holdersets.ICustomHolderSet<E> customHolderSet)
+ return this.forgeDispatchCodec.encode(customHolderSet, p_206675_, p_206676_);
return this.f_206658_.encode(p_206674_.m_203440_().mapRight(List::copyOf), p_206675_, p_206676_);
}
}
@@ -0,0 +1,16 @@
--- a/net/minecraft/resources/RegistryLoader.java
+++ b/net/minecraft/resources/RegistryLoader.java
@@ -48,7 +_,12 @@
if (dataresult != null) {
return dataresult;
} else {
- Holder<E> holder = p_214229_.m_214121_(p_214232_);
+ // Prevents an exception from disrupting codec decoding when calling this with prematurely frozen registries - see comment in LevelStorageSource
+ DataResult<Holder<E>> maybeHolder = p_214229_.m_214185_(p_214232_);
+ if (maybeHolder.error().isPresent()) {
+ return maybeHolder;
+ }
+ Holder<E> holder = maybeHolder.result().get();
readcache.f_206803_.put(p_214232_, DataResult.success(holder));
DataResult<Holder<E>> dataresult1;
if (p_214233_.isEmpty()) {
@@ -1,5 +1,13 @@
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -385,6 +_,7 @@
this.f_140140_ = true;
}
+ net.minecraftforge.event.ForgeEventFactory.fireChunkTicketLevelUpdated(this.f_140133_, p_140177_, p_140180_, p_140178_, p_140179_);
return p_140179_;
}
}
@@ -490,6 +_,7 @@
if (this.f_140131_.remove(p_140182_, p_140183_) && p_203002_ != null) {
if (p_203002_ instanceof LevelChunk) {
@@ -67,7 +67,7 @@
this.m_243086_(playerchatmessage1);
}, this.f_9745_);
});
@@ -1375,7 +_,7 @@
@@ -1383,7 +_,7 @@
private CompletableFuture<Component> m_215246_(String p_215247_) {
Component component = Component.m_237113_(p_215247_);
@@ -76,7 +76,7 @@
return !component.equals(p_238202_) ? p_238202_ : null;
});
completablefuture.thenAcceptAsync((p_242747_) -> {
@@ -1524,11 +_,13 @@
@@ -1532,11 +_,13 @@
return;
}
@@ -91,16 +91,16 @@
if (interactionresult.m_19077_()) {
CriteriaTriggers.f_10565_.m_61494_(ServerGamePacketListenerImpl.this.f_9743_, itemstack, entity);
if (interactionresult.m_19080_()) {
@@ -1550,7 +_,7 @@
@@ -1558,6 +_,8 @@
public void m_141994_() {
if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && entity != ServerGamePacketListenerImpl.this.f_9743_) {
- ServerGamePacketListenerImpl.this.f_9743_.m_5706_(entity);
+ if(ServerGamePacketListenerImpl.this.f_9743_.canHit(entity, 3)) ServerGamePacketListenerImpl.this.f_9743_.m_5706_(entity); //Forge: Perform attack range check. Original check was dist < 6, range is 3, so vanilla used padding=3
+ //Forge: Perform attack range check. Original check was dist < 6, range is 3, so vanilla used padding=3
+ if(ServerGamePacketListenerImpl.this.f_9743_.canHit(entity, 3))
ServerGamePacketListenerImpl.this.f_9743_.m_5706_(entity);
} else {
ServerGamePacketListenerImpl.this.m_9942_(Component.m_237115_("multiplayer.disconnect.invalid_entity_attacked"));
ServerGamePacketListenerImpl.f_9744_.warn("Player {} tried to attack an invalid entity", (Object)ServerGamePacketListenerImpl.this.f_9743_.m_7755_().getString());
@@ -1749,6 +_,7 @@
@@ -1757,6 +_,7 @@
}
public void m_7423_(ServerboundCustomPayloadPacket p_9860_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
@@ -69,7 +_,13 @@
@@ -65,7 +_,13 @@
}
public void m_9933_() {
@@ -15,7 +15,7 @@
this.m_10055_();
} else if (this.f_10019_ == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
ServerPlayer serverplayer = this.f_10018_.m_6846_().m_11259_(this.f_10021_.getId());
@@ -194,14 +_,14 @@
@@ -178,14 +_,14 @@
GameProfile gameprofile = this.f_10018_.m_236731_();
if (gameprofile != null && p_10047_.f_238040_().equalsIgnoreCase(gameprofile.getName())) {
this.f_10021_ = gameprofile;
@@ -32,7 +32,7 @@
}
}
@@ -238,7 +_,7 @@
@@ -222,7 +_,7 @@
throw new IllegalStateException("Protocol error", cryptexception);
}
@@ -41,7 +41,7 @@
public void run() {
GameProfile gameprofile = ServerLoginPacketListenerImpl.this.f_10021_;
@@ -246,11 +_,11 @@
@@ -230,11 +_,11 @@
ServerLoginPacketListenerImpl.this.f_10021_ = ServerLoginPacketListenerImpl.this.f_10018_.m_129925_().hasJoinedServer(new GameProfile((UUID)null, gameprofile.getName()), s, this.m_10064_());
if (ServerLoginPacketListenerImpl.this.f_10021_ != null) {
ServerLoginPacketListenerImpl.f_10015_.info("UUID of player {} is {}", ServerLoginPacketListenerImpl.this.f_10021_.getName(), ServerLoginPacketListenerImpl.this.f_10021_.getId());
@@ -55,7 +55,7 @@
} else {
ServerLoginPacketListenerImpl.this.m_10053_(Component.m_237115_("multiplayer.disconnect.unverified_username"));
ServerLoginPacketListenerImpl.f_10015_.error("Username '{}' tried to join with an invalid session", (Object)gameprofile.getName());
@@ -259,7 +_,7 @@
@@ -243,7 +_,7 @@
if (ServerLoginPacketListenerImpl.this.f_10018_.m_129792_()) {
ServerLoginPacketListenerImpl.f_10015_.warn("Authentication servers are down but will let them in anyway!");
ServerLoginPacketListenerImpl.this.f_10021_ = gameprofile;
@@ -64,7 +64,7 @@
} else {
ServerLoginPacketListenerImpl.this.m_10053_(Component.m_237115_("multiplayer.disconnect.authservers_down"));
ServerLoginPacketListenerImpl.f_10015_.error("Couldn't verify username because servers are unavailable");
@@ -279,6 +_,7 @@
@@ -263,6 +_,7 @@
}
public void m_7223_(ServerboundCustomQueryPacket p_10045_) {
@@ -0,0 +1,20 @@
--- a/net/minecraft/util/datafix/schemas/V2832.java
+++ b/net/minecraft/util/datafix/schemas/V2832.java
@@ -19,7 +_,7 @@
return DSL.fields("Level", DSL.optionalFields("Entities", DSL.list(References.f_16785_.in(p_185234_)), "TileEntities", DSL.list(DSL.or(References.f_16781_.in(p_185234_), DSL.remainder())), "TileTicks", DSL.list(DSL.fields("i", References.f_16787_.in(p_185234_))), "Sections", DSL.list(DSL.optionalFields("biomes", DSL.optionalFields("palette", DSL.list(References.f_16794_.in(p_185234_))), "block_states", DSL.optionalFields("palette", DSL.list(References.f_16783_.in(p_185234_))))), "Structures", DSL.optionalFields("Starts", DSL.compoundList(References.f_16790_.in(p_185234_)))));
});
p_185234_.registerType(false, References.f_16795_, () -> {
- return DSL.fields("dimensions", DSL.compoundList(DSL.constType(m_17310_()), DSL.fields("generator", DSL.taggedChoiceLazy("type", DSL.string(), ImmutableMap.of("minecraft:debug", DSL::remainder, "minecraft:flat", () -> {
+ return DSL.fields("dimensions", DSL.compoundList(DSL.constType(m_17310_()), DSL.fields("generator", DSL.or(DSL.taggedChoiceLazy("type", DSL.string(), ImmutableMap.of("minecraft:debug", DSL::remainder, "minecraft:flat", () -> {
return DSL.optionalFields("settings", DSL.optionalFields("biome", References.f_16794_.in(p_185234_), "layers", DSL.list(DSL.optionalFields("block", References.f_16787_.in(p_185234_)))));
}, "minecraft:noise", () -> {
return DSL.optionalFields("biome_source", DSL.taggedChoiceLazy("type", DSL.string(), ImmutableMap.of("minecraft:fixed", () -> {
@@ -29,7 +_,7 @@
}, "minecraft:checkerboard", () -> {
return DSL.fields("biomes", DSL.list(References.f_16794_.in(p_185234_)));
}, "minecraft:the_end", DSL::remainder)), "settings", DSL.or(DSL.constType(DSL.string()), DSL.optionalFields("default_block", References.f_16787_.in(p_185234_), "default_fluid", References.f_16787_.in(p_185234_))));
- })))));
+ })), DSL.remainder()))));
});
}
}
@@ -590,6 +590,15 @@
if (this.f_20935_.m_41781_()) {
this.m_21329_();
}
@@ -2989,7 +_,7 @@
public boolean m_21254_() {
if (this.m_6117_() && !this.f_20935_.m_41619_()) {
Item item = this.f_20935_.m_41720_();
- if (item.m_6164_(this.f_20935_) != UseAnim.BLOCK) {
+ if (item.m_6164_(this.f_20935_) != UseAnim.BLOCK && !this.f_20935_.canPerformAction(net.minecraftforge.common.ToolActions.SHIELD_BLOCK)) { // TODO 1.20 only use the tool action
return false;
} else {
return item.m_8105_(this.f_20935_) - this.f_20936_ >= 5;
@@ -3115,8 +_,8 @@
}
@@ -194,33 +194,14 @@
this.m_21008_(p_36159_, ItemStack.f_41583_);
}
@@ -1020,7 +_,7 @@
double d1 = p_36201_.f_82481_;
double d2 = 0.05D;
@@ -1014,6 +_,7 @@
return !this.f_36077_.f_35935_;
}
- while(d0 != 0.0D && this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(d0, (double)(-this.f_19793_), 0.0D))) {
+ while(d0 != 0.0D && this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(d0, (double)(-this.getStepHeight()), 0.0D))) {
if (d0 < 0.05D && d0 >= -0.05D) {
d0 = 0.0D;
} else if (d0 > 0.0D) {
@@ -1030,7 +_,7 @@
}
}
- while(d1 != 0.0D && this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(0.0D, (double)(-this.f_19793_), d1))) {
+ while(d1 != 0.0D && this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(0.0D, (double)(-this.getStepHeight()), d1))) {
if (d1 < 0.05D && d1 >= -0.05D) {
d1 = 0.0D;
} else if (d1 > 0.0D) {
@@ -1040,7 +_,7 @@
}
}
- while(d0 != 0.0D && d1 != 0.0D && this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(d0, (double)(-this.f_19793_), d1))) {
+ while(d0 != 0.0D && d1 != 0.0D && this.f_19853_.m_45756_(this, this.m_20191_().m_82386_(d0, (double)(-this.getStepHeight()), d1))) {
if (d0 < 0.05D && d0 >= -0.05D) {
d0 = 0.0D;
} else if (d0 > 0.0D) {
+ // Forge: Don't update this method to use IForgeEntity#getStepHeight() - https://github.com/MinecraftForge/MinecraftForge/issues/8922
protected Vec3 m_5763_(Vec3 p_36201_, MoverType p_36202_) {
if (!this.f_36077_.f_35935_ && p_36201_.f_82480_ <= 0.0D && (p_36202_ == MoverType.SELF || p_36202_ == MoverType.PLAYER) && this.m_36343_() && this.m_36386_()) {
double d0 = p_36201_.f_82479_;
@@ -1065,10 +_,11 @@
}
@@ -24,9 +24,9 @@
this.f_39000_ = 0;
+ boolean flag = false;
+
+ if (!net.minecraftforge.common.ForgeHooks.onAnvilChange(this, itemstack, itemstack2, f_39768_, f_39001_, j, this.f_39771_)) return;
if (!itemstack2.m_41619_()) {
- boolean flag = itemstack2.m_150930_(Items.f_42690_) && !EnchantedBookItem.m_41163_(itemstack2).isEmpty();
+ if (!net.minecraftforge.common.ForgeHooks.onAnvilChange(this, itemstack, itemstack2, f_39768_, f_39001_, j, this.f_39771_)) return;
+ flag = itemstack2.m_41720_() == Items.f_42690_ && !EnchantedBookItem.m_41163_(itemstack2).isEmpty();
if (itemstack1.m_41763_() && itemstack1.m_41720_().m_6832_(itemstack, itemstack2)) {
int l2 = Math.min(itemstack1.m_41773_(), itemstack1.m_41776_() / 4);
@@ -0,0 +1,14 @@
--- a/net/minecraft/world/item/UseAnim.java
+++ b/net/minecraft/world/item/UseAnim.java
@@ -9,5 +_,10 @@
SPEAR,
CROSSBOW,
SPYGLASS,
- TOOT_HORN;
+ TOOT_HORN,
+ /**
+ * Items with custom arm animation should return this in `Item#getUseAnimation`
+ * to prevent vanilla from also trying to animate same item
+ */
+ CUSTOM
}
@@ -38,6 +38,22 @@
}, p_44834_);
return mutablefloat.floatValue();
}
@@ -168,6 +_,7 @@
m_44853_(enchantmenthelper$enchantmentvisitor, p_44824_.m_20158_());
}
+ if(false) // Forge: Fix MC-248272
if (p_44825_ instanceof Player) {
m_44850_(enchantmenthelper$enchantmentvisitor, p_44824_.m_21205_());
}
@@ -182,6 +_,7 @@
m_44853_(enchantmenthelper$enchantmentvisitor, p_44897_.m_20158_());
}
+ if(false) // Forge: Fix MC-248272
if (p_44897_ instanceof Player) {
m_44850_(enchantmenthelper$enchantmentvisitor, p_44897_.m_21205_());
}
@@ -302,7 +_,7 @@
public static int m_220287_(RandomSource p_220288_, int p_220289_, int p_220290_, ItemStack p_220291_) {
@@ -4,7 +4,7 @@
import net.minecraft.world.phys.Vec3;
import org.slf4j.Logger;
+// TODO: ForgeEventFactory.getPotentialSpawns, ForgeHooks.canEntitySpawn
+// TODO: ForgeHooks.canEntitySpawn
public final class NaturalSpawner {
private static final Logger f_46977_ = LogUtils.getLogger();
private static final int f_151589_ = 24;
@@ -35,12 +35,13 @@
return;
}
@@ -266,7 +_,7 @@
@@ -266,7 +_,8 @@
}
private static WeightedRandomList<MobSpawnSettings.SpawnerData> m_220443_(ServerLevel p_220444_, StructureManager p_220445_, ChunkGenerator p_220446_, MobCategory p_220447_, BlockPos p_220448_, @Nullable Holder<Biome> p_220449_) {
- return m_220455_(p_220448_, p_220444_, p_220447_, p_220445_) ? NetherFortressStructure.f_228517_ : p_220446_.m_223133_(p_220449_ != null ? p_220449_ : p_220444_.m_204166_(p_220448_), p_220445_, p_220447_, p_220448_);
+ return m_220455_(p_220448_, p_220444_, p_220447_, p_220445_) ? p_220445_.m_220521_().m_175515_(Registry.f_235725_).m_123013_(BuiltinStructures.f_209859_).m_226612_().get(MobCategory.MONSTER).f_210044_() : p_220446_.m_223133_(p_220449_ != null ? p_220449_ : p_220444_.m_204166_(p_220448_), p_220445_, p_220447_, p_220448_);
+ // Forge: Add in potential spawns, and replace hardcoded nether fortress mob list
+ return net.minecraftforge.event.ForgeEventFactory.getPotentialSpawns(p_220444_, p_220447_, p_220448_, m_220455_(p_220448_, p_220444_, p_220447_, p_220445_) ? p_220445_.m_220521_().m_175515_(Registry.f_235725_).m_123013_(BuiltinStructures.f_209859_).m_226612_().get(MobCategory.MONSTER).f_210044_() : p_220446_.m_223133_(p_220449_ != null ? p_220449_ : p_220444_.m_204166_(p_220448_), p_220445_, p_220447_, p_220448_));
}
public static boolean m_220455_(BlockPos p_220456_, ServerLevel p_220457_, MobCategory p_220458_, StructureManager p_220459_) {
@@ -1,5 +1,19 @@
--- a/net/minecraft/world/level/storage/LevelStorageSource.java
+++ b/net/minecraft/world/level/storage/LevelStorageSource.java
@@ -96,6 +_,13 @@
}
Dynamic<T> dynamic1 = p_78206_.update(References.f_16795_, dynamic, p_78207_, SharedConstants.m_183709_().getWorldVersion());
+ // The above line is modified (via the patch in V2832), such that the data fixer upper will retain dimensions that don't exist in the schema, in the dynamic.
+ // When we parse the WorldGenSettings below, in vanilla, this uses the same call paths that can cause things to register (such as dimension types).
+ // However, since at this point all resource data will have been loaded, anything that *would* register now is going to error later, because it'll create a Holder<> reference, that is not bound to anything. This unbound reference will then throw an error when the registries are frozen.
+ // So, we freeze the registries before this call to parse(). This prevents them from leaking any new unbound holders into the registry.
+ // Attempting to register to a frozen registry throws an exception, which we resolve via a patch in RegistryLoader, causing it to return DataResult.error() instead, and prevent the faulty dimension from registering without aborting the parsing of the WorldGenSettings
+ // Finally, the resultOrPartial() promotes only the dimensions which successfully parsed, and the LenientUnboundedMapCodec which is patched into the WorldGenSettings codec ensures that *only* the invalid dimensions will fail to parse (see MC-197860), and not discard other dimensions as well.
+ if (p_78205_.getOps() instanceof net.minecraft.resources.RegistryOps<T> ops) ops.f_206806_.m_203610_().forEach(e -> e.f_206234_().m_203521_());
DataResult<WorldGenSettings> dataresult = WorldGenSettings.f_64600_.parse(dynamic1);
return Pair.of(dataresult.resultOrPartial(Util.m_137489_("WorldGenSettings: ", f_78191_::error)).orElseGet(() -> {
RegistryAccess registryaccess = RegistryAccess.m_206154_(dynamic1);
@@ -372,6 +_,19 @@
return LevelStorageSource.this.m_230817_(this.f_230867_, LevelStorageSource.m_211737_(p_211748_, p_211749_, p_211750_));
}
@@ -0,0 +1,8 @@
{
"values": [
"#forge:armors/helmets",
"#forge:armors/chestplates",
"#forge:armors/leggings",
"#forge:armors/boots"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:leather_boots",
"minecraft:chainmail_boots",
"minecraft:iron_boots",
"minecraft:golden_boots",
"minecraft:diamond_boots",
"minecraft:netherite_boots"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:leather_chestplate",
"minecraft:chainmail_chestplate",
"minecraft:iron_chestplate",
"minecraft:golden_chestplate",
"minecraft:diamond_chestplate",
"minecraft:netherite_chestplate"
]
}
@@ -0,0 +1,11 @@
{
"values": [
"minecraft:leather_helmet",
"minecraft:turtle_helmet",
"minecraft:chainmail_helmet",
"minecraft:iron_helmet",
"minecraft:golden_helmet",
"minecraft:diamond_helmet",
"minecraft:netherite_helmet"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:leather_leggings",
"minecraft:chainmail_leggings",
"minecraft:iron_leggings",
"minecraft:golden_leggings",
"minecraft:diamond_leggings",
"minecraft:netherite_leggings"
]
}
@@ -0,0 +1,14 @@
{
"values": [
"#forge:tools/swords",
"#forge:tools/axes",
"#forge:tools/pickaxes",
"#forge:tools/shovels",
"#forge:tools/hoes",
"#forge:tools/shields",
"#forge:tools/bows",
"#forge:tools/crossbows",
"#forge:tools/fishing_rods",
"#forge:tools/tridents"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:wooden_axe",
"minecraft:stone_axe",
"minecraft:iron_axe",
"minecraft:golden_axe",
"minecraft:diamond_axe",
"minecraft:netherite_axe"
]
}
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:bow"
]
}
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:crossbow"
]
}
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:fishing_rod"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:wooden_hoe",
"minecraft:stone_hoe",
"minecraft:iron_hoe",
"minecraft:golden_hoe",
"minecraft:diamond_hoe",
"minecraft:netherite_hoe"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:wooden_pickaxe",
"minecraft:stone_pickaxe",
"minecraft:iron_pickaxe",
"minecraft:golden_pickaxe",
"minecraft:diamond_pickaxe",
"minecraft:netherite_pickaxe"
]
}
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:shield"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:wooden_shovel",
"minecraft:stone_shovel",
"minecraft:iron_shovel",
"minecraft:golden_shovel",
"minecraft:diamond_shovel",
"minecraft:netherite_shovel"
]
}
@@ -0,0 +1,10 @@
{
"values": [
"minecraft:wooden_sword",
"minecraft:stone_sword",
"minecraft:iron_sword",
"minecraft:golden_sword",
"minecraft:diamond_sword",
"minecraft:netherite_sword"
]
}
@@ -0,0 +1,5 @@
{
"values": [
"minecraft:trident"
]
}
@@ -1,6 +1,7 @@
{
"values": [
"minecraft:desert",
"minecraft:beach",
"minecraft:badlands",
"minecraft:wooded_badlands"
]
@@ -3,6 +3,7 @@
"minecraft:swamp",
"minecraft:jungle",
"minecraft:sparse_jungle",
"minecraft:beach",
"minecraft:bamboo_jungle",
"minecraft:lush_caves",
"minecraft:mangrove_swamp"
@@ -0,0 +1,51 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.level.ColorResolver;
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
import net.minecraftforge.fml.ModLoader;
import org.jetbrains.annotations.ApiStatus;
import java.util.Map;
/**
* Manager for custom {@link ColorResolver} instances, collected via {@link RegisterColorHandlersEvent.ColorResolvers}.
*/
public final class ColorResolverManager
{
private static ImmutableList<ColorResolver> colorResolvers;
@ApiStatus.Internal
public static void init()
{
ImmutableList.Builder<ColorResolver> builder = ImmutableList.builder();
ModLoader.get().postEvent(new RegisterColorHandlersEvent.ColorResolvers(builder));
colorResolvers = builder.build();
}
/**
* Register a {@link BlockTintCache} for every registered {@link ColorResolver} into the given target map.
*
* @param level the level to use
* @param target the map to populate
*/
public static void registerBlockTintCaches(ClientLevel level, Map<ColorResolver, BlockTintCache> target)
{
for (var resolver : colorResolvers)
{
target.put(resolver, new BlockTintCache(pos -> level.calculateBlockTint(pos, resolver)));
}
}
private ColorResolverManager()
{
}
}
+11 -3
View File
@@ -27,6 +27,7 @@ import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.LerpingBossEvent;
import net.minecraft.client.gui.components.toasts.Toast;
import net.minecraft.client.gui.screens.ConfirmScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.TitleScreen;
@@ -128,6 +129,7 @@ import net.minecraftforge.client.event.RenderTooltipEvent;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.client.event.ScreenshotEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.event.ToastAddEvent;
import net.minecraftforge.client.event.ViewportEvent;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
@@ -1091,10 +1093,16 @@ public class ForgeHooksClient
};
}
public static int onScreenPotionSize(Screen screen, int availableSpace, boolean compact)
public static ScreenEvent.RenderInventoryMobEffects onScreenPotionSize(Screen screen, int availableSpace, boolean compact, int horizontalOffset)
{
final ScreenEvent.RenderInventoryMobEffects event = new ScreenEvent.RenderInventoryMobEffects(screen, availableSpace, compact);
return MinecraftForge.EVENT_BUS.post(event) ? 0 : (event.isCompact() ? 1 : 2);
final ScreenEvent.RenderInventoryMobEffects event = new ScreenEvent.RenderInventoryMobEffects(screen, availableSpace, compact, horizontalOffset);
MinecraftForge.EVENT_BUS.post(event);
return event;
}
public static boolean onToastAdd(Toast toast)
{
return MinecraftForge.EVENT_BUS.post(new ToastAddEvent(toast));
}
public static boolean isBlockInSolidLayer(BlockState state)
@@ -0,0 +1,34 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
/**
* An ArmPose that can be defined by the user.
* Register one by creating a custom {@link net.minecraft.client.model.HumanoidModel.ArmPose}
* and returning it in {@link IClientItemExtensions#getArmPose(LivingEntity, InteractionHand, ItemStack)}.
*/
@FunctionalInterface
public interface IArmPoseTransformer
{
/**
* This method should be used to apply all wanted transformations to the player when the ArmPose is active.
* You can use {@link LivingEntity#getTicksUsingItem()} and {@link LivingEntity#getUseItemRemainingTicks()} for moving animations.
*
* @param model The humanoid model
* @param entity The humanoid entity
* @param arm Arm to pose
*/
void applyTransform(HumanoidModel<?> model, LivingEntity entity, HumanoidArm arm);
}
@@ -0,0 +1,29 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client;
import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;
import net.minecraftforge.client.event.RegisterItemDecorationsEvent;
/**
* An ItemDecorator that is used to render something on specific items, when the DurabilityBar and StackCount is rendered.
* Add it to an item using {@linkplain RegisterItemDecorationsEvent#register(ItemLike, IItemDecorator)}.
*/
public interface IItemDecorator
{
/**
* Is called after {@linkplain ItemRenderer#renderGuiItemDecorations(Font, ItemStack, int, int, String)} is done rendering.
* The StackCount is rendered at blitOffset+200 so use the blitOffset with caution.
* <p>
* The RenderState during this call will be: enableTexture, enableDepthTest, enableBlend and defaultBlendFunc
* @return true if you have modified the RenderState and it has to be reset for other ItemDecorators
*/
boolean render(Font font, ItemStack stack, int xOffset, int yOffset, float blitOffset);
}
@@ -0,0 +1,73 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.blaze3d.systems.RenderSystem;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.client.gui.Font;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.event.RegisterItemDecorationsEvent;
import net.minecraftforge.fml.ModLoader;
import net.minecraftforge.fml.ModLoadingContext;
import org.jetbrains.annotations.ApiStatus;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ApiStatus.Internal
public final class ItemDecoratorHandler
{
private final List<IItemDecorator> itemDecorators;
private static Map<Item, ItemDecoratorHandler> DECORATOR_LOOKUP = ImmutableMap.of();
private static final ItemDecoratorHandler EMPTY = new ItemDecoratorHandler();
private ItemDecoratorHandler()
{
this.itemDecorators = ImmutableList.of();
}
private ItemDecoratorHandler(List<IItemDecorator> itemDecorators)
{
this.itemDecorators = ImmutableList.copyOf(itemDecorators);
}
public static void init()
{
var decorators = new HashMap<Item, List<IItemDecorator>>();
var event = new RegisterItemDecorationsEvent(decorators);
ModLoader.get().postEventWithWrapInModOrder(event, (mc, e) -> ModLoadingContext.get().setActiveContainer(mc), (mc, e) -> ModLoadingContext.get().setActiveContainer(null));
var builder = new ImmutableMap.Builder<Item, ItemDecoratorHandler>();
decorators.forEach((item, itemDecorators) -> builder.put(item, new ItemDecoratorHandler(itemDecorators)));
DECORATOR_LOOKUP = builder.build();
}
public static ItemDecoratorHandler of(ItemStack stack)
{
return DECORATOR_LOOKUP.getOrDefault(stack.getItem(), EMPTY);
}
public void render(Font font, ItemStack stack, int xOffset, int yOffset, float blitOffset)
{
resetRenderState();
for (IItemDecorator itemDecorator : itemDecorators)
{
if (itemDecorator.render(font, stack, xOffset, yOffset, blitOffset))
resetRenderState();
}
}
private void resetRenderState()
{
RenderSystem.enableTexture();
RenderSystem.enableDepthTest();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
}
}
@@ -5,10 +5,13 @@
package net.minecraftforge.client.event;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.block.BlockColors;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.level.ItemLike;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
@@ -127,4 +130,26 @@ public abstract class RegisterColorHandlersEvent extends Event implements IModBu
itemColors.register(itemColor, items);
}
}
/**
* Allows registration of custom {@link ColorResolver} implementations to be used with
* {@link net.minecraft.world.level.BlockAndTintGetter#getBlockTint(BlockPos, ColorResolver)}.
*/
public static class ColorResolvers extends RegisterColorHandlersEvent
{
private final ImmutableList.Builder<ColorResolver> builder;
@ApiStatus.Internal
public ColorResolvers(ImmutableList.Builder<ColorResolver> builder)
{
this.builder = builder;
}
public void register(ColorResolver resolver)
{
this.builder.add(resolver);
}
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client.event;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.ItemLike;
import net.minecraftforge.client.IItemDecorator;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.event.IModBusEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.jetbrains.annotations.ApiStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Allows users to register custom {@linkplain IItemDecorator IItemDecorator} to Items.
*
* <p>This event is not {@linkplain Cancelable cancelable}, and does not {@linkplain HasResult have a result}.
*
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
*/
public class RegisterItemDecorationsEvent extends Event implements IModBusEvent
{
private final Map<Item, List<IItemDecorator>> decorators;
@ApiStatus.Internal
public RegisterItemDecorationsEvent(Map<Item, List<IItemDecorator>> decorators)
{
this.decorators = decorators;
}
/**
* Register an ItemDecorator to an Item
*/
public void register(ItemLike itemLike, IItemDecorator decorator)
{
List<IItemDecorator> itemDecoratorList = decorators.computeIfAbsent(itemLike.asItem(), item -> new ArrayList<>());
itemDecoratorList.add(decorator);
}
}
@@ -275,6 +275,7 @@ public abstract class ScreenEvent extends Event
/**
* Fired ahead of rendering any active mob effects in the {@link EffectRenderingInventoryScreen inventory screen}.
* Can be used to select the size of the effects display (full or compact) or even hide or replace vanilla's rendering entirely.
* This event can also be used to modify the horizontal position of the stack of effects being rendered.
*
* <p>This event is {@linkplain Cancelable cancellable} and does not {@linkplain HasResult have a result}.
* Cancelling this event will prevent vanilla rendering.</p>
@@ -287,13 +288,15 @@ public abstract class ScreenEvent extends Event
{
private final int availableSpace;
private boolean compact;
private int horizontalOffset;
@ApiStatus.Internal
public RenderInventoryMobEffects(Screen screen, int availableSpace, boolean compact)
public RenderInventoryMobEffects(Screen screen, int availableSpace, boolean compact, int horizontalOffset)
{
super(screen);
this.availableSpace = availableSpace;
this.compact = compact;
this.horizontalOffset = horizontalOffset;
}
/**
@@ -312,6 +315,30 @@ public abstract class ScreenEvent extends Event
return compact;
}
/**
* The distance from the left side of the screen that the effect stack is rendered. Positive values shift this more to the right.
*/
public int getHorizontalOffset()
{
return horizontalOffset;
}
/**
* Replaces the horizontal offset of the effect stack
*/
public void setHorizontalOffset(int offset)
{
horizontalOffset = offset;
}
/**
* Adds to the horizontal offset of the effect stack. Negative values are acceptable.
*/
public void addHorizontalOffset(int offset)
{
horizontalOffset += offset;
}
/**
* Sets whether the effects should be rendered in compact mode (only icons, no text), or the default full size.
*/
@@ -0,0 +1,38 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.client.event;
import net.minecraft.client.gui.components.toasts.Toast;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.LogicalSide;
/**
* Fired when the client queues a {@link Toast} message to be shown onscreen.
* Toasts are small popups that appear on the top right of the screen, for certain actions such as unlocking Advancements and Recipes.
*
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
* Cancelling the event stops the toast from being queued, which means it never renders.</p>
*
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
*/
@Cancelable
public class ToastAddEvent extends Event
{
private final Toast toast;
public ToastAddEvent(Toast toast)
{
this.toast = toast;
}
public Toast getToast()
{
return toast;
}
}
@@ -5,19 +5,24 @@
package net.minecraftforge.client.extensions.common;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.Model;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.IArmPoseTransformer;
import net.minecraftforge.fml.LogicalSide;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -57,6 +62,37 @@ public interface IClientItemExtensions
return null;
}
/**
* This method returns an ArmPose that can be defined using the {@link net.minecraft.client.model.HumanoidModel.ArmPose#create(String, boolean, IArmPoseTransformer)} method.
* This allows for creating custom item use animations.
*
* @param entityLiving The entity holding the item
* @param hand The hand the ArmPose will be applied to
* @param itemStack The stack being held
* @return A custom ArmPose that can be used to define movement of the arm
*/
@Nullable
default HumanoidModel.ArmPose getArmPose(LivingEntity entityLiving, InteractionHand hand, ItemStack itemStack)
{
return null;
}
/**
* Called right before when client applies transformations to item in hand and render it.
*
* @param poseStack The pose stack
* @param player The player holding the item, it's always main client player
* @param arm The arm holding the item
* @param itemInHand The held item
* @param partialTick Partial tick time, useful for interpolation
* @param equipProcess Equip process time, Ranging from 0.0 to 1.0. 0.0 when it's done equipping
* @param swingProcess Swing process time, Ranging from 0.0 to 1.0. 0.0 when it's done swinging
* @return true if it should skip applying other transforms and go straight to rendering
*/
default boolean applyForgeHandTransform(PoseStack poseStack, LocalPlayer player, HumanoidArm arm, ItemStack itemInHand, float partialTick, float equipProcess, float swingProcess) {
return false;
}
/**
* Queries the humanoid armor model for this item when it's equipped.
*
@@ -516,7 +516,7 @@ public class ForgeGui extends Gui
RenderSystem.defaultBlendFunc();
int color = (animateOverlayMessageColor ? Mth.hsvToRgb(hue / 50.0F, 0.7F, 0.6F) & WHITE : WHITE);
drawBackdrop(pStack, font, -4, font.width(overlayMessageString), 16777215 | (opacity << 24));
font.draw(pStack, overlayMessageString.getVisualOrderText(), -font.width(overlayMessageString) / 2, -4, color | (opacity << 24));
font.drawShadow(pStack, overlayMessageString.getVisualOrderText(), -font.width(overlayMessageString) / 2, -4, color | (opacity << 24));
RenderSystem.disableBlend();
pStack.popPose();
}
@@ -25,12 +25,16 @@ import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.ResourceLocationException;
import net.minecraft.advancements.Advancement;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.core.*;
import net.minecraft.network.chat.*;
import net.minecraft.network.chat.contents.LiteralContents;
@@ -145,6 +149,8 @@ import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.RegistryManager;
import net.minecraftforge.registries.holdersets.ICustomHolderSet;
import net.minecraftforge.server.permission.PermissionAPI;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -152,6 +158,7 @@ import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import net.minecraft.ChatFormatting;
import net.minecraft.resources.HolderSetCodec;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.damagesource.DamageSource;
@@ -1488,4 +1495,13 @@ public class ForgeHooks
{
return registryKey.getNamespace().equals("minecraft") ? registryKey.getPath() : registryKey.getNamespace() + "/" + registryKey.getPath();
}
public static boolean canUseEntitySelectors(SharedSuggestionProvider provider)
{
if (provider instanceof CommandSourceStack source && source.getEntity() instanceof ServerPlayer player)
{
return PermissionAPI.getPermission(player, ForgeMod.USE_SELECTORS_PERMISSION);
}
return provider.hasPermission(Commands.LEVEL_GAMEMASTERS);
}
}
@@ -14,6 +14,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob;
import net.minecraft.commands.Commands;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.RangedAttribute;
import net.minecraft.world.entity.item.ItemEntity;
@@ -61,6 +62,11 @@ import net.minecraftforge.fml.*;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.*;
import net.minecraftforge.registries.*;
import net.minecraftforge.registries.holdersets.AndHolderSet;
import net.minecraftforge.registries.holdersets.AnyHolderSet;
import net.minecraftforge.registries.holdersets.HolderSetType;
import net.minecraftforge.registries.holdersets.NotHolderSet;
import net.minecraftforge.registries.holdersets.OrHolderSet;
import net.minecraftforge.network.NetworkConstants;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@@ -68,6 +74,9 @@ import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.network.filters.VanillaPacketSplitter;
import net.minecraftforge.server.command.EnumArgument;
import net.minecraftforge.server.command.ModIdArgument;
import net.minecraftforge.server.permission.events.PermissionGatherEvent;
import net.minecraftforge.server.permission.nodes.PermissionNode;
import net.minecraftforge.server.permission.nodes.PermissionTypes;
import net.minecraftforge.versions.forge.ForgeVersion;
import net.minecraftforge.versions.mcp.MCPVersion;
@@ -120,6 +129,7 @@ public class ForgeMod
private static final DeferredRegister<ArgumentTypeInfo<?, ?>> COMMAND_ARGUMENT_TYPES = DeferredRegister.create(Registry.COMMAND_ARGUMENT_TYPE_REGISTRY, "forge");
private static final DeferredRegister<Codec<? extends BiomeModifier>> BIOME_MODIFIER_SERIALIZERS = DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, "forge");
private static final DeferredRegister<Codec<? extends StructureModifier>> STRUCTURE_MODIFIER_SERIALIZERS = DeferredRegister.create(ForgeRegistries.Keys.STRUCTURE_MODIFIER_SERIALIZERS, "forge");
private static final DeferredRegister<HolderSetType> HOLDER_SET_TYPES = DeferredRegister.create(ForgeRegistries.Keys.HOLDER_SET_TYPES, "forge");
@SuppressWarnings({ "unchecked", "rawtypes" })
private static final RegistryObject<EnumArgument.Info> ENUM_COMMAND_ARGUMENT_TYPE = COMMAND_ARGUMENT_TYPES.register("enum", () ->
@@ -212,6 +222,27 @@ public class ForgeMod
*/
public static final RegistryObject<Codec<NoneStructureModifier>> NONE_STRUCTURE_MODIFIER_TYPE = STRUCTURE_MODIFIER_SERIALIZERS.register("none", () -> Codec.unit(NoneStructureModifier.INSTANCE));
/**
* Stock holder set type that represents any/all values in a registry. Can be used in a holderset object with {@code { "type": "forge:any" }}
*/
public static final RegistryObject<HolderSetType> ANY_HOLDER_SET = HOLDER_SET_TYPES.register("any", () -> AnyHolderSet::codec);
/**
* Stock holder set type that represents an intersection of other holdersets. Can be used in a holderset object with {@code { "type": "forge:and", "values": [list of holdersets] }}
*/
public static final RegistryObject<HolderSetType> AND_HOLDER_SET = HOLDER_SET_TYPES.register("and", () -> AndHolderSet::codec);
/**
* Stock holder set type that represents a union of other holdersets. Can be used in a holderset object with {@code { "type": "forge:or", "values": [list of holdersets] }}
*/
public static final RegistryObject<HolderSetType> OR_HOLDER_SET = HOLDER_SET_TYPES.register("or", () -> OrHolderSet::codec);
/**
* <p>Stock holder set type that represents all values in a registry except those in another given set.
* Can be used in a holderset object with {@code { "type": "forge:not", "value": holderset }}</p>
*/
public static final RegistryObject<HolderSetType> NOT_HOLDER_SET = HOLDER_SET_TYPES.register("not", () -> NotHolderSet::codec);
private static final DeferredRegister<FluidType> VANILLA_FLUID_TYPES = DeferredRegister.create(ForgeRegistries.Keys.FLUID_TYPES, "minecraft");
public static final RegistryObject<FluidType> EMPTY_TYPE = VANILLA_FLUID_TYPES.register("empty", () ->
@@ -418,6 +449,7 @@ public class ForgeMod
COMMAND_ARGUMENT_TYPES.register(modEventBus);
BIOME_MODIFIER_SERIALIZERS.register(modEventBus);
STRUCTURE_MODIFIER_SERIALIZERS.register(modEventBus);
HOLDER_SET_TYPES.register(modEventBus);
VANILLA_FLUID_TYPES.register(modEventBus);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
MinecraftForge.EVENT_BUS.addListener(this::missingSoundMapping);
@@ -433,6 +465,7 @@ public class ForgeMod
MinecraftForge.EVENT_BUS.addListener(VillagerTradingManager::loadTrades);
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
MinecraftForge.EVENT_BUS.addListener(this::mappingChanged);
MinecraftForge.EVENT_BUS.addListener(this::registerPermissionNodes);
ForgeRegistries.ITEMS.tags().addOptionalTagDefaults(Tags.Items.ENCHANTING_FUELS, Set.of(ForgeRegistries.ITEMS.getDelegateOrThrow(Items.LAPIS_LAZULI)));
}
@@ -574,4 +607,12 @@ public class ForgeMod
event.register(Registry.LOOT_ITEM_REGISTRY, new ResourceLocation("forge:loot_table_id"), () -> LootTableIdCondition.LOOT_TABLE_ID);
event.register(Registry.LOOT_ITEM_REGISTRY, new ResourceLocation("forge:can_tool_perform_action"), () -> CanToolPerformAction.LOOT_CONDITION_TYPE);
}
public static final PermissionNode<Boolean> USE_SELECTORS_PERMISSION = new PermissionNode<>("forge", "use_entity_selectors",
PermissionTypes.BOOLEAN, (player, uuid, contexts) -> player != null && player.hasPermissions(Commands.LEVEL_GAMEMASTERS));
public void registerPermissionNodes(PermissionGatherEvent.Nodes event)
{
event.addNodes(USE_SELECTORS_PERMISSION);
}
}
@@ -26,7 +26,7 @@ public class MinecraftForge
* ORE_GEN_BUS for ore gen events
* EVENT_BUS for everything else
*/
public static final IEventBus EVENT_BUS = BusBuilder.builder().startShutdown().build();
public static final IEventBus EVENT_BUS = BusBuilder.builder().startShutdown().useModLauncher().build();
static final ForgeInternalHandler INTERNAL_HANDLER = new ForgeInternalHandler();
private static final Logger LOGGER = LogManager.getLogger();
@@ -394,6 +394,125 @@ public class Tags
public static final TagKey<Item> STORAGE_BLOCKS_RAW_IRON = tag("storage_blocks/raw_iron");
public static final TagKey<Item> STORAGE_BLOCKS_REDSTONE = tag("storage_blocks/redstone");
public static final TagKey<Item> STRING = tag("string");
/**
* A tag containing all existing tools.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS = tag("tools");
/**
* A tag containing all existing swords.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_SWORDS = tag("tools/swords");
/**
* A tag containing all existing axes.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_AXES = tag("tools/axes");
/**
* A tag containing all existing pickaxes.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_PICKAXES = tag("tools/pickaxes");
/**
* A tag containing all existing shovels.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_SHOVELS = tag("tools/shovels");
/**
* A tag containing all existing hoes.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_HOES = tag("tools/hoes");
/**
* A tag containing all existing shields.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_SHIELDS = tag("tools/shields");
/**
* A tag containing all existing bows.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_BOWS = tag("tools/bows");
/**
* A tag containing all existing crossbows.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_CROSSBOWS = tag("tools/crossbows");
/**
* A tag containing all existing fishing rods.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_FISHING_RODS = tag("tools/fishing_rods");
/**
* A tag containing all existing tridents.
*
* Note: This tag is not an alternative or a substitute to {@link net.minecraftforge.common.ToolActions}.
*
* @see net.minecraftforge.common.ToolAction
* @see net.minecraftforge.common.ToolActions
*/
public static final TagKey<Item> TOOLS_TRIDENTS = tag("tools/tridents");
/**
* A tag containing all existing armors.
*/
public static final TagKey<Item> ARMORS = tag("armors");
/**
* A tag containing all existing helmets.
*/
public static final TagKey<Item> ARMORS_HELMETS = tag("armors/helmets");
/**
* A tag containing all chestplates.
*/
public static final TagKey<Item> ARMORS_CHESTPLATES = tag("armors/chestplates");
/**
* A tag containing all existing leggings.
*/
public static final TagKey<Item> ARMORS_LEGGINGS = tag("armors/leggings");
/**
* A tag containing all existing boots.
*/
public static final TagKey<Item> ARMORS_BOOTS = tag("armors/boots");
private static TagKey<Item> tag(String name)
{
@@ -37,6 +37,7 @@ public final class ForgeBiomeTagsProvider extends BiomeTagsProvider
tag(Biomes.MUSHROOM_FIELDS, Tags.Biomes.IS_MUSHROOM, Tags.Biomes.IS_RARE);
tag(Biomes.JUNGLE, Tags.Biomes.IS_HOT_OVERWORLD, Tags.Biomes.IS_WET_OVERWORLD, Tags.Biomes.IS_DENSE_OVERWORLD);
tag(Biomes.SPARSE_JUNGLE, Tags.Biomes.IS_HOT_OVERWORLD, Tags.Biomes.IS_WET_OVERWORLD, Tags.Biomes.IS_RARE);
tag(Biomes.BEACH, Tags.Biomes.IS_WET_OVERWORLD, Tags.Biomes.IS_SANDY);
tag(Biomes.SNOWY_BEACH, Tags.Biomes.IS_COLD_OVERWORLD, Tags.Biomes.IS_SNOWY);
tag(Biomes.DARK_FOREST, Tags.Biomes.IS_SPOOKY, Tags.Biomes.IS_DENSE_OVERWORLD);
tag(Biomes.SNOWY_TAIGA, Tags.Biomes.IS_COLD_OVERWORLD, Tags.Biomes.IS_CONIFEROUS, Tags.Biomes.IS_SNOWY);
@@ -153,6 +153,22 @@ public final class ForgeItemTagsProvider extends ItemTagsProvider
copy(Tags.Blocks.STORAGE_BLOCKS_RAW_IRON, Tags.Items.STORAGE_BLOCKS_RAW_IRON);
copy(Tags.Blocks.STORAGE_BLOCKS_NETHERITE, Tags.Items.STORAGE_BLOCKS_NETHERITE);
tag(Tags.Items.STRING).add(Items.STRING);
tag(Tags.Items.TOOLS_SWORDS).add(Items.WOODEN_SWORD, Items.STONE_SWORD, Items.IRON_SWORD, Items.GOLDEN_SWORD, Items.DIAMOND_SWORD, Items.NETHERITE_SWORD);
tag(Tags.Items.TOOLS_AXES).add(Items.WOODEN_AXE, Items.STONE_AXE, Items.IRON_AXE, Items.GOLDEN_AXE, Items.DIAMOND_AXE, Items.NETHERITE_AXE);
tag(Tags.Items.TOOLS_PICKAXES).add(Items.WOODEN_PICKAXE, Items.STONE_PICKAXE, Items.IRON_PICKAXE, Items.GOLDEN_PICKAXE, Items.DIAMOND_PICKAXE, Items.NETHERITE_PICKAXE);
tag(Tags.Items.TOOLS_SHOVELS).add(Items.WOODEN_SHOVEL, Items.STONE_SHOVEL, Items.IRON_SHOVEL, Items.GOLDEN_SHOVEL, Items.DIAMOND_SHOVEL, Items.NETHERITE_SHOVEL);
tag(Tags.Items.TOOLS_HOES).add(Items.WOODEN_HOE, Items.STONE_HOE, Items.IRON_HOE, Items.GOLDEN_HOE, Items.DIAMOND_HOE, Items.NETHERITE_HOE);
tag(Tags.Items.TOOLS_SHIELDS).add(Items.SHIELD);
tag(Tags.Items.TOOLS_BOWS).add(Items.BOW);
tag(Tags.Items.TOOLS_CROSSBOWS).add(Items.CROSSBOW);
tag(Tags.Items.TOOLS_FISHING_RODS).add(Items.FISHING_ROD);
tag(Tags.Items.TOOLS_TRIDENTS).add(Items.TRIDENT);
tag(Tags.Items.TOOLS).addTags(Tags.Items.TOOLS_SWORDS, Tags.Items.TOOLS_AXES, Tags.Items.TOOLS_PICKAXES, Tags.Items.TOOLS_SHOVELS, Tags.Items.TOOLS_HOES, Tags.Items.TOOLS_SHIELDS, Tags.Items.TOOLS_BOWS, Tags.Items.TOOLS_CROSSBOWS, Tags.Items.TOOLS_FISHING_RODS, Tags.Items.TOOLS_TRIDENTS);
tag(Tags.Items.ARMORS_HELMETS).add(Items.LEATHER_HELMET, Items.TURTLE_HELMET, Items.CHAINMAIL_HELMET, Items.IRON_HELMET, Items.GOLDEN_HELMET, Items.DIAMOND_HELMET, Items.NETHERITE_HELMET);
tag(Tags.Items.ARMORS_CHESTPLATES).add(Items.LEATHER_CHESTPLATE, Items.CHAINMAIL_CHESTPLATE, Items.IRON_CHESTPLATE, Items.GOLDEN_CHESTPLATE, Items.DIAMOND_CHESTPLATE, Items.NETHERITE_CHESTPLATE);
tag(Tags.Items.ARMORS_LEGGINGS).add(Items.LEATHER_LEGGINGS, Items.CHAINMAIL_LEGGINGS, Items.IRON_LEGGINGS, Items.GOLDEN_LEGGINGS, Items.DIAMOND_LEGGINGS, Items.NETHERITE_LEGGINGS);
tag(Tags.Items.ARMORS_BOOTS).add(Items.LEATHER_BOOTS, Items.CHAINMAIL_BOOTS, Items.IRON_BOOTS, Items.GOLDEN_BOOTS, Items.DIAMOND_BOOTS, Items.NETHERITE_BOOTS);
tag(Tags.Items.ARMORS).addTags(Tags.Items.ARMORS_HELMETS, Tags.Items.ARMORS_CHESTPLATES, Tags.Items.ARMORS_LEGGINGS, Tags.Items.ARMORS_BOOTS);
}
private void addColored(Consumer<TagKey<Item>> consumer, TagKey<Item> group, String pattern)
@@ -9,6 +9,7 @@ import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
@@ -174,4 +175,15 @@ public interface IForgeBlockEntity extends ICapabilitySerializable<CompoundTag>
{
return ModelData.EMPTY;
}
/**
* Returns whether this {@link BlockEntity} has custom outline rendering behavior.
*
* @param player the local player currently viewing this {@code BlockEntity}
* @return {@code true} to enable outline processing
*/
default boolean hasCustomOutlineRendering(Player player)
{
return false;
}
}
@@ -12,6 +12,7 @@ import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.Entity;
@@ -410,4 +411,17 @@ public interface IForgeEntity extends ICapabilitySerializable<CompoundTag>
{
return type.getSound(self(), action);
}
/**
* Returns whether this {@link Entity} has custom outline rendering behavior which does
* not use the existing automatic outline rendering based on {@link Entity#isCurrentlyGlowing()}
* and the entity's team color.
*
* @param player the local player currently viewing this {@code Entity}
* @return {@code true} to enable outline processing
*/
default boolean hasCustomOutlineRendering(Player player)
{
return false;
}
}
@@ -0,0 +1,26 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.common.extensions;
public interface IForgeHolderSet<T>
{
/**
* <p>Adds a callback to run when this holderset's contents invalidate (i.e. because tags were rebound).</p>
*
* <p>The intended usage and use case is with composite holdersets that need to cache sets/list based on other
* holdersets, which may be mutable (because they are tag-based or themselves composite holdersets).
* Composite holdersets should use this to add callbacks to each of their component holdersets when constructed.</p>
*
* @param runnable Runnable to invoke when this component holderset's contents are no longer valid.
* This runnable should only clear caches and allow them to be lazily reevaluated later,
* as not all tag holdersets may have been rebound when this is called.
* This runnable should also invalidate all of the caller's listeners.
*/
default public void addInvalidationListener(Runnable runnable)
{
// noop by default, mutable/composite holdersets must override
}
}
@@ -81,8 +81,6 @@ public class FakePlayer extends ServerPlayer
this.connection = new FakePlayerNetHandler(level.getServer(), this);
}
@Override public Vec3 position() { return new Vec3(0, 0, 0); }
@Override public BlockPos blockPosition() { return BlockPos.ZERO; }
@Override public void displayClientMessage(Component chatComponent, boolean actionBar) { }
@Override public void awardStat(Stat stat, int amount) { }
@Override public boolean isInvulnerableTo(DamageSource source) { return true; }
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.common.world;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
/**
*
* AnvilUpdateEvent is fired when the inputs (either input stack, or the name) to an anvil are changed. <br>
* AnvilUpdateEvent is fired whenever the input stacks (left or right) or the name in an anvil changed. <br>
* It is called from {@link AnvilMenu#createResult()}. <br>
* If the event is canceled, vanilla behavior will not run, and the output will be set to {@link ItemStack#EMPTY}. <br>
* If the event is not canceled, but the output is not empty, it will set the output and not run vanilla behavior. <br>
@@ -16,11 +16,15 @@ import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.ReloadableServerResources;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.players.PlayerList;
import net.minecraft.util.RandomSource;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.Container;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.portal.PortalShape;
import net.minecraft.world.level.block.state.BlockState;
@@ -115,6 +119,7 @@ import net.minecraftforge.event.level.BlockEvent.CreateFluidSourceEvent;
import net.minecraftforge.event.level.BlockEvent.EntityMultiPlaceEvent;
import net.minecraftforge.event.level.BlockEvent.EntityPlaceEvent;
import net.minecraftforge.event.level.BlockEvent.NeighborNotifyEvent;
import net.minecraftforge.event.level.ChunkTicketLevelUpdatedEvent;
import net.minecraftforge.event.level.ChunkWatchEvent;
import net.minecraftforge.event.level.ExplosionEvent;
import net.minecraftforge.event.level.PistonEvent;
@@ -607,6 +612,12 @@ public class ForgeEventFactory
return event.getResult() != Result.DENY;
}
public static void fireChunkTicketLevelUpdated(ServerLevel level, long chunkPos, int oldTicketLevel, int newTicketLevel, @Nullable ChunkHolder chunkHolder)
{
if (oldTicketLevel != newTicketLevel)
MinecraftForge.EVENT_BUS.post(new ChunkTicketLevelUpdatedEvent(level, chunkPos, oldTicketLevel, newTicketLevel, chunkHolder));
}
public static void fireChunkWatch(ServerPlayer entity, LevelChunk chunk, ServerLevel level)
{
MinecraftForge.EVENT_BUS.post(new ChunkWatchEvent.Watch(entity, chunk, level));
@@ -801,4 +812,12 @@ public class ForgeEventFactory
{
MinecraftForge.EVENT_BUS.post(new TickEvent.ServerTickEvent(TickEvent.Phase.END, haveTime, server));
}
public static WeightedRandomList<MobSpawnSettings.SpawnerData> getPotentialSpawns(LevelAccessor level, MobCategory category, BlockPos pos, WeightedRandomList<MobSpawnSettings.SpawnerData> oldList)
{
LevelEvent.PotentialSpawns event = new LevelEvent.PotentialSpawns(level, category, pos, oldList);
if (MinecraftForge.EVENT_BUS.post(event))
return WeightedRandomList.create();
return WeightedRandomList.create(event.getSpawnerDataList());
}
}
@@ -0,0 +1,90 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.event.level;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ServerLevel;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.LogicalSide;
import org.jetbrains.annotations.Nullable;
/**
* This event is fired whenever a chunk has its ticket level changed via the server's ChunkMap.
* <p>
* This event does not fire if the new ticket level is the same as the old level, or if both the
* new <strong>AND</strong> old ticket levels represent values past the max chunk distance.
* <p>
* Due to how vanilla processes ticket level changes this event may be fired "twice" in one tick for the same chunk.
* The scenario where this happens is when increasing the level from say 31 (ticking) to 32, the way vanilla does it
* is by first changing it from 31 to 46, and then queuing the update from 46 to 32. However, when going from 32 to 31,
* vanilla is able to go directly.
* <p>
* This event is not {@linkplain Cancelable cancellable} and does not {@linkplain HasResult have a result}.
* <p>
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus}
* only on the {@linkplain LogicalSide#SERVER logical server}.
**/
public class ChunkTicketLevelUpdatedEvent extends Event
{
private final ServerLevel level;
private final long chunkPos;
private final int oldTicketLevel;
private final int newTicketLevel;
@Nullable
private final ChunkHolder chunkHolder;
public ChunkTicketLevelUpdatedEvent(ServerLevel level, long chunkPos, int oldTicketLevel, int newTicketLevel, @Nullable ChunkHolder chunkHolder)
{
this.level = level;
this.chunkPos = chunkPos;
this.oldTicketLevel = oldTicketLevel;
this.newTicketLevel = newTicketLevel;
this.chunkHolder = chunkHolder;
}
/**
* {@return the server level containing the chunk}
*/
public ServerLevel getLevel()
{
return this.level;
}
/**
* {@return the long representation of the chunk position the ticket level changed for}
*/
public long getChunkPos()
{
return this.chunkPos;
}
/**
* {@return the previous ticket level the chunk had}
*/
public int getOldTicketLevel()
{
return this.oldTicketLevel;
}
/**
* {@return the new ticket level for the chunk}
*/
public int getNewTicketLevel()
{
return this.newTicketLevel;
}
/**
* {@return chunk that had its ticket level updated}
*/
@Nullable
public ChunkHolder getChunkHolder()
{
return this.chunkHolder;
}
}
@@ -5,13 +5,21 @@
package net.minecraftforge.event.level;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.ProgressListener;
import net.minecraft.util.random.WeightedRandomList;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.biome.MobSpawnSettings;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraftforge.common.ForgeInternalHandler;
import net.minecraftforge.common.MinecraftForge;
@@ -117,4 +125,83 @@ public class LevelEvent extends Event
return settings;
}
}
/**
* Fired when building a list of all possible entities that can spawn at the specified location.
*
* <p>If an entry is added to the list, it needs to be a globally unique instance.</p>
*
* The event is called in {@link net.minecraft.world.level.NaturalSpawner#mobsAt(ServerLevel,
* StructureManager, ChunkGenerator, MobCategory, RandomSource, BlockPos)}.</p>
*
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
* Canceling the event will result in an empty list, meaning no entity will be spawned.</p>
*/
@Cancelable
public static class PotentialSpawns extends LevelEvent
{
private final MobCategory mobcategory;
private final BlockPos pos;
private final List<MobSpawnSettings.SpawnerData> list;
private final List<MobSpawnSettings.SpawnerData> view;
public PotentialSpawns(LevelAccessor level, MobCategory category, BlockPos pos, WeightedRandomList<MobSpawnSettings.SpawnerData> oldList)
{
super(level);
this.pos = pos;
this.mobcategory = category;
if (!oldList.isEmpty())
this.list = new ArrayList<>(oldList.unwrap());
else
this.list = new ArrayList<>();
this.view = Collections.unmodifiableList(list);
}
/**
* {@return the category of the mobs in the spawn list.}
*/
public MobCategory getMobCategory()
{
return mobcategory;
}
/**
* {@return the block position where the chosen mob will be spawned.}
*/
public BlockPos getPos()
{
return pos;
}
/**
* {@return the list of mobs that can potentially be spawned.}
*/
public List<MobSpawnSettings.SpawnerData> getSpawnerDataList()
{
return view;
}
/**
* Appends a SpawnerData entry to the spawn list.
*
* @param data SpawnerData entry to be appended to the spawn list.
*/
public void addSpawnerData(MobSpawnSettings.SpawnerData data)
{
list.add(data);
}
/**
* Removes a SpawnerData entry from the spawn list.
*
* @param data SpawnerData entry to be removed from the spawn list.
*
* {@return {@code true} if the spawn list contained the specified element.}
*/
public boolean removeSpawnerData(MobSpawnSettings.SpawnerData data)
{
return list.remove(data);
}
}
}
@@ -5,83 +5,24 @@
package net.minecraftforge.network;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceArrayMap;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.login.ServerboundCustomQueryPacket;
import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket;
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.unsafe.UnsafeHacks;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
public interface ICustomPacket<T extends Packet<?>> {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
enum Fields {
CPACKETCUSTOMPAYLOAD(ServerboundCustomPayloadPacket.class),
SPACKETCUSTOMPAYLOAD(ClientboundCustomPayloadPacket.class),
CPACKETCUSTOMLOGIN(ServerboundCustomQueryPacket.class),
SPACKETCUSTOMLOGIN(ClientboundCustomQueryPacket.class),
;
/**
* Returns a unsafe reference to this packet's internal data.
* Any modifications to this buffer will be reflected in the main buffer.
*/
@Nullable
FriendlyByteBuf getInternalData();
static final Reference2ReferenceArrayMap<Class<?>, Fields> lookup;
static {
lookup = Stream.of(values()).
collect(Collectors.toMap(Fields::getClazz, Function.identity(), (m1, m2)->m1, Reference2ReferenceArrayMap::new));
}
ResourceLocation getName();
private final Class<?> clazz;
final Optional<Field> data;
final Optional<Field> channel;
final Optional<Field> index;
Fields(Class<?> customPacketClass)
{
this.clazz = customPacketClass;
Field[] fields = customPacketClass.getDeclaredFields();
data = Arrays.stream(fields).filter(f-> !Modifier.isStatic(f.getModifiers()) && f.getType() == FriendlyByteBuf.class).findFirst();
channel = Arrays.stream(fields).filter(f->!Modifier.isStatic(f.getModifiers()) && f.getType() == ResourceLocation.class).findFirst();
index = Arrays.stream(fields).filter(f->!Modifier.isStatic(f.getModifiers()) && f.getType() == int.class).findFirst();
}
private Class<?> getClazz()
{
return clazz;
}
}
default FriendlyByteBuf getInternalData() {
return Fields.lookup.get(this.getClass()).data.map(f->UnsafeHacks.<FriendlyByteBuf>getField(f, this)).orElse(null);
}
default ResourceLocation getName() {
return Fields.lookup.get(this.getClass()).channel.map(f->UnsafeHacks.<ResourceLocation>getField(f, this)).orElse(LoginWrapper.WRAPPER);
}
default int getIndex() {
return Fields.lookup.get(this.getClass()).index.map(f->UnsafeHacks.getIntField(f, this)).orElse(Integer.MIN_VALUE);
}
default void setData(FriendlyByteBuf buffer) {
Fields.lookup.get(this.getClass()).data.ifPresent(f->UnsafeHacks.setField(f, this, buffer));
}
default void setName(ResourceLocation channelName) {
Fields.lookup.get(this.getClass()).channel.ifPresent(f->UnsafeHacks.setField(f, this, channelName));
}
default void setIndex(int index) {
Fields.lookup.get(this.getClass()).index.ifPresent(f->UnsafeHacks.setIntField(f, this, index));
}
int getIndex();
default NetworkDirection getDirection() {
return NetworkDirection.directionFor(this.getClass());
@@ -13,6 +13,7 @@ import net.minecraftforge.network.event.EventNetworkChannel;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.ApiStatus;
/**
* Wrapper for custom login packets. Transforms unnamed login channel messages into channels dispatched the same
@@ -21,7 +22,8 @@ import org.apache.logging.log4j.Logger;
public class LoginWrapper
{
private static final Logger LOGGER = LogManager.getLogger();
static final ResourceLocation WRAPPER = new ResourceLocation("fml:loginwrapper");
@ApiStatus.Internal
public static final ResourceLocation WRAPPER = new ResourceLocation("fml:loginwrapper");
private EventNetworkChannel wrapperChannel;
LoginWrapper() {
@@ -32,12 +32,14 @@ public class MCRegisterPacketHandler
public static class ChannelList {
private Set<ResourceLocation> locations = new HashSet<>();
private Set<ResourceLocation> remoteLocations = Set.of();
public void updateFrom(final Supplier<NetworkEvent.Context> source, FriendlyByteBuf buffer, final NetworkEvent.RegistrationChangeType changeType) {
byte[] data = new byte[Math.max(buffer.readableBytes(), 0)];
buffer.readBytes(data);
Set<ResourceLocation> oldLocations = this.locations;
this.locations = bytesToResLocation(data);
this.remoteLocations = Set.copyOf(this.locations);
// ensure all locations receive updates, old and new.
oldLocations.addAll(this.locations);
oldLocations.stream()
@@ -76,6 +78,14 @@ public class MCRegisterPacketHandler
}
return rl;
}
/**
* {@return the unmodifiable set of channel locations sent by the remote side}
* This is useful for interacting with other modloaders via the network to inspect registered network channel IDs.
*/
public Set<ResourceLocation> getRemoteLocations() {
return this.remoteLocations;
}
}
public void addChannels(Set<ResourceLocation> locations, Connection manager) {
@@ -14,7 +14,6 @@ import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.unsafe.UnsafeHacks;
import org.apache.commons.lang3.tuple.Pair;
import java.util.function.BiFunction;
@@ -25,15 +24,16 @@ import java.util.stream.Stream;
public enum NetworkDirection
{
PLAY_TO_SERVER(NetworkEvent.ClientCustomPayloadEvent::new, LogicalSide.CLIENT, ServerboundCustomPayloadPacket.class, 1),
PLAY_TO_CLIENT(NetworkEvent.ServerCustomPayloadEvent::new, LogicalSide.SERVER, ClientboundCustomPayloadPacket.class, 0),
LOGIN_TO_SERVER(NetworkEvent.ClientCustomPayloadLoginEvent::new, LogicalSide.CLIENT, ServerboundCustomQueryPacket.class, 3),
LOGIN_TO_CLIENT(NetworkEvent.ServerCustomPayloadLoginEvent::new, LogicalSide.SERVER, ClientboundCustomQueryPacket.class, 2);
PLAY_TO_SERVER(NetworkEvent.ClientCustomPayloadEvent::new, LogicalSide.CLIENT, ServerboundCustomPayloadPacket.class, 1, (d, i, n) -> new ServerboundCustomPayloadPacket(n, d)),
PLAY_TO_CLIENT(NetworkEvent.ServerCustomPayloadEvent::new, LogicalSide.SERVER, ClientboundCustomPayloadPacket.class, 0, (d, i, n) -> new ClientboundCustomPayloadPacket(n, d)),
LOGIN_TO_SERVER(NetworkEvent.ClientCustomPayloadLoginEvent::new, LogicalSide.CLIENT, ServerboundCustomQueryPacket.class, 3, (d, i, n) -> new ServerboundCustomQueryPacket(i, d)),
LOGIN_TO_CLIENT(NetworkEvent.ServerCustomPayloadLoginEvent::new, LogicalSide.SERVER, ClientboundCustomQueryPacket.class, 2, (d, i, n) -> new ClientboundCustomQueryPacket(i, n, d));
private final BiFunction<ICustomPacket<?>, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier;
private final LogicalSide logicalSide;
private final Class<? extends Packet> packetClass;
private final int otherWay;
private final Factory factory;
private static final Reference2ReferenceArrayMap<Class<? extends Packet>, NetworkDirection> packetLookup;
@@ -42,12 +42,13 @@ public enum NetworkDirection
collect(Collectors.toMap(NetworkDirection::getPacketClass, Function.identity(), (m1,m2)->m1, Reference2ReferenceArrayMap::new));
}
NetworkDirection(BiFunction<ICustomPacket<?>, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier, LogicalSide logicalSide, Class<? extends Packet> clazz, int i)
private NetworkDirection(BiFunction<ICustomPacket<?>, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier, LogicalSide logicalSide, Class<? extends Packet> clazz, int i, Factory factory)
{
this.eventSupplier = eventSupplier;
this.logicalSide = logicalSide;
this.packetClass = clazz;
this.otherWay = i;
this.factory = factory;
}
private Class<? extends Packet> getPacketClass() {
@@ -75,10 +76,10 @@ public enum NetworkDirection
@SuppressWarnings("unchecked")
public <T extends Packet<?>> ICustomPacket<T> buildPacket(Pair<FriendlyByteBuf,Integer> packetData, ResourceLocation channelName)
{
ICustomPacket<T> packet = (ICustomPacket<T>)UnsafeHacks.newInstance(getPacketClass());
packet.setName(channelName);
packet.setData(packetData.getLeft());
packet.setIndex(packetData.getRight());
return packet;
return this.factory.create(packetData.getLeft(), packetData.getRight(), channelName);
}
private interface Factory<T extends Packet<?>> {
ICustomPacket<T> create(FriendlyByteBuf data, Integer index, ResourceLocation channelName);
}
}
@@ -231,4 +231,10 @@ public class NetworkHooks
{
return mgr.channel().attr(NetworkConstants.FML_MOD_MISMATCH_DATA).get();
}
@Nullable
public static MCRegisterPacketHandler.ChannelList getChannelList(Connection mgr)
{
return mgr.channel().attr(NetworkConstants.FML_MC_REGISTRY).get();
}
}
@@ -36,7 +36,7 @@ public class NetworkInstance
this.networkProtocolVersion = networkProtocolVersion.get();
this.clientAcceptedVersions = clientAcceptedVersions;
this.serverAcceptedVersions = serverAcceptedVersions;
this.networkEventBus = BusBuilder.builder().setExceptionHandler(this::handleError).build();
this.networkEventBus = BusBuilder.builder().setExceptionHandler(this::handleError).useModLauncher().build();
}
private void handleError(IEventBus iEventBus, Event event, IEventListener[] iEventListeners, int i, Throwable throwable)
@@ -95,6 +95,9 @@ public class NetworkInstance
public boolean isRemotePresent(Connection manager) {
ConnectionData connectionData = NetworkHooks.getConnectionData(manager);
return connectionData != null && connectionData.getChannels().containsKey(channelName);
MCRegisterPacketHandler.ChannelList channelList = NetworkHooks.getChannelList(manager);
return (connectionData != null && connectionData.getChannels().containsKey(channelName))
// if it's not in the fml connection data, let's check if it's sent by another modloader.
|| (channelList != null && channelList.getRemoteLocations().contains(channelName));
}
}
@@ -135,7 +135,7 @@ public class IndexedMessageCodec
}
void consume(FriendlyByteBuf payload, int payloadIndex, Supplier<NetworkEvent.Context> context) {
if (payload == null) {
if (payload == null || !payload.isReadable()) {
LOGGER.error(SIMPLENET, "Received empty payload on channel {}", Optional.ofNullable(networkInstance).map(NetworkInstance::getChannelName).map(Objects::toString).orElse("MISSING CHANNEL"));
if (!HandshakeHandler.packetNeedsResponse(context.get().getNetworkManager(), payloadIndex))
{
@@ -26,6 +26,7 @@ public class ForgeDeferredRegistriesSetup
ForgeRegistries.DEFERRED_BIOME_MODIFIERS.register(modEventBus);
ForgeRegistries.DEFERRED_STRUCTURE_MODIFIER_SERIALIZERS.register(modEventBus);
ForgeRegistries.DEFERRED_STRUCTURE_MODIFIERS.register(modEventBus);
ForgeRegistries.DEFERRED_HOLDER_SET_TYPES.register(modEventBus);
setup = true;
}
@@ -45,6 +45,7 @@ import net.minecraftforge.common.Tags;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.world.BiomeModifier;
import net.minecraftforge.fluids.FluidType;
import net.minecraftforge.registries.holdersets.HolderSetType;
import java.util.function.Supplier;
import net.minecraftforge.common.world.StructureModifier;
@@ -127,6 +128,12 @@ public class ForgeRegistries
* Use {@link Keys#FLUID_TYPES} to create a {@link DeferredRegister}.
*/
public static final Supplier<IForgeRegistry<FluidType>> FLUID_TYPES = DEFERRED_FLUID_TYPES.makeRegistry(GameData::getFluidTypeRegistryBuilder);
static final DeferredRegister<HolderSetType> DEFERRED_HOLDER_SET_TYPES = DeferredRegister.create(Keys.HOLDER_SET_TYPES, "forge");
/**
* Calling {@link Supplier#get()} before {@link NewRegistryEvent} is fired will result in a null registry returned.
* Use {@link Keys#HOLDER_SET_TYPES} to create a {@link DeferredRegister}.
*/
public static final Supplier<IForgeRegistry<HolderSetType>> HOLDER_SET_TYPES = DEFERRED_HOLDER_SET_TYPES.makeRegistry(GameData::getHolderSetTypeRegistryBuilder);
// Custom forge datapack registries
static final DeferredRegister<BiomeModifier> DEFERRED_BIOME_MODIFIERS = DeferredRegister.create(Keys.BIOME_MODIFIERS, "forge");
@@ -175,6 +182,7 @@ public class ForgeRegistries
public static final ResourceKey<Registry<Codec<? extends BiomeModifier>>> BIOME_MODIFIER_SERIALIZERS = key("forge:biome_modifier_serializers");
public static final ResourceKey<Registry<Codec<? extends StructureModifier>>> STRUCTURE_MODIFIER_SERIALIZERS = key("forge:structure_modifier_serializers");
public static final ResourceKey<Registry<FluidType>> FLUID_TYPES = key("forge:fluid_type");
public static final ResourceKey<Registry<HolderSetType>> HOLDER_SET_TYPES = key("forge:holder_set_type");
// Forge Dynamic
public static final ResourceKey<Registry<BiomeModifier>> BIOME_MODIFIERS = key("forge:biome_modifier");
@@ -48,6 +48,8 @@ import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.StartupMessageManager;
import net.minecraftforge.fml.util.EnhancedRuntimeException;
import net.minecraftforge.fml.util.thread.EffectiveSide;
import net.minecraftforge.registries.holdersets.HolderSetType;
import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -164,6 +166,11 @@ public class GameData
{
return makeRegistry(FLUID_TYPES).disableSaving();
}
static RegistryBuilder<HolderSetType> getHolderSetTypeRegistryBuilder()
{
return new RegistryBuilder<HolderSetType>().disableSaving().disableSync();
}
private static <T> RegistryBuilder<T> makeRegistry(ResourceKey<? extends Registry<T>> key)
{
@@ -0,0 +1,80 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.registries.holdersets;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.core.Registry;
import net.minecraft.resources.HolderSetCodec;
import net.minecraft.resources.ResourceKey;
import net.minecraftforge.common.ForgeMod;
/**
* <p>Holderset that represents an intersection of other holdersets. Json format:</p>
* <pre>
* {
* "type": "forge:and",
* "values":
* [
* // list of sub-holdersets (strings, lists, or objects)
* ]
* }
* </pre>
*/
public class AndHolderSet<T> extends CompositeHolderSet<T>
{
public static <T> Codec<? extends ICustomHolderSet<T>> codec(ResourceKey<? extends Registry<T>> registryKey, Codec<Holder<T>> holderCodec, boolean forceList)
{
return HolderSetCodec.create(registryKey, holderCodec, forceList)
.listOf()
.xmap(AndHolderSet::new, AndHolderSet::getComponents)
.fieldOf("values")
.codec();
}
public AndHolderSet(List<HolderSet<T>> values)
{
super(values);
}
@Override
public HolderSetType type()
{
return ForgeMod.AND_HOLDER_SET.get();
}
@Override
protected Set<Holder<T>> createSet()
{
List<HolderSet<T>> components = this.getComponents();
if (components.size() < 1)
{
return Set.of();
}
if (components.size() == 1)
{
return components.get(0).stream().collect(Collectors.toSet());
}
List<HolderSet<T>> remainingComponents = components.subList(1, components.size());
return components.get(0)
.stream()
.filter(holder -> remainingComponents.stream().allMatch(holderset -> holderset.contains(holder)))
.collect(Collectors.toSet());
}
@Override
public String toString()
{
return "AndSet[" + this.getComponents() + "]";
}
}
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff. Show more