mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f2f5c02a0 | ||
|
|
7a6843fa4a | ||
|
|
f0ecf16c6b | ||
|
|
8998fa71b2 | ||
|
|
4e677a7558 | ||
|
|
07254b36d7 | ||
|
|
a51b8d256d | ||
|
|
75fcd9448e | ||
|
|
6b45999702 | ||
|
|
a4f52f4057 | ||
|
|
b8b3201372 | ||
|
|
41deadc1e2 | ||
|
|
82e8d06e54 | ||
|
|
51db5f2ff7 | ||
|
|
2ec9e515ff | ||
|
|
0579572148 | ||
|
|
83f4e6353c | ||
|
|
130953e519 | ||
|
|
7981093591 | ||
|
|
79112d6208 | ||
|
|
a3eb6263f4 | ||
|
|
d91bc9c73d | ||
|
|
c807665ab9 |
No files matched your search
+1
-1
@@ -43,7 +43,7 @@ ext {
|
||||
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'
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
MinecraftForge
|
||||
=============
|
||||
[](https://files.minecraftforge.net)
|
||||
[](https://files.minecraftforge.net)
|
||||
[](https://files.minecraftforge.net) [](https://discord.gg/UvedJ9m) [](https://www.patreon.com/LexManos)
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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_);
|
||||
@@ -541,6 +_,19 @@
|
||||
@@ -541,6 +_,21 @@
|
||||
TinyFileDialogs.tinyfd_messageBox("Minecraft", stringbuilder.toString(), "ok", "error", false);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@
|
||||
+ 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_());
|
||||
|
||||
+10
@@ -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_);
|
||||
}
|
||||
|
||||
+5
-4
@@ -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);
|
||||
|
||||
+14
@@ -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_);
|
||||
|
||||
@@ -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_();
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
+7
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -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_; }
|
||||
}
|
||||
+10
-1
@@ -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_(); }
|
||||
}
|
||||
+18
@@ -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_(); }
|
||||
}
|
||||
+9
@@ -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()) {
|
||||
@@ -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 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
@@ -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,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()
|
||||
{
|
||||
}
|
||||
}
|
||||
Executable → Regular
+11
-3
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -131,7 +131,7 @@ public class LevelEvent extends Event
|
||||
*
|
||||
* <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#getRandomSpawnMobAt(ServerLevel,
|
||||
* 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}.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.registries.holdersets;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
|
||||
/**
|
||||
* <p>Holderset that represents all elements of a registry. Json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:any"
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public record AnyHolderSet<T>(Registry<T> registry) implements ICustomHolderSet<T>
|
||||
{
|
||||
public static <T> Codec<? extends ICustomHolderSet<T>> codec(ResourceKey<? extends Registry<T>> registryKey, Codec<Holder<T>> holderCodec, boolean forceList)
|
||||
{
|
||||
return RegistryOps.retrieveRegistry(registryKey)
|
||||
.xmap(AnyHolderSet::new, AnyHolderSet::registry)
|
||||
.codec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderSetType type()
|
||||
{
|
||||
return ForgeMod.ANY_HOLDER_SET.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Holder<T>> iterator()
|
||||
{
|
||||
return this.stream().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Holder<T>> stream()
|
||||
{
|
||||
return registry.holders().map(Function.identity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return this.registry.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Either<TagKey<T>, List<Holder<T>>> unwrap()
|
||||
{
|
||||
return Either.right(this.stream().toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Holder<T>> getRandomElement(RandomSource random)
|
||||
{
|
||||
return this.registry.getRandom(random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Holder<T> get(int i)
|
||||
{
|
||||
return this.registry.getHolder(i).orElseThrow(() -> new NoSuchElementException("No element " + i + " in registry " + this.registry.key()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Holder<T> holder)
|
||||
{
|
||||
return holder.unwrapKey().map(this.registry::containsKey).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInRegistry(Registry<T> registry)
|
||||
{
|
||||
return this.registry == registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "AnySet(" + this.registry.key() + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.registries.holdersets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
||||
/**
|
||||
* Composite holdersets have component holdersets and possibly owner holdersets
|
||||
* (which have this holderset as a component).
|
||||
* When their component holderset(s) invalidate, they clear any cached data and then
|
||||
* invalidate their owner holdersets.
|
||||
*/
|
||||
public abstract class CompositeHolderSet<T> implements ICustomHolderSet<T>
|
||||
{
|
||||
private final List<Runnable> owners = new ArrayList<>();
|
||||
private final List<HolderSet<T>> components;
|
||||
|
||||
@Nullable
|
||||
private Set<Holder<T>> set = null;
|
||||
@Nullable
|
||||
private List<Holder<T>> list = null;
|
||||
|
||||
public CompositeHolderSet(List<HolderSet<T>> components)
|
||||
{
|
||||
this.components = components;
|
||||
for (HolderSet<T> holderset : components)
|
||||
{
|
||||
holderset.addInvalidationListener(this::invalidate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return immutable Set of Holders given this composite holderset's component holdersets}
|
||||
*/
|
||||
protected abstract Set<Holder<T>> createSet();
|
||||
|
||||
public List<HolderSet<T>> getComponents()
|
||||
{
|
||||
return this.components;
|
||||
}
|
||||
|
||||
public Set<Holder<T>> getSet()
|
||||
{
|
||||
Set<Holder<T>> thisSet = this.set;
|
||||
if (thisSet == null)
|
||||
{
|
||||
Set<Holder<T>> set = this.createSet();
|
||||
this.set = set;
|
||||
return set;
|
||||
}
|
||||
else
|
||||
{
|
||||
return thisSet;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Holder<T>> getList()
|
||||
{
|
||||
List<Holder<T>> thisList = this.list;
|
||||
if (thisList == null)
|
||||
{
|
||||
List<Holder<T>> list = List.copyOf(this.getSet());
|
||||
this.list = list;
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
return thisList;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInvalidationListener(Runnable runnable)
|
||||
{
|
||||
this.owners.add(runnable);
|
||||
}
|
||||
|
||||
private void invalidate()
|
||||
{
|
||||
this.set = null;
|
||||
this.list = null;
|
||||
for (Runnable runnable : this.owners)
|
||||
{
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Holder<T>> stream()
|
||||
{
|
||||
return this.getList().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return this.getList().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Either<TagKey<T>, List<Holder<T>>> unwrap()
|
||||
{
|
||||
return Either.right(this.getList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Holder<T>> getRandomElement(RandomSource rand)
|
||||
{
|
||||
List<Holder<T>> list = this.getList();
|
||||
int size = list.size();
|
||||
return size > 0
|
||||
? Optional.of(list.get(rand.nextInt(size)))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Holder<T> get(int i)
|
||||
{
|
||||
return this.getList().get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Holder<T> holder)
|
||||
{
|
||||
return this.getSet().contains(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInRegistry(Registry<T> registry)
|
||||
{
|
||||
for (HolderSet<T> component : this.components)
|
||||
{
|
||||
if (!component.isValidInRegistry(registry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Holder<T>> iterator()
|
||||
{
|
||||
return this.getList().iterator();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.registries.holdersets;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface HolderSetType
|
||||
{
|
||||
<T> Codec<? extends ICustomHolderSet<T>> makeCodec(ResourceKey<? extends Registry<T>> registryKey, Codec<Holder<T>> holderCodec, boolean forceList);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.registries.holdersets;
|
||||
|
||||
import net.minecraft.core.HolderSet;
|
||||
|
||||
/**
|
||||
* Interface for mods' custom holderset types
|
||||
*/
|
||||
public interface ICustomHolderSet<T> extends HolderSet<T>
|
||||
{
|
||||
/**
|
||||
* {@return HolderSetType registered to {@link ForgeRegistries.HOLDER_SET_TYPES}}
|
||||
*/
|
||||
HolderSetType type();
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.registries.holdersets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.HolderSetCodec;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
|
||||
/**
|
||||
* <p>Holderset that represents all elements of a registry not present in another holderset.
|
||||
* forge:exclusion is preferable when the number of allowed elements is small relative to the size of the registry.
|
||||
* Json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:not",
|
||||
* "value": "not_this_holderset" // string, list, or object
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
// this doesn't extend CompositeHolderSet because it doesn't need to cache a set
|
||||
public class NotHolderSet<T> implements ICustomHolderSet<T>
|
||||
{
|
||||
public static <T> Codec<? extends ICustomHolderSet<T>> codec(ResourceKey<? extends Registry<T>> registryKey, Codec<Holder<T>> holderCodec, boolean forceList)
|
||||
{
|
||||
return RecordCodecBuilder.<NotHolderSet<T>>create(builder -> builder.group(
|
||||
RegistryOps.retrieveRegistry(registryKey).forGetter(NotHolderSet::registry),
|
||||
HolderSetCodec.create(registryKey, holderCodec, forceList).fieldOf("value").forGetter(NotHolderSet::value)
|
||||
).apply(builder, NotHolderSet::new));
|
||||
}
|
||||
|
||||
private final List<Runnable> owners = new ArrayList<>();
|
||||
private final Registry<T> registry;
|
||||
private final HolderSet<T> value;
|
||||
@Nullable
|
||||
private List<Holder<T>> list = null;
|
||||
|
||||
public Registry<T> registry() { return this.registry; }
|
||||
public HolderSet<T> value() { return this.value; }
|
||||
|
||||
public NotHolderSet(Registry<T> registry, HolderSet<T> value)
|
||||
{
|
||||
this.registry = registry;
|
||||
this.value = value;
|
||||
this.value.addInvalidationListener(this::invalidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderSetType type()
|
||||
{
|
||||
return ForgeMod.NOT_HOLDER_SET.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInvalidationListener(Runnable runnable)
|
||||
{
|
||||
this.owners.add(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Holder<T>> iterator()
|
||||
{
|
||||
return this.getList().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Holder<T>> stream()
|
||||
{
|
||||
return this.getList().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return this.getList().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Either<TagKey<T>, List<Holder<T>>> unwrap()
|
||||
{
|
||||
return Either.right(this.getList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Holder<T>> getRandomElement(RandomSource random)
|
||||
{
|
||||
List<Holder<T>> list = this.getList();
|
||||
int size = list.size();
|
||||
return size > 0
|
||||
? Optional.of(list.get(random.nextInt(size)))
|
||||
: Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Holder<T> get(int i)
|
||||
{
|
||||
return this.getList().get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Holder<T> holder)
|
||||
{
|
||||
return !this.value.contains(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInRegistry(Registry<T> registry)
|
||||
{
|
||||
return this.registry == registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "NotSet(" + this.value + ")";
|
||||
}
|
||||
|
||||
private List<Holder<T>> getList()
|
||||
{
|
||||
List<Holder<T>> thisList = this.list;
|
||||
if (thisList == null)
|
||||
{
|
||||
List<Holder<T>> list = this.registry.holders()
|
||||
.filter(holder -> !this.value.contains(holder))
|
||||
.map(holder -> (Holder<T>)holder)
|
||||
.toList();
|
||||
this.list = list;
|
||||
return list;
|
||||
}
|
||||
else
|
||||
{
|
||||
return thisList;
|
||||
}
|
||||
}
|
||||
|
||||
private void invalidate()
|
||||
{
|
||||
this.list = null;
|
||||
for (Runnable runnable : this.owners)
|
||||
{
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 a union of other holdersets. Json format:</p>
|
||||
* <pre>
|
||||
* {
|
||||
* "type": "forge:or",
|
||||
* "values":
|
||||
* [
|
||||
* // list of sub-holdersets (strings, lists, or objects)
|
||||
* ]
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class OrHolderSet<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(OrHolderSet::new, OrHolderSet::getComponents)
|
||||
.fieldOf("values")
|
||||
.codec();
|
||||
}
|
||||
|
||||
public OrHolderSet(List<HolderSet<T>> values)
|
||||
{
|
||||
super(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderSetType type()
|
||||
{
|
||||
return ForgeMod.OR_HOLDER_SET.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Holder<T>> createSet()
|
||||
{
|
||||
return this.getComponents().stream().flatMap(HolderSet::stream).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "OrSet[" + this.getComponents() + "]";
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,7 @@ public class PathPackResources extends AbstractPackResources
|
||||
{
|
||||
Path root = resolve(type.getDirectory());
|
||||
return Files.walk(root, 1)
|
||||
.filter(Files::isDirectory)
|
||||
.map(path -> root.relativize(path))
|
||||
.filter(path -> path.getNameCount() > 0) // skip the root entry
|
||||
.map(p -> p.toString().replaceAll("/$", "")) // remove the trailing slash, if present
|
||||
|
||||
@@ -77,6 +77,7 @@ public net.minecraft.client.particle.ParticleEngine m_107381_(Lnet/minecraft/cor
|
||||
public net.minecraft.client.particle.ParticleEngine$SpriteParticleRegistration
|
||||
public net.minecraft.client.player.LocalPlayer m_8088_()I # getPermissionLevel
|
||||
public net.minecraft.client.renderer.GameRenderer m_109128_(Lnet/minecraft/resources/ResourceLocation;)V # loadEffect
|
||||
public net.minecraft.client.renderer.LevelRenderer m_109817_()Z # shouldShowEntityOutlines
|
||||
protected-f net.minecraft.client.renderer.RenderStateShard f_110131_ # setupState
|
||||
public net.minecraft.client.renderer.RenderStateShard$BooleanStateShard
|
||||
public net.minecraft.client.renderer.RenderStateShard$CullStateShard
|
||||
@@ -268,6 +269,7 @@ public-f net.minecraft.data.tags.TagsProvider m_6055_()Ljava/lang/String; # getN
|
||||
public net.minecraft.data.tags.TagsProvider$TagAppender f_126569_ # registry
|
||||
public net.minecraft.gametest.framework.GameTestServer <init>(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lnet/minecraft/server/packs/repository/PackRepository;Lnet/minecraft/server/WorldStem;Ljava/util/Collection;Lnet/minecraft/core/BlockPos;)V # constructor
|
||||
public net.minecraft.network.protocol.status.ClientboundStatusResponsePacket f_134885_ # GSON
|
||||
public net.minecraft.resources.RegistryOps f_206806_ # registryAccess
|
||||
public net.minecraft.resources.ResourceLocation m_135835_(C)Z # validNamespaceChar
|
||||
public net.minecraft.resources.ResourceLocation m_135841_(Ljava/lang/String;)Z # isValidPath
|
||||
public net.minecraft.resources.ResourceLocation m_135843_(Ljava/lang/String;)Z # isValidNamespace
|
||||
|
||||
@@ -2,6 +2,7 @@ com/mojang/blaze3d/vertex/VertexConsumer.putBulkData(Lcom/mojang/blaze3d/vertex/
|
||||
net/minecraft/advancements/Advancement$Builder.fromJson(Lcom/google/gson/JsonObject;Lnet/minecraft/advancements/critereon/DeserializationContext;Lnet/minecraftforge/common/crafting/conditions/ICondition$IContext;)Lnet/minecraft/advancements/Advancement$Builder;=|p_138381_,p_138382_,context
|
||||
net/minecraft/client/Options.processOptionsForge(Lnet/minecraft/client/Options$FieldAccess;)V=|p_168428_
|
||||
net/minecraft/client/gui/screens/MenuScreens.getScreenFactory(Lnet/minecraft/world/inventory/MenuType;Lnet/minecraft/client/Minecraft;ILnet/minecraft/network/chat/Component;)Ljava/util/Optional;=|p_96202_,p_96203_,p_96204_,p_96205_
|
||||
net/minecraft/client/gui/screens/inventory/InventoryScreen.renderEntityInInventoryRaw(IIIFFLnet/minecraft/world/entity/LivingEntity;)V=|p_98851_,p_98852_,p_98853_,angleXComponent,angleYComponent,p_98856_
|
||||
net/minecraft/client/gui/screens/worldselection/WorldOpenFlows.doLoadLevel(Lnet/minecraft/client/gui/screens/Screen;Ljava/lang/String;ZZZ)V=|p_233146_,p_233147_,p_233148_,p_233149_,confirmExperimentalWarning
|
||||
net/minecraft/client/renderer/ScreenEffectRenderer.getOverlayBlock(Lnet/minecraft/world/entity/player/Player;)Lorg/apache/commons/lang3/tuple/Pair;=|p_110717_
|
||||
net/minecraft/client/renderer/ScreenEffectRenderer.renderFluid(Lnet/minecraft/client/Minecraft;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/resources/ResourceLocation;)V=|p_110726_,p_110727_,texture
|
||||
@@ -14,7 +15,7 @@ net/minecraft/client/renderer/block/ModelBlockRenderer.renderModel(Lcom/mojang/b
|
||||
net/minecraft/client/renderer/block/ModelBlockRenderer.tesselateBlock(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZLnet/minecraft/util/RandomSource;JILnet/minecraftforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V=|p_111048_,p_111049_,p_111050_,p_111051_,p_111052_,p_111053_,p_111054_,p_111055_,p_111056_,p_111057_,modelData,renderType
|
||||
net/minecraft/client/renderer/block/ModelBlockRenderer.tesselateWithAO(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZLnet/minecraft/util/RandomSource;JILnet/minecraftforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V=|p_111079_,p_111080_,p_111081_,p_111082_,p_111083_,p_111084_,p_111085_,p_111086_,p_111087_,p_111088_,modelData,renderType
|
||||
net/minecraft/client/renderer/block/ModelBlockRenderer.tesselateWithoutAO(Lnet/minecraft/world/level/BlockAndTintGetter;Lnet/minecraft/client/resources/model/BakedModel;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;ZLnet/minecraft/util/RandomSource;JILnet/minecraftforge/client/model/data/ModelData;Lnet/minecraft/client/renderer/RenderType;)V=|p_111091_,p_111092_,p_111093_,p_111094_,p_111095_,p_111096_,p_111097_,p_111098_,p_111099_,p_111100_,modelData,renderType
|
||||
net/minecraft/client/renderer/block/model/BlockElementFace.<init>(Lnet/minecraft/core/Direction;ILjava/lang/String;Lnet/minecraft/client/renderer/block/model/BlockFaceUV;Z)V=|p_111359_,p_111360_,p_111361_,p_111362_,emissive
|
||||
net/minecraft/client/renderer/block/model/BlockElementFace.<init>(Lnet/minecraft/core/Direction;ILjava/lang/String;Lnet/minecraft/client/renderer/block/model/BlockFaceUV;I)V=|p_111359_,p_111360_,p_111361_,p_111362_,emissivity
|
||||
net/minecraft/client/renderer/block/model/BlockModel.bakeVanilla(Lnet/minecraft/client/resources/model/ModelBakery;Lnet/minecraft/client/renderer/block/model/BlockModel;Ljava/util/function/Function;Lnet/minecraft/client/resources/model/ModelState;Lnet/minecraft/resources/ResourceLocation;ZLnet/minecraftforge/client/RenderTypeGroup;)Lnet/minecraft/client/resources/model/BakedModel;=|p_111450_,p_111451_,p_111452_,p_111453_,p_111454_,p_111455_,renderTypes
|
||||
net/minecraft/client/renderer/block/model/ItemTransform.<init>(Lcom/mojang/math/Vector3f;Lcom/mojang/math/Vector3f;Lcom/mojang/math/Vector3f;Lcom/mojang/math/Vector3f;)V=|p_111760_,p_111761_,p_111762_,rightRotation
|
||||
net/minecraft/client/renderer/block/model/ItemTransforms.<init>(Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lnet/minecraft/client/renderer/block/model/ItemTransform;Lcom/google/common/collect/ImmutableMap;)V=|p_111798_,p_111799_,p_111800_,p_111801_,p_111802_,p_111803_,p_111804_,p_111805_,moddedTransforms
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.client;
|
||||
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.ColorResolver;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
/**
|
||||
* This mod tests custom {@link ColorResolver ColorResolvers} using {@link RegisterColorHandlersEvent.ColorResolvers}.
|
||||
* To test, place the registered test block, it should be tinted blue in biomes with precipitation and red in others.
|
||||
* The color should blend according to the biome blend setting.
|
||||
*/
|
||||
@Mod(CustomColorResolverTest.MOD_ID)
|
||||
public class CustomColorResolverTest
|
||||
{
|
||||
static final String MOD_ID = "custom_color_resolver_test";
|
||||
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID);
|
||||
private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MOD_ID);
|
||||
|
||||
private static final RegistryObject<Block> BLOCK = BLOCKS.register("test_block", () -> new Block(BlockBehaviour.Properties.of(Material.STONE)));
|
||||
|
||||
public CustomColorResolverTest()
|
||||
{
|
||||
final IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
ITEMS.register(modBus);
|
||||
BLOCKS.register(modBus);
|
||||
|
||||
ITEMS.register("test_block", () -> new BlockItem(BLOCK.get(), new Item.Properties()));
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber(value = Dist.CLIENT, modid=MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
private static class ClientHandler
|
||||
{
|
||||
|
||||
private static final ColorResolver COLOR_RESOLVER = (biome, x, z) -> biome.getPrecipitation() == Biome.Precipitation.NONE ? 0xFF0000 : 0x0000FF;
|
||||
|
||||
@SubscribeEvent
|
||||
static void registerColorResolver(RegisterColorHandlersEvent.ColorResolvers event)
|
||||
{
|
||||
event.register(COLOR_RESOLVER);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
static void registerBlockColor(RegisterColorHandlersEvent.Block event)
|
||||
{
|
||||
event.register(((state, btGetter, pos, tintIndex) -> btGetter == null || pos == null ? 0 : btGetter.getBlockTint(pos, COLOR_RESOLVER)), BLOCK.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.debug.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.ScreenEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@@ -49,10 +50,15 @@ public class PotionSizeEventTest
|
||||
if (player.getActiveEffects().size() <= 3)
|
||||
{
|
||||
event.setCompact(true); // Force compact mode for 3 or less active effects
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
event.setCompact(false); // Force classic mode for 4 or more active effects
|
||||
}
|
||||
if (player.hasEffect(MobEffects.MOVEMENT_SLOWDOWN))
|
||||
{
|
||||
event.addHorizontalOffset(20); // Move the effect rendering to the right when slowness is enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.client.rendering;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.IItemDecorator;
|
||||
import net.minecraftforge.client.ItemDecoratorHandler;
|
||||
import net.minecraftforge.client.event.RegisterItemDecorationsEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
@Mod(CustomItemDecorationsTest.MOD_ID)
|
||||
public class CustomItemDecorationsTest
|
||||
{
|
||||
public static final String MOD_ID = "custom_item_decorations_test";
|
||||
private static final boolean ENABLED = true;
|
||||
|
||||
public CustomItemDecorationsTest() { }
|
||||
|
||||
@Mod.EventBusSubscriber(modid = CustomItemDecorationsTest.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
||||
public static class ClientEvents
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void onRegisterItemDecorations(final RegisterItemDecorationsEvent event)
|
||||
{
|
||||
if (ENABLED)
|
||||
event.register(Items.EGG, new StackSizeDurabilityBar());
|
||||
}
|
||||
}
|
||||
|
||||
private static class StackSizeDurabilityBar implements IItemDecorator
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean render(Font font, ItemStack stack, int xOffset, int yOffset, float blitOffset)
|
||||
{
|
||||
RenderSystem.disableTexture();
|
||||
RenderSystem.disableBlend();
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
BufferBuilder bufferbuilder = tesselator.getBuilder();
|
||||
float f = Math.max(0.0F, (stack.getMaxStackSize() - (float)stack.getCount()) / stack.getMaxStackSize());
|
||||
int i = Math.round(13.0F - (float)stack.getCount() * 13.0F / stack.getMaxStackSize());
|
||||
int j = Mth.hsvToRgb(f / 3.0F,1f,1f);
|
||||
fillRect(bufferbuilder, xOffset + 2, yOffset, blitOffset + 189, 13, 2, 0, 0, 0);
|
||||
fillRect(bufferbuilder, xOffset + 2, yOffset, blitOffset + 190, i, 1, j >> 16 & 255, j >> 8 & 255, j & 255);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.enableTexture();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void fillRect(BufferBuilder pRenderer, int pX, int pY, float pZ, int pWidth, int pHeight, int pRed, int pGreen, int pBlue)
|
||||
{
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
pRenderer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
pRenderer.vertex(pX, pY, pZ).color(pRed, pGreen, pBlue, 255).endVertex();
|
||||
pRenderer.vertex(pX, pY + pHeight, pZ).color(pRed, pGreen, pBlue, 255).endVertex();
|
||||
pRenderer.vertex(pX + pWidth, pY + pHeight, pZ).color(pRed, pGreen, pBlue, 255).endVertex();
|
||||
pRenderer.vertex(pX + pWidth, pY, pZ).color(pRed, pGreen, pBlue, 255).endVertex();
|
||||
BufferUploader.drawWithShader(pRenderer.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.entity.player;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.entity.HumanoidArm;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.UseAnim;
|
||||
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.registries.DeferredRegister;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.RegistryObject;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Tests if item usage animation system works as intended. `item_use_animation_test:thing` is edible item with custom usage animation made with this system.
|
||||
* In game, use `/give @s item_use_animation_test:thing 1` to obtain test item
|
||||
* When you try to eat it, your arm in 3d person should start swinging really fast.
|
||||
* And item in your hand will go down little.
|
||||
*/
|
||||
@Mod(ItemUseAnimationTest.MOD_ID)
|
||||
public class ItemUseAnimationTest
|
||||
{
|
||||
|
||||
public static final String MOD_ID = "item_use_animation_test";
|
||||
|
||||
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID);
|
||||
|
||||
private static final RegistryObject<Item> THING = ITEMS.register("thing", () -> new ThingItem(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).food(new FoodProperties.Builder().nutrition(4).alwaysEat().build())));
|
||||
|
||||
public ItemUseAnimationTest()
|
||||
{
|
||||
ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
|
||||
}
|
||||
|
||||
private static class ThingItem extends Item
|
||||
{
|
||||
|
||||
public ThingItem(Item.Properties props)
|
||||
{
|
||||
super(props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UseAnim getUseAnimation(ItemStack stack)
|
||||
{
|
||||
return UseAnim.CUSTOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeClient(Consumer<IClientItemExtensions> consumer)
|
||||
{
|
||||
consumer.accept(new IClientItemExtensions()
|
||||
{
|
||||
|
||||
private static final HumanoidModel.ArmPose SWING_POSE = HumanoidModel.ArmPose.create("SWING", false, (model, entity, arm) -> {
|
||||
if (arm == HumanoidArm.RIGHT)
|
||||
{
|
||||
model.rightArm.xRot = (float) (Math.random() * Math.PI * 2);
|
||||
} else
|
||||
{
|
||||
model.leftArm.xRot = (float) (Math.random() * Math.PI * 2);
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public HumanoidModel.ArmPose getArmPose(LivingEntity entityLiving, InteractionHand hand, ItemStack itemStack)
|
||||
{
|
||||
if (!itemStack.isEmpty())
|
||||
{
|
||||
if (entityLiving.getUsedItemHand() == hand && entityLiving.getUseItemRemainingTicks() > 0)
|
||||
{
|
||||
return SWING_POSE;
|
||||
}
|
||||
}
|
||||
return HumanoidModel.ArmPose.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyForgeHandTransform(PoseStack poseStack, LocalPlayer player, HumanoidArm arm, ItemStack itemInHand, float partialTick, float equipProcess, float swingProcess) {
|
||||
applyItemArmTransform(poseStack, arm);
|
||||
if (player.isUsingItem()) {
|
||||
poseStack.translate(0.0, -0.05, 0.0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void applyItemArmTransform(PoseStack poseStack, HumanoidArm arm) {
|
||||
int i = arm == HumanoidArm.RIGHT ? 1 : -1;
|
||||
poseStack.translate(i * 0.56F, -0.52F, -0.72F);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug.misc;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.AnvilUpdateEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* This class provides a way to test the AnvilUpdateEvent. <br>
|
||||
* The event is now fired as described in the javadoc (of AnvilUpdateEvent). <br>
|
||||
* "AnvilUpdateEvent is fired whenever the input stacks (left or right) or the name in an anvil changed."
|
||||
*/
|
||||
@Mod(AnvilUpdateEventTest.MOD_ID)
|
||||
public class AnvilUpdateEventTest
|
||||
{
|
||||
private static final boolean ENABLED = false;
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
static final String MOD_ID = "anvil_update_event_fix";
|
||||
|
||||
public AnvilUpdateEventTest()
|
||||
{
|
||||
if (ENABLED)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.addListener(this::anvilUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
private void anvilUpdate(AnvilUpdateEvent event)
|
||||
{
|
||||
LOGGER.info("Anvil input or name changed!");
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import net.minecraftforge.event.level.LevelEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
/**
|
||||
* <p>This tests net.minecraftforge.event.world.World.WorldEvent.PotentialSpawns. If ENABLED is set to true,
|
||||
* <p>This tests net.minecraftforge.event.world.World.LevelEvent.PotentialSpawns. If ENABLED is set to true,
|
||||
* this test mod uses the PotentialSpawns event to prevent mobs in the MONSTER mob category from spawning if the
|
||||
* game difficulty is set to anything other than hard.</p>
|
||||
*/
|
||||
|
||||
@@ -242,6 +242,12 @@ modId="custom_transformtype_test"
|
||||
modId="mega_model_test"
|
||||
[[mods]]
|
||||
modId="emissive_elements_test"
|
||||
[[mods]]
|
||||
modId="anvil_update_event_fix"
|
||||
[[mods]]
|
||||
modId="item_use_animation_test"
|
||||
[[mods]]
|
||||
modId="custom_color_resolver_test"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "custom_color_resolver_test:block/block"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"parent": "minecraft:block/grass_block"
|
||||
}
|
||||
Reference in new issue
Block a user