mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 01:04:24 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb2bbeed0 | ||
|
|
12d24df4f6 | ||
|
|
e69f5e262a | ||
|
|
23cee57d88 | ||
|
|
ab70bde1d6 | ||
|
|
f65381fbff | ||
|
|
b680d09359 | ||
|
|
7969daf81a | ||
|
|
f157567d2a | ||
|
|
93a615e900 | ||
|
|
7c84249996 | ||
|
|
881725c7d5 | ||
|
|
2745531f08 | ||
|
|
bcdd44aece | ||
|
|
bad5b1b5d4 | ||
|
|
30f255d76c | ||
|
|
ebb316a15c | ||
|
|
e6bb7eecbd | ||
|
|
c66f70d6c2 | ||
|
|
26adf4da44 | ||
|
|
30d0a630d6 | ||
|
|
00ad61b4ae | ||
|
|
09bc73d5cd | ||
|
|
1ee53c0464 | ||
|
|
16863c8d3b | ||
|
|
150e8281ae | ||
|
|
4385eb2155 | ||
|
|
5c40bef28e | ||
|
|
55aa419100 | ||
|
|
a4bef82836 | ||
|
|
b741df5f18 | ||
|
|
0c81a71308 | ||
|
|
ea7f755a11 | ||
|
|
d947d35eb1 | ||
|
|
5271ef79fe | ||
|
|
b7131824f0 | ||
|
|
3e624db4f8 | ||
|
|
fc7af96bde | ||
|
|
b1965db30b | ||
|
|
8df5a80725 | ||
|
|
d9043298d3 | ||
|
|
e91ff9a5a6 | ||
|
|
77fb08713f | ||
|
|
2c965fac90 | ||
|
|
2f229c5bb1 | ||
|
|
54b08d2711 | ||
|
|
46f641a502 | ||
|
|
6304cb655b |
No files matched your search
+18
-9
@@ -27,8 +27,8 @@ plugins {
|
||||
id 'net.minecraftforge.gradleutils' version '2.+'
|
||||
id 'eclipse'
|
||||
id 'de.undercouch.download' version '5.4.0'
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.6,6.2)' apply false
|
||||
id 'net.minecraftforge.gradle.mcp' version '[6.0.6,6.2)' apply false
|
||||
id 'net.minecraftforge.gradle.patcher' version '[6.0.11,6.2)' apply false
|
||||
id 'net.minecraftforge.gradle.mcp' version '[6.0.11,6.2)' apply false
|
||||
}
|
||||
|
||||
Util.init() //Init all our extension methods!
|
||||
@@ -209,6 +209,11 @@ subprojects {
|
||||
maven gradleutils.getPublishingForgeMaven()
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
options.warnings = false // Shutup deprecated for removal warnings
|
||||
}
|
||||
}
|
||||
|
||||
project(':mcp') {
|
||||
@@ -887,9 +892,8 @@ project(':forge') {
|
||||
apply plugin: 'org.cadixdev.licenser'
|
||||
|
||||
applyPatches {
|
||||
verbose = true
|
||||
//failOnError = false
|
||||
}
|
||||
level 'WARNING'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
@@ -1775,10 +1779,10 @@ project(':forge') {
|
||||
}
|
||||
// Since we need the modules in the bootstrap, we need to make sure they are compiled before we do each run
|
||||
afterEvaluate { prepareRuns.dependsOn(PACKED_DEPS) }
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
|
||||
}
|
||||
|
||||
// Make sure we run bin compat checking during local testing.
|
||||
if (!System.env.MAVEN_USER || !System.env.MAVEN_PASSWORD)
|
||||
publish.dependsOn(':forge:checkJarCompatibility')
|
||||
}
|
||||
|
||||
//evaluationDependsOnChildren()
|
||||
@@ -1789,6 +1793,11 @@ task setup() { //These must be strings so that we can do lazy resolution. Else
|
||||
dependsOn ':forge:extractMapped'
|
||||
}
|
||||
|
||||
task doChecks {
|
||||
dependsOn ':forge:checkJarCompatibility'
|
||||
dependsOn ':forge:publish'
|
||||
}
|
||||
|
||||
if (symlinkValid)
|
||||
project.gradle.startParameter.excludedTaskNames.add(':fmlonly:genPatches')
|
||||
project.gradle.startParameter.excludedTaskNames.add(':clean:genPatches')
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ You can download the installer for the *Recommended Build* or the
|
||||
*Latest build* there. Latest builds may have newer features but may be
|
||||
more unstable as a result. The installer will attempt to install Forge
|
||||
into your vanilla launcher environment, where you can then create a new
|
||||
profile using that version and play the game!
|
||||
profile using that version and play the game!
|
||||
|
||||
For support and questions, visit [the Support Forum][Support-Forum] or [the Forge Discord server][Discord].
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.4 MiB |
@@ -0,0 +1,11 @@
|
||||
--- a/com/mojang/blaze3d/vertex/SheetedDecalTextureGenerator.java
|
||||
+++ b/com/mojang/blaze3d/vertex/SheetedDecalTextureGenerator.java
|
||||
@@ -46,7 +_,7 @@
|
||||
|
||||
public void m_5752_() {
|
||||
Vector3f vector3f = this.f_85869_.transform(new Vector3f(this.f_85876_, this.f_85877_, this.f_85878_));
|
||||
- Direction direction = Direction.m_122372_(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
+ Direction direction = net.minecraftforge.client.ForgeHooksClient.getNearestStable(vector3f.x(), vector3f.y(), vector3f.z());
|
||||
Vector4f vector4f = this.f_85868_.transform(new Vector4f(this.f_85870_, this.f_85871_, this.f_85872_, 1.0F));
|
||||
vector4f.rotateY((float)Math.PI);
|
||||
vector4f.rotateX((-(float)Math.PI / 2F));
|
||||
@@ -12,6 +12,15 @@
|
||||
private static final Set<String> f_90811_ = Sets.newHashSet();
|
||||
public static final String f_167805_ = "key.categories.movement";
|
||||
public static final String f_167806_ = "key.categories.misc";
|
||||
@@ -41,7 +_,7 @@
|
||||
private int f_90818_;
|
||||
|
||||
public static void m_90835_(InputConstants.Key p_90836_) {
|
||||
- KeyMapping keymapping = f_90810_.get(p_90836_);
|
||||
+ for (KeyMapping keymapping : f_90810_.getAll(p_90836_))
|
||||
if (keymapping != null) {
|
||||
++keymapping.f_90818_;
|
||||
}
|
||||
@@ -49,7 +_,7 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,14 @@
|
||||
TextureAtlasSprite textureatlassprite = mobeffecttexturemanager.m_118732_(mobeffect);
|
||||
int i1 = j;
|
||||
float f1 = f;
|
||||
@@ -574,12 +_,13 @@
|
||||
@@ -572,16 +_,21 @@
|
||||
}
|
||||
|
||||
public void m_280295_(GuiGraphics p_283501_) {
|
||||
+ renderSelectedItemName(p_283501_, 0);
|
||||
+ }
|
||||
+
|
||||
+ public void renderSelectedItemName(GuiGraphics p_283501_, int yShift) {
|
||||
this.f_92986_.m_91307_().m_6180_("selectedItemName");
|
||||
if (this.f_92993_ > 0 && !this.f_92994_.m_41619_()) {
|
||||
- MutableComponent mutablecomponent = Component.m_237119_().m_7220_(this.f_92994_.m_41786_()).m_130940_(this.f_92994_.m_41791_().f_43022_);
|
||||
@@ -31,8 +37,11 @@
|
||||
+ Component highlightTip = this.f_92994_.getHighlightTip(mutablecomponent);
|
||||
+ int i = this.m_93082_().m_92852_(highlightTip);
|
||||
int j = (this.f_92977_ - i) / 2;
|
||||
int k = this.f_92978_ - 59;
|
||||
- int k = this.f_92978_ - 59;
|
||||
+ int k = this.f_92978_ - Math.max(yShift, 59);
|
||||
if (!this.f_92986_.f_91072_.m_105205_()) {
|
||||
k += 14;
|
||||
}
|
||||
@@ -593,7 +_,13 @@
|
||||
|
||||
if (l > 0) {
|
||||
|
||||
@@ -33,6 +33,26 @@
|
||||
int i = p_282636_.m_272191_(p_281596_, (float)p_281586_, (float)p_282816_, p_281743_, p_282394_, this.f_279612_.m_85850_().m_252922_(), this.f_279627_, Font.DisplayMode.NORMAL, 0, 15728880);
|
||||
this.m_286081_();
|
||||
return i;
|
||||
@@ -405,6 +_,10 @@
|
||||
}
|
||||
|
||||
public void m_280543_(ResourceLocation p_283059_, int p_283575_, int p_283192_, int p_281790_, int p_283642_, int p_282691_, int p_281912_, int p_281728_, int p_282324_) {
|
||||
+ blitRepeating(p_283059_, p_283575_, p_283192_, p_281790_, p_283642_, p_282691_, p_281912_, p_281728_, p_282324_, 256, 256);
|
||||
+ }
|
||||
+
|
||||
+ public void blitRepeating(ResourceLocation p_283059_, int p_283575_, int p_283192_, int p_281790_, int p_283642_, int p_282691_, int p_281912_, int p_281728_, int p_282324_, int textureWidth, int textureHeight) {
|
||||
int i = p_283575_;
|
||||
|
||||
int j;
|
||||
@@ -417,7 +_,7 @@
|
||||
for(IntIterator intiterator1 = m_280358_(p_283642_, p_282324_); intiterator1.hasNext(); l += i1) {
|
||||
i1 = intiterator1.nextInt();
|
||||
int j1 = (p_282324_ - i1) / 2;
|
||||
- this.m_280218_(p_283059_, i, l, p_282691_ + k, p_281912_ + j1, j, i1);
|
||||
+ this.m_280163_(p_283059_, i, l, p_282691_ + k, p_281912_ + j1, j, i1, textureWidth, textureHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,6 +_,7 @@
|
||||
crashreportcategory.m_128165_("Item Type", () -> {
|
||||
return String.valueOf((Object)p_281675_.m_41720_());
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
@@ -82,6 +_,7 @@
|
||||
} else {
|
||||
gridlayout$rowhelper.m_264139_(this.m_262456_(f_262254_, SocialInteractionsScreen::new));
|
||||
}
|
||||
+ gridlayout$rowhelper.m_264108_(Button.m_253074_(Component.m_237115_("fml.menu.mods"), button -> this.f_96541_.m_91152_(new net.minecraftforge.client.gui.ModListScreen(this))).m_252780_(f_262268_).m_253136_(), 2);
|
||||
|
||||
Component component = this.f_96541_.m_91090_() ? f_262217_ : f_262246_;
|
||||
this.f_252482_ = gridlayout$rowhelper.m_264108_(Button.m_253074_(component, (p_280815_) -> {
|
||||
+5
-1
@@ -34,7 +34,7 @@
|
||||
this.f_97334_.m_104401_(advancementtab.m_97182_(), true);
|
||||
break;
|
||||
}
|
||||
@@ -98,6 +_,11 @@
|
||||
@@ -98,9 +_,15 @@
|
||||
int i = (this.f_96543_ - 252) / 2;
|
||||
int j = (this.f_96544_ - 140) / 2;
|
||||
this.m_280273_(p_282589_);
|
||||
@@ -46,6 +46,10 @@
|
||||
this.m_97373_(p_282589_, p_282255_, p_283354_, i, j);
|
||||
this.m_280088_(p_282589_, i, j);
|
||||
this.m_280355_(p_282589_, p_282255_, p_283354_, i, j);
|
||||
+ super.m_88315_(p_282589_, p_282255_, p_283354_, p_283123_);
|
||||
}
|
||||
|
||||
public boolean m_7979_(double p_97347_, double p_97348_, int p_97349_, double p_97350_, double p_97351_) {
|
||||
@@ -135,10 +_,12 @@
|
||||
p_283395_.m_280218_(f_97329_, p_281890_, p_282532_, 0, 0, 252, 140);
|
||||
if (this.f_97335_.size() > 1) {
|
||||
|
||||
+9
-5
@@ -187,7 +187,7 @@
|
||||
list1.add(i++, creativemodetab.m_40786_().m_6881_().m_130940_(ChatFormatting.BLUE));
|
||||
}
|
||||
}
|
||||
@@ -639,13 +_,13 @@
|
||||
@@ -639,21 +_,22 @@
|
||||
}
|
||||
|
||||
protected void m_7286_(GuiGraphics p_282663_, float p_282504_, int p_282089_, int p_282249_) {
|
||||
@@ -203,8 +203,10 @@
|
||||
this.f_98510_.m_88315_(p_282663_, p_282089_, p_282249_, p_282504_);
|
||||
int j = this.f_97735_ + 175;
|
||||
int k = this.f_97736_ + 18;
|
||||
@@ -654,6 +_,7 @@
|
||||
p_282663_.m_280218_(f_98504_, j, k + (int)((float)(i - k - 17) * this.f_98508_), 232 + (this.m_98631_() ? 0 : 12), 0, 12, 15);
|
||||
int i = k + 112;
|
||||
if (f_98507_.m_40791_()) {
|
||||
- p_282663_.m_280218_(f_98504_, j, k + (int)((float)(i - k - 17) * this.f_98508_), 232 + (this.m_98631_() ? 0 : 12), 0, 12, 15);
|
||||
+ p_282663_.m_280218_(f_98507_.getTabsImage(), j, k + (int)((float)(i - k - 17) * this.f_98508_), 232 + (this.m_98631_() ? 0 : 12), 0, 12, 15);
|
||||
}
|
||||
|
||||
+ if (currentPage.getVisibleTabs().contains(f_98507_)) //Forge: only display tab selection when the selected tab is on the current page
|
||||
@@ -240,14 +242,16 @@
|
||||
int j = i * 26;
|
||||
int k = 0;
|
||||
int l = this.f_97735_ + this.m_258094_(p_283489_);
|
||||
@@ -720,6 +_,7 @@
|
||||
@@ -720,7 +_,8 @@
|
||||
i1 += this.f_97727_ - 4;
|
||||
}
|
||||
|
||||
- p_283590_.m_280218_(f_98504_, l, i1, j, k, 26, 32);
|
||||
+ com.mojang.blaze3d.systems.RenderSystem.enableBlend(); //Forge: Make sure blend is enabled else tabs show a white border.
|
||||
p_283590_.m_280218_(f_98504_, l, i1, j, k, 26, 32);
|
||||
+ p_283590_.m_280218_(p_283489_.getTabsImage(), l, i1, j, k, 26, 32);
|
||||
p_283590_.m_280168_().m_85836_();
|
||||
p_283590_.m_280168_().m_252880_(0.0F, 0.0F, 100.0F);
|
||||
l += 5;
|
||||
@@ -763,6 +_,14 @@
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
BlockState blockstate = this.f_105189_.f_91073_.m_8055_(p_105270_);
|
||||
this.f_105189_.m_91301_().m_120581_(this.f_105189_.f_91073_, p_105270_, blockstate, 1.0F);
|
||||
this.m_233729_(this.f_105189_.f_91073_, (p_233757_) -> {
|
||||
+ if (!net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105270_, p_105271_).isCanceled())
|
||||
+ if (!net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105270_, p_105271_, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK).isCanceled())
|
||||
this.m_105267_(p_105270_);
|
||||
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, p_105270_, p_105271_, p_233757_);
|
||||
});
|
||||
@@ -31,7 +31,7 @@
|
||||
if (this.f_105196_) {
|
||||
this.f_105190_.m_104955_(new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK, this.f_105191_, p_105271_));
|
||||
}
|
||||
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock event = net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105270_, p_105271_);
|
||||
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock event = net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105270_, p_105271_, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK);
|
||||
|
||||
BlockState blockstate1 = this.f_105189_.f_91073_.m_8055_(p_105270_);
|
||||
this.f_105189_.m_91301_().m_120581_(this.f_105189_.f_91073_, p_105270_, blockstate1, 0.0F);
|
||||
@@ -60,7 +60,7 @@
|
||||
BlockState blockstate1 = this.f_105189_.f_91073_.m_8055_(p_105284_);
|
||||
this.f_105189_.m_91301_().m_120581_(this.f_105189_.f_91073_, p_105284_, blockstate1, 1.0F);
|
||||
this.m_233729_(this.f_105189_.f_91073_, (p_233753_) -> {
|
||||
+ if (!net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105284_, p_105285_).isCanceled())
|
||||
+ if (!net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105284_, p_105285_, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK).isCanceled())
|
||||
this.m_105267_(p_105284_);
|
||||
return new ServerboundPlayerActionPacket(ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK, p_105284_, p_105285_, p_233753_);
|
||||
});
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
++this.f_105194_;
|
||||
this.f_105189_.m_91301_().m_120581_(this.f_105189_.f_91073_, p_105284_, blockstate, Mth.m_14036_(this.f_105193_, 0.0F, 1.0F));
|
||||
+ if (net.minecraftforge.common.ForgeHooks.onLeftClickBlock(this.f_105189_.f_91074_, p_105284_, p_105285_).getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return true;
|
||||
+ if (net.minecraftforge.common.ForgeHooks.onClientMineHold(this.f_105189_.f_91074_, p_105284_, p_105285_).getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return true;
|
||||
if (this.f_105193_ >= 1.0F) {
|
||||
this.f_105196_ = false;
|
||||
this.m_233729_(this.f_105189_.f_91073_, (p_233739_) -> {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
--- a/net/minecraft/client/particle/FireworkParticles.java
|
||||
+++ b/net/minecraft/client/particle/FireworkParticles.java
|
||||
@@ -172,7 +_,7 @@
|
||||
} else {
|
||||
for(int i = 0; i < this.f_106752_.size(); ++i) {
|
||||
CompoundTag compoundtag = this.f_106752_.m_128728_(i);
|
||||
- if (FireworkRocketItem.Shape.m_41237_(compoundtag.m_128445_("Type")) == FireworkRocketItem.Shape.LARGE_BALL) {
|
||||
+ if (FireworkRocketItem.Shape.getShape(compoundtag) == FireworkRocketItem.Shape.LARGE_BALL) {
|
||||
flag1 = true;
|
||||
break;
|
||||
}
|
||||
@@ -192,7 +_,7 @@
|
||||
if (this.f_106754_ % 2 == 0 && this.f_106752_ != null && this.f_106754_ / 2 < this.f_106752_.size()) {
|
||||
int k = this.f_106754_ / 2;
|
||||
CompoundTag compoundtag1 = this.f_106752_.m_128728_(k);
|
||||
- FireworkRocketItem.Shape fireworkrocketitem$shape = FireworkRocketItem.Shape.m_41237_(compoundtag1.m_128445_("Type"));
|
||||
+ FireworkRocketItem.Shape fireworkrocketitem$shape = FireworkRocketItem.Shape.getShape(compoundtag1);
|
||||
boolean flag4 = compoundtag1.m_128471_("Trail");
|
||||
boolean flag2 = compoundtag1.m_128471_("Flicker");
|
||||
int[] aint = compoundtag1.m_128465_("Colors");
|
||||
@@ -201,6 +_,10 @@
|
||||
aint = new int[]{DyeColor.BLACK.m_41070_()};
|
||||
}
|
||||
|
||||
+ var factory = net.minecraftforge.client.FireworkShapeFactoryRegistry.get(fireworkrocketitem$shape);
|
||||
+ if (factory != null)
|
||||
+ factory.build(this, flag4, flag2, aint, aint1);
|
||||
+ else
|
||||
switch (fireworkrocketitem$shape) {
|
||||
case SMALL_BALL:
|
||||
default:
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/particle/Particle.java
|
||||
+++ b/net/minecraft/client/particle/Particle.java
|
||||
@@ -226,4 +_,12 @@
|
||||
@@ -226,4 +_,16 @@
|
||||
public Optional<ParticleGroup> m_142654_() {
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -11,5 +11,9 @@
|
||||
+ */
|
||||
+ public boolean shouldCull() {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ public net.minecraft.world.phys.Vec3 getPos() {
|
||||
+ return new net.minecraft.world.phys.Vec3(this.f_107212_, this.f_107213_, this.f_107214_);
|
||||
+ }
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/client/particle/TerrainParticle.java
|
||||
+++ b/net/minecraft/client/particle/TerrainParticle.java
|
||||
@@ -28,7 +_,7 @@
|
||||
this.f_107227_ = 0.6F;
|
||||
this.f_107228_ = 0.6F;
|
||||
this.f_107229_ = 0.6F;
|
||||
- if (!p_172458_.m_60713_(Blocks.f_50440_)) {
|
||||
+ if (net.minecraftforge.client.extensions.common.IClientBlockExtensions.of(p_172458_).areBreakingParticlesTinted(p_172458_, p_172451_, p_172459_)) {
|
||||
int i = Minecraft.m_91087_().m_91298_().m_92577_(p_172458_, p_172451_, p_172459_, 0);
|
||||
this.f_107227_ *= (float)(i >> 16 & 255) / 255.0F;
|
||||
this.f_107228_ *= (float)(i >> 8 & 255) / 255.0F;
|
||||
@@ -69,7 +_,13 @@
|
||||
public static class Provider implements ParticleProvider<BlockParticleOption> {
|
||||
public Particle m_6966_(BlockParticleOption p_108304_, ClientLevel p_108305_, double p_108306_, double p_108307_, double p_108308_, double p_108309_, double p_108310_, double p_108311_) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
}
|
||||
|
||||
- return new BakedQuad(aint, p_111603_.f_111355_, direction, p_111604_, p_111608_);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.fillNormal(aint, direction);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.fillNormal(aint, direction, p_111603_.getFaceData().calculateNormals());
|
||||
+ var data = p_111603_.getFaceData();
|
||||
+ var quad = new BakedQuad(aint, p_111603_.f_111355_, direction, p_111604_, p_111608_, data.ambientOcclusion());
|
||||
+ if (!net.minecraftforge.client.model.ForgeFaceData.DEFAULT.equals(data)) {
|
||||
|
||||
@@ -9,21 +9,13 @@
|
||||
this.f_120088_.setSoTimeout(5000);
|
||||
this.f_120088_.joinGroup(this.f_120087_);
|
||||
}
|
||||
@@ -87,7 +_,19 @@
|
||||
@@ -87,7 +_,11 @@
|
||||
String s = LanServerPinger.m_120111_(p_120097_);
|
||||
String s1 = LanServerPinger.m_120116_(p_120097_);
|
||||
if (s1 != null) {
|
||||
- s1 = p_120098_.getHostAddress() + ":" + s1;
|
||||
+ if (net.minecraftforge.network.DualStackUtils.checkIPv6(p_120098_)) {
|
||||
+ final String ip;
|
||||
+
|
||||
+ // compress to short form if enabled in config
|
||||
+ if (net.minecraftforge.common.ForgeConfig.CLIENT.compressLanIPv6Addresses.get())
|
||||
+ ip = com.google.common.net.InetAddresses.toAddrString(p_120098_);
|
||||
+ else
|
||||
+ ip = p_120098_.getHostAddress();
|
||||
+
|
||||
+ s1 = "[" + ip + "]:" + s1;
|
||||
+ s1 = "[" + com.google.common.net.InetAddresses.toAddrString(p_120098_) + "]:" + s1;
|
||||
+ } else {
|
||||
+ s1 = p_120098_.getHostAddress() + ":" + s1;
|
||||
+ }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/client/server/LanServerPinger.java
|
||||
+++ b/net/minecraft/client/server/LanServerPinger.java
|
||||
@@ -16,7 +_,7 @@
|
||||
@@ -13,7 +_,7 @@
|
||||
public class LanServerPinger extends Thread {
|
||||
private static final AtomicInteger f_120101_ = new AtomicInteger(0);
|
||||
private static final Logger f_120102_ = LogUtils.getLogger();
|
||||
@@ -9,7 +9,7 @@
|
||||
public static final int f_174975_ = 4445;
|
||||
private static final long f_174976_ = 1500L;
|
||||
private final String f_120103_;
|
||||
@@ -39,7 +_,7 @@
|
||||
@@ -36,7 +_,7 @@
|
||||
|
||||
while(!this.isInterrupted() && this.f_120105_) {
|
||||
try {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
public boolean m_207277_(HolderOwner<T> p_256542_) {
|
||||
return this.f_254711_.m_254921_(p_256542_);
|
||||
+ }
|
||||
+ // FORGE: Keep a list of invalidation callbacks so they can be run when tags rebind
|
||||
+ // 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);
|
||||
|
||||
@@ -66,9 +66,12 @@
|
||||
Predicate<ResourceLocation> predicate = (p_255496_) -> {
|
||||
return registrylookup.m_254902_(ResourceKey.m_135785_(this.f_254716_, p_255496_)).isPresent();
|
||||
};
|
||||
@@ -77,12 +_,13 @@
|
||||
@@ -75,14 +_,16 @@
|
||||
ResourceLocation resourcelocation = p_255499_.getKey();
|
||||
TagBuilder tagbuilder = p_255499_.getValue();
|
||||
List<TagEntry> list = tagbuilder.m_215904_();
|
||||
List<TagEntry> list1 = list.stream().filter((p_274771_) -> {
|
||||
- List<TagEntry> list1 = list.stream().filter((p_274771_) -> {
|
||||
+ List<TagEntry> list1 = java.util.stream.Stream.concat(list.stream(), tagbuilder.getRemoveEntries()).filter((p_274771_) -> {
|
||||
return !p_274771_.m_215940_(predicate, predicate1);
|
||||
- }).toList();
|
||||
+ }).filter(this::missing).toList(); // Forge: Add validation via existing resources
|
||||
@@ -77,13 +80,14 @@
|
||||
} else {
|
||||
- JsonElement jsonelement = TagFile.f_215958_.encodeStart(JsonOps.INSTANCE, new TagFile(list, false)).getOrThrow(false, f_126541_::error);
|
||||
- Path path = this.f_236439_.m_245731_(resourcelocation);
|
||||
+ JsonElement jsonelement = TagFile.f_215958_.encodeStart(JsonOps.INSTANCE, new TagFile(list, tagbuilder.isReplace())).getOrThrow(false, f_126541_::error);
|
||||
+ var removed = tagbuilder.getRemoveEntries().toList();
|
||||
+ JsonElement jsonelement = TagFile.f_215958_.encodeStart(JsonOps.INSTANCE, new TagFile(list, tagbuilder.isReplace(), removed)).getOrThrow(false, f_126541_::error);
|
||||
+ Path path = this.getPath(resourcelocation);
|
||||
+ if (path == null) return CompletableFuture.completedFuture(null); // Forge: Allow running this data provider without writing it. Recipe provider needs valid tags.
|
||||
return DataProvider.m_253162_(p_253684_, jsonelement, path);
|
||||
}
|
||||
}).toArray((p_253442_) -> {
|
||||
@@ -91,13 +_,23 @@
|
||||
@@ -91,13 +_,25 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,7 +108,9 @@
|
||||
|
||||
protected TagBuilder m_236451_(TagKey<T> p_236452_) {
|
||||
return this.f_126543_.computeIfAbsent(p_236452_.f_203868_(), (p_236442_) -> {
|
||||
+ existingFileHelper.trackGenerated(p_236442_, resourceType);
|
||||
+ if (existingFileHelper != null) {
|
||||
+ existingFileHelper.trackGenerated(p_236442_, resourceType);
|
||||
+ }
|
||||
return TagBuilder.m_215899_();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -68,6 +_,8 @@
|
||||
private MinecraftServerGui f_139605_;
|
||||
@Nullable
|
||||
private final TextFilterClient f_139606_;
|
||||
+ @Nullable
|
||||
+ private net.minecraft.client.server.LanServerPinger dediLanPinger;
|
||||
|
||||
public DedicatedServer(Thread p_214789_, LevelStorageSource.LevelStorageAccess p_214790_, PackRepository p_214791_, WorldStem p_214792_, DedicatedServerSettings p_214793_, DataFixer p_214794_, Services p_214795_, ChunkProgressListenerFactory p_214796_) {
|
||||
super(p_214789_, p_214790_, p_214791_, p_214792_, Proxy.NO_PROXY, p_214794_, p_214795_, p_214796_);
|
||||
@@ -79,6 +_,7 @@
|
||||
public boolean m_7038_() throws IOException {
|
||||
Thread thread = new Thread("Server console handler") {
|
||||
@@ -22,26 +31,41 @@
|
||||
if (dedicatedserverproperties.f_139744_ != null) {
|
||||
this.m_129900_().m_46170_(GameRules.f_46153_).m_46246_(dedicatedserverproperties.f_139744_, this);
|
||||
}
|
||||
@@ -183,12 +_,13 @@
|
||||
thread1.start();
|
||||
}
|
||||
|
||||
+ // <3 you Grum for this, saves us ~30 patch files! --^
|
||||
if (dedicatedserverproperties.f_139721_) {
|
||||
MinecraftServerStatistics.m_18328_(this);
|
||||
@@ -188,7 +_,12 @@
|
||||
f_139598_.info("JMX monitoring enabled");
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ if (net.minecraftforge.common.ForgeConfig.SERVER.advertiseDedicatedServerToLan.get()) {
|
||||
+ this.dediLanPinger = new net.minecraft.client.server.LanServerPinger(this.m_129916_(), String.valueOf(this.m_7448_()));
|
||||
+ this.dediLanPinger.start();
|
||||
+ }
|
||||
+
|
||||
+ return net.minecraftforge.server.ServerLifecycleHooks.handleServerStarting(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,6 +_,7 @@
|
||||
@@ -263,6 +_,10 @@
|
||||
this.f_139601_.m_7530_();
|
||||
}
|
||||
|
||||
+ if (this.dediLanPinger != null) {
|
||||
+ this.dediLanPinger.interrupt();
|
||||
+ this.dediLanPinger = null;
|
||||
+ }
|
||||
}
|
||||
|
||||
public void m_5703_(BooleanSupplier p_139661_) {
|
||||
@@ -492,7 +_,12 @@
|
||||
}
|
||||
|
||||
public void m_7041_() {
|
||||
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.GameShuttingDownEvent());
|
||||
super.m_7041_();
|
||||
+ if (this.dediLanPinger != null) {
|
||||
+ this.dediLanPinger.interrupt();
|
||||
+ this.dediLanPinger = null;
|
||||
+ }
|
||||
Util.m_137580_();
|
||||
SkullBlockEntity.m_196704_();
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
public void m_214168_(BlockPos p_215120_, ServerboundPlayerActionPacket.Action p_215121_, Direction p_215122_, int p_215123_, int p_215124_) {
|
||||
- if (this.f_9245_.m_146892_().m_82557_(Vec3.m_82512_(p_215120_)) > ServerGamePacketListenerImpl.f_215198_) {
|
||||
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock event = net.minecraftforge.common.ForgeHooks.onLeftClickBlock(f_9245_, p_215120_, p_215122_);
|
||||
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock event = net.minecraftforge.common.ForgeHooks.onLeftClickBlock(f_9245_, p_215120_, p_215122_, p_215121_);
|
||||
+ if (event.isCanceled() || (!this.m_9295_() && event.getResult() == net.minecraftforge.eventbus.api.Event.Result.DENY)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
+13
@@ -25,6 +25,19 @@
|
||||
this.f_9742_.m_129512_(new ClientboundMoveVehiclePacket(entity));
|
||||
return;
|
||||
}
|
||||
@@ -983,8 +_,10 @@
|
||||
case SWAP_ITEM_WITH_OFFHAND:
|
||||
if (!this.f_9743_.m_5833_()) {
|
||||
ItemStack itemstack = this.f_9743_.m_21120_(InteractionHand.OFF_HAND);
|
||||
- this.f_9743_.m_21008_(InteractionHand.OFF_HAND, this.f_9743_.m_21120_(InteractionHand.MAIN_HAND));
|
||||
- this.f_9743_.m_21008_(InteractionHand.MAIN_HAND, itemstack);
|
||||
+ var event = net.minecraftforge.common.ForgeHooks.onLivingSwapHandItems(this.f_9743_);
|
||||
+ if (event.isCanceled()) return;
|
||||
+ this.f_9743_.m_21008_(InteractionHand.OFF_HAND, event.getItemSwappedToOffHand());
|
||||
+ this.f_9743_.m_21008_(InteractionHand.MAIN_HAND, event.getItemSwappedToMainHand());
|
||||
this.f_9743_.m_5810_();
|
||||
}
|
||||
|
||||
@@ -1035,7 +_,7 @@
|
||||
Vec3 vec3 = blockhitresult.m_82450_();
|
||||
BlockPos blockpos = blockhitresult.m_82425_();
|
||||
|
||||
+10
@@ -15,6 +15,16 @@
|
||||
this.m_10055_();
|
||||
} else if (this.f_10019_ == ServerLoginPacketListenerImpl.State.DELAY_ACCEPT) {
|
||||
ServerPlayer serverplayer = this.f_10018_.m_6846_().m_11259_(this.f_10021_.getId());
|
||||
@@ -138,7 +_,8 @@
|
||||
}
|
||||
|
||||
public String m_10056_() {
|
||||
- return this.f_10021_ != null ? this.f_10021_ + " (" + this.f_10013_.m_129523_() + ")" : String.valueOf((Object)this.f_10013_.m_129523_());
|
||||
+ final String addressString = net.minecraftforge.network.DualStackUtils.getAddressString(this.f_10013_.m_129523_());
|
||||
+ return this.f_10021_ != null ? this.f_10021_ + " (" + addressString + ")" : addressString;
|
||||
}
|
||||
|
||||
public void m_5990_(ServerboundHelloPacket p_10047_) {
|
||||
@@ -147,14 +_,14 @@
|
||||
GameProfile gameprofile = this.f_10018_.m_236731_();
|
||||
if (gameprofile != null && p_10047_.f_238040_().equalsIgnoreCase(gameprofile.getName())) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
public PackRepository(RepositorySource... p_251886_) {
|
||||
- this.f_10497_ = ImmutableSet.copyOf(p_251886_);
|
||||
+ this.f_10497_ = new java.util.HashSet<>(List.of(p_251886_)); //Forge: This needs to be a mutable set, so that we can add to it later on.
|
||||
+ this.f_10497_ = new java.util.LinkedHashSet<>(List.of(p_251886_)); //Forge: This needs to be a mutable set, so that we can add to it later on.
|
||||
}
|
||||
|
||||
public void m_10506_() {
|
||||
|
||||
@@ -8,7 +8,15 @@
|
||||
|
||||
public PlayerList(MinecraftServer p_203842_, LayeredRegistryAccess<RegistryLayer> p_251844_, PlayerDataStorage p_203844_, int p_203845_) {
|
||||
this.f_11195_ = p_203842_;
|
||||
@@ -174,6 +_,7 @@
|
||||
@@ -167,13 +_,14 @@
|
||||
p_11263_.m_284127_(serverlevel1);
|
||||
String s1 = "local";
|
||||
if (p_11262_.m_129523_() != null) {
|
||||
- s1 = p_11262_.m_129523_().toString();
|
||||
+ s1 = net.minecraftforge.network.DualStackUtils.getAddressString(p_11262_.m_129523_());
|
||||
}
|
||||
|
||||
f_11188_.info("{}[{}] logged in with entity id {} at ({}, {}, {})", p_11263_.m_7755_().getString(), s1, p_11263_.m_19879_(), p_11263_.m_20185_(), p_11263_.m_20186_(), p_11263_.m_20189_());
|
||||
LevelData leveldata = serverlevel1.m_6106_();
|
||||
p_11263_.m_143427_(compoundtag);
|
||||
ServerGamePacketListenerImpl servergamepacketlistenerimpl = new ServerGamePacketListenerImpl(this.f_11195_, p_11262_, p_11263_);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
--- a/net/minecraft/tags/TagFile.java
|
||||
+++ b/net/minecraft/tags/TagFile.java
|
||||
@@ -4,8 +_,12 @@
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import java.util.List;
|
||||
|
||||
-public record TagFile(List<TagEntry> f_215959_, boolean f_215960_) {
|
||||
+public record TagFile(List<TagEntry> f_215959_, boolean f_215960_, List<TagEntry> remove) {
|
||||
public static final Codec<TagFile> f_215958_ = RecordCodecBuilder.create((p_215967_) -> {
|
||||
- return p_215967_.group(TagEntry.f_215911_.listOf().fieldOf("values").forGetter(TagFile::f_215959_), Codec.BOOL.optionalFieldOf("replace", Boolean.valueOf(false)).forGetter(TagFile::f_215960_)).apply(p_215967_, TagFile::new);
|
||||
+ return p_215967_.group(TagEntry.f_215911_.listOf().fieldOf("values").forGetter(TagFile::f_215959_), Codec.BOOL.optionalFieldOf("replace", Boolean.valueOf(false)).forGetter(TagFile::f_215960_), TagEntry.f_215911_.listOf().optionalFieldOf("remove", List.of()).forGetter(TagFile::remove)).apply(p_215967_, TagFile::new);
|
||||
});
|
||||
+
|
||||
+ public TagFile(List<TagEntry> f_215959_, boolean f_215960_) {
|
||||
+ this(f_215959_, f_215960_, List.of());
|
||||
+ }
|
||||
}
|
||||
@@ -1,5 +1,34 @@
|
||||
--- a/net/minecraft/tags/TagLoader.java
|
||||
+++ b/net/minecraft/tags/TagLoader.java
|
||||
@@ -59,6 +_,7 @@
|
||||
tagfile.f_215959_().forEach((p_215997_) -> {
|
||||
list.add(new TagLoader.EntryWithSource(p_215997_, s));
|
||||
});
|
||||
+ tagfile.remove().forEach(e -> list.add(new TagLoader.EntryWithSource(e, s, true)));
|
||||
} catch (Exception exception) {
|
||||
f_13445_.error("Couldn't read tag list {} from {} in data pack {}", resourcelocation1, resourcelocation, resource.m_215506_(), exception);
|
||||
}
|
||||
@@ -69,16 +_,17 @@
|
||||
}
|
||||
|
||||
private Either<Collection<TagLoader.EntryWithSource>, Collection<T>> m_215978_(TagEntry.Lookup<T> p_215979_, List<TagLoader.EntryWithSource> p_215980_) {
|
||||
- ImmutableSet.Builder<T> builder = ImmutableSet.builder();
|
||||
+ var builder = new java.util.HashSet<T>();
|
||||
List<TagLoader.EntryWithSource> list = new ArrayList<>();
|
||||
|
||||
for(TagLoader.EntryWithSource tagloader$entrywithsource : p_215980_) {
|
||||
- if (!tagloader$entrywithsource.f_216042_().m_215927_(p_215979_, builder::add)) {
|
||||
+ if (!tagloader$entrywithsource.f_216042_().m_215927_(p_215979_, tagloader$entrywithsource.remove() ? builder::remove : builder::add)) {
|
||||
+ if (!tagloader$entrywithsource.remove()) // Treat all removals as optional at runtime. If it was missing, then it could of never been added.
|
||||
list.add(tagloader$entrywithsource);
|
||||
}
|
||||
}
|
||||
|
||||
- return list.isEmpty() ? Either.right(builder.build()) : Either.left(list);
|
||||
+ return list.isEmpty() ? Either.right(List.copyOf(builder)) : Either.left(list);
|
||||
}
|
||||
|
||||
public Map<ResourceLocation, Collection<T>> m_203898_(Map<ResourceLocation, List<TagLoader.EntryWithSource>> p_203899_) {
|
||||
@@ -100,7 +_,7 @@
|
||||
});
|
||||
dependencysorter.m_284430_((p_284682_, p_284683_) -> {
|
||||
@@ -9,3 +38,13 @@
|
||||
}).ifRight((p_216001_) -> {
|
||||
map.put(p_284682_, p_216001_);
|
||||
});
|
||||
@@ -112,7 +_,8 @@
|
||||
return this.m_203898_(this.m_144495_(p_203901_));
|
||||
}
|
||||
|
||||
- public static record EntryWithSource(TagEntry f_216042_, String f_216043_) {
|
||||
+ public static record EntryWithSource(TagEntry f_216042_, String f_216043_, boolean remove) {
|
||||
+ public EntryWithSource(TagEntry f_216042_, String f_216043_) { this(f_216042_, f_216043_, false); }
|
||||
public String toString() {
|
||||
return this.f_216042_ + " (from " + this.f_216043_ + ")";
|
||||
}
|
||||
@@ -41,7 +41,7 @@
|
||||
this.m_8097_();
|
||||
this.m_6034_(0.0D, 0.0D, 0.0D);
|
||||
- this.f_19816_ = this.m_6380_(Pose.STANDING, this.f_19815_);
|
||||
+ net.minecraftforge.event.entity.EntityEvent.Size sizeEvent = net.minecraftforge.event.ForgeEventFactory.getEntitySizeForge(this, Pose.STANDING, this.f_19815_, this.m_6380_(Pose.STANDING, this.f_19815_));
|
||||
+ var sizeEvent = net.minecraftforge.event.ForgeEventFactory.getEntitySizeForge(this, Pose.STANDING, this.f_19815_, this.m_6380_(Pose.STANDING, this.f_19815_));
|
||||
+ this.f_19815_ = sizeEvent.getNewSize();
|
||||
+ this.f_19816_ = sizeEvent.getNewEyeHeight();
|
||||
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityEvent.EntityConstructing(this));
|
||||
@@ -147,7 +147,7 @@
|
||||
this.m_5496_(soundtype.m_56776_(), soundtype.m_56773_() * 0.15F, soundtype.m_56774_());
|
||||
}
|
||||
|
||||
@@ -1176,19 +_,22 @@
|
||||
@@ -1176,31 +_,38 @@
|
||||
|
||||
public void m_5844_() {
|
||||
if (this.m_6069_()) {
|
||||
@@ -175,6 +175,24 @@
|
||||
}
|
||||
|
||||
void m_20074_() {
|
||||
Entity entity = this.m_20202_();
|
||||
+ java.util.function.BooleanSupplier updateFluidHeight = () -> this.m_204031_(FluidTags.f_13131_, 0.014D);
|
||||
if (entity instanceof Boat boat) {
|
||||
if (!boat.m_5842_()) {
|
||||
this.f_19798_ = false;
|
||||
- return;
|
||||
+ updateFluidHeight = () -> {
|
||||
+ this.updateFluidHeightAndDoFluidPushing(state -> this.shouldUpdateFluidWhileBoating(state, boat));
|
||||
+ return false;
|
||||
+ };
|
||||
}
|
||||
}
|
||||
|
||||
- if (this.m_204031_(FluidTags.f_13131_, 0.014D)) {
|
||||
+ if (updateFluidHeight.getAsBoolean()) {
|
||||
if (!this.f_19798_ && !this.f_19803_) {
|
||||
this.m_5841_();
|
||||
}
|
||||
@@ -1217,6 +_,7 @@
|
||||
private void m_20323_() {
|
||||
this.f_19800_ = this.m_204029_(FluidTags.f_13131_);
|
||||
@@ -385,7 +403,7 @@
|
||||
EntityDimensions entitydimensions = this.f_19815_;
|
||||
Pose pose = this.m_20089_();
|
||||
EntityDimensions entitydimensions1 = this.m_6972_(pose);
|
||||
+ net.minecraftforge.event.entity.EntityEvent.Size sizeEvent = net.minecraftforge.event.ForgeEventFactory.getEntitySizeForge(this, pose, entitydimensions, entitydimensions1, this.m_6380_(pose, entitydimensions1));
|
||||
+ var sizeEvent = net.minecraftforge.event.ForgeEventFactory.getEntitySizeForge(this, pose, entitydimensions, entitydimensions1, this.m_6380_(pose, entitydimensions1));
|
||||
+ entitydimensions1 = sizeEvent.getNewSize();
|
||||
this.f_19815_ = entitydimensions1;
|
||||
- this.f_19816_ = this.m_6380_(pose, entitydimensions1);
|
||||
@@ -404,11 +422,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2980,9 +_,17 @@
|
||||
@@ -2980,9 +_,22 @@
|
||||
this.f_19859_ = this.m_146908_();
|
||||
}
|
||||
|
||||
+ @Deprecated // Forge: Use no parameter version instead, only for vanilla Tags
|
||||
+ @Deprecated // Forge: Use predicate version instead, only for vanilla Tags
|
||||
public boolean m_204031_(TagKey<Fluid> p_204032_, double p_204033_) {
|
||||
+ this.updateFluidHeightAndDoFluidPushing();
|
||||
+ if(p_204032_ == FluidTags.f_13131_) return this.isInFluidType(net.minecraftforge.common.ForgeMod.WATER_TYPE.get());
|
||||
@@ -416,7 +434,12 @@
|
||||
+ else return false;
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.1")
|
||||
+ public void updateFluidHeightAndDoFluidPushing() {
|
||||
+ this.updateFluidHeightAndDoFluidPushing(com.google.common.base.Predicates.alwaysTrue());
|
||||
+ }
|
||||
+
|
||||
+ public void updateFluidHeightAndDoFluidPushing(Predicate<FluidState> shouldUpdate) {
|
||||
if (this.m_146899_()) {
|
||||
- return false;
|
||||
+ return;
|
||||
@@ -436,7 +459,7 @@
|
||||
FluidState fluidstate = this.m_9236_().m_6425_(blockpos$mutableblockpos);
|
||||
- if (fluidstate.m_205070_(p_204032_)) {
|
||||
+ net.minecraftforge.fluids.FluidType fluidType = fluidstate.getFluidType();
|
||||
+ if (!fluidType.isAir()) {
|
||||
+ if (!fluidType.isAir() && shouldUpdate.test(fluidstate)) {
|
||||
double d1 = (double)((float)i2 + fluidstate.m_76155_(this.m_9236_(), blockpos$mutableblockpos));
|
||||
if (d1 >= aabb.f_82289_) {
|
||||
flag1 = true;
|
||||
@@ -525,7 +548,7 @@
|
||||
public float m_274421_() {
|
||||
return this.f_19793_;
|
||||
}
|
||||
@@ -3319,6 +_,103 @@
|
||||
@@ -3319,6 +_,109 @@
|
||||
public boolean m_142265_(Level p_146843_, BlockPos p_146844_) {
|
||||
return true;
|
||||
}
|
||||
@@ -593,6 +616,7 @@
|
||||
+ /**
|
||||
+ * Accessor method for {@link #getEyeHeight(Pose, EntityDimensions)}
|
||||
+ */
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.1") // Remove Entity Eye/Size hooks, as they need to be redesigned
|
||||
+ public float getEyeHeightAccess(Pose pose, EntityDimensions size) {
|
||||
+ return this.m_6380_(pose, size);
|
||||
+ }
|
||||
@@ -624,6 +648,11 @@
|
||||
+ return this.forgeFluidTypeHeight.object2DoubleEntrySet().stream().max(java.util.Comparator.comparingDouble(Object2DoubleMap.Entry::getDoubleValue)).map(Object2DoubleMap.Entry::getKey).orElseGet(net.minecraftforge.common.ForgeMod.EMPTY_TYPE);
|
||||
+ }
|
||||
+
|
||||
+ @Deprecated(forRemoval = true, since = "1.20.1") // Remove Entity Eye/Size hooks, as they need to be redesigned
|
||||
+ public EntityDimensions getDimensionsForge(Pose pose) {
|
||||
+ return m_6972_(pose);
|
||||
+ }
|
||||
+
|
||||
+ /* ================================== Forge End =====================================*/
|
||||
+
|
||||
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
public static final int f_147166_ = 2;
|
||||
public static final int f_147167_ = 4;
|
||||
public static final int f_147168_ = 98;
|
||||
@@ -239,7 +_,8 @@
|
||||
this.f_20885_ = this.m_146908_();
|
||||
this.m_274367_(0.6F);
|
||||
NbtOps nbtops = NbtOps.f_128958_;
|
||||
- this.f_20939_ = this.m_8075_(new Dynamic<>(nbtops, nbtops.createMap(ImmutableMap.of(nbtops.createString("memories"), nbtops.emptyMap()))));
|
||||
+ var dyn = new Dynamic<>(nbtops, nbtops.createMap(ImmutableMap.of(nbtops.createString("memories"), nbtops.emptyMap())));
|
||||
+ this.f_20939_ = net.minecraftforge.common.ForgeHooks.onLivingMakeBrain(this, this.m_8075_(dyn), dyn);
|
||||
}
|
||||
|
||||
public Brain<?> m_6274_() {
|
||||
@@ -273,7 +_,7 @@
|
||||
}
|
||||
|
||||
@@ -43,31 +53,16 @@
|
||||
public boolean m_6040_() {
|
||||
return this.m_6336_() == MobType.f_21641_;
|
||||
}
|
||||
@@ -352,8 +_,8 @@
|
||||
@@ -352,6 +_,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
- if (this.m_204029_(FluidTags.f_13131_) && !this.m_9236_().m_8055_(BlockPos.m_274561_(this.m_20185_(), this.m_20188_(), this.m_20189_())).m_60713_(Blocks.f_50628_)) {
|
||||
- boolean flag1 = !this.m_6040_() && !MobEffectUtil.m_19588_(this) && (!flag || !((Player)this).m_150110_().f_35934_);
|
||||
+ if (!this.getEyeInFluidType().isAir() && !this.m_9236_().m_8055_(BlockPos.m_274561_(this.m_20185_(), this.m_20188_(), this.m_20189_())).m_60713_(Blocks.f_50628_)) {
|
||||
+ boolean flag1 = this.canDrownInFluidType(this.getEyeInFluidType()) && !MobEffectUtil.m_19588_(this) && (!flag || !((Player)this).m_150110_().f_35934_);
|
||||
+ int airSupply = this.m_20146_();
|
||||
+ net.minecraftforge.common.ForgeHooks.onLivingBreathe(this, airSupply - m_7302_(airSupply), m_7305_(airSupply) - airSupply);
|
||||
+ if (false) // Forge: Handled in ForgeHooks#onLivingBreathe(LivingEntity, int, int)
|
||||
if (this.m_204029_(FluidTags.f_13131_) && !this.m_9236_().m_8055_(BlockPos.m_274561_(this.m_20185_(), this.m_20188_(), this.m_20189_())).m_60713_(Blocks.f_50628_)) {
|
||||
boolean flag1 = !this.m_6040_() && !MobEffectUtil.m_19588_(this) && (!flag || !((Player)this).m_150110_().f_35934_);
|
||||
if (flag1) {
|
||||
this.m_20301_(this.m_7302_(this.m_20146_()));
|
||||
if (this.m_20146_() == -20) {
|
||||
@@ -371,10 +_,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- if (!this.m_9236_().f_46443_ && this.m_20159_() && this.m_20202_() != null && this.m_20202_().m_275843_()) {
|
||||
+ if (!this.m_9236_().f_46443_ && this.m_20159_() && this.m_20202_() != null && !this.m_20202_().canBeRiddenUnderFluidType(this.getEyeInFluidType(), this)) {
|
||||
this.m_8127_();
|
||||
}
|
||||
- } else if (this.m_20146_() < this.m_6062_()) {
|
||||
+ } // Forge: Move to if statement since we need to increase the air supply if in bubble column or can't drown
|
||||
+ if (this.m_20146_() < this.m_6062_() && (!this.canDrownInFluidType(this.getEyeInFluidType()) || this.m_9236_().m_8055_(BlockPos.m_274561_(this.m_20185_(), this.m_20188_(), this.m_20189_())).m_60713_(Blocks.f_50628_))) {
|
||||
this.m_20301_(this.m_7305_(this.m_20146_()));
|
||||
}
|
||||
|
||||
@@ -387,7 +_,7 @@
|
||||
}
|
||||
}
|
||||
@@ -77,6 +72,16 @@
|
||||
this.m_252836_();
|
||||
}
|
||||
|
||||
@@ -734,7 +_,8 @@
|
||||
}
|
||||
|
||||
if (p_21096_.m_128425_("Brain", 10)) {
|
||||
- this.f_20939_ = this.m_8075_(new Dynamic<>(NbtOps.f_128958_, p_21096_.m_128423_("Brain")));
|
||||
+ var dyn = new Dynamic<>(NbtOps.f_128958_, p_21096_.m_128423_("Brain"));
|
||||
+ this.f_20939_ = net.minecraftforge.common.ForgeHooks.onLivingMakeBrain(this, this.m_8075_(dyn), dyn);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -749,7 +_,7 @@
|
||||
if (!mobeffectinstance.m_19552_(this, () -> {
|
||||
this.m_141973_(mobeffectinstance, true, (Entity)null);
|
||||
@@ -386,6 +391,19 @@
|
||||
if (!this.f_20911_ || this.f_20913_ >= this.m_21304_() / 2 || this.f_20913_ < 0) {
|
||||
this.f_20913_ = -1;
|
||||
this.f_20911_ = true;
|
||||
@@ -1761,8 +_,10 @@
|
||||
|
||||
private void m_21312_() {
|
||||
ItemStack itemstack = this.m_6844_(EquipmentSlot.OFFHAND);
|
||||
- this.m_8061_(EquipmentSlot.OFFHAND, this.m_6844_(EquipmentSlot.MAINHAND));
|
||||
- this.m_8061_(EquipmentSlot.MAINHAND, itemstack);
|
||||
+ var event = net.minecraftforge.common.ForgeHooks.onLivingSwapHandItems(this);
|
||||
+ if (event.isCanceled()) return;
|
||||
+ this.m_8061_(EquipmentSlot.OFFHAND, event.getItemSwappedToOffHand());
|
||||
+ this.m_8061_(EquipmentSlot.MAINHAND, event.getItemSwappedToMainHand());
|
||||
}
|
||||
|
||||
protected void m_6088_() {
|
||||
@@ -1955,14 +_,17 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
--- a/net/minecraft/world/entity/ai/Brain.java
|
||||
+++ b/net/minecraft/world/entity/ai/Brain.java
|
||||
@@ -478,6 +_,30 @@
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
+ public net.minecraftforge.common.util.BrainBuilder<E> createBuilder(){
|
||||
+ var builder = new net.minecraftforge.common.util.BrainBuilder<>(this);
|
||||
+ builder.getMemoryTypes().addAll(this.f_21843_.keySet());
|
||||
+ builder.getSensorTypes().addAll(this.f_21844_.keySet());
|
||||
+ builder.addAvailableBehaviorsByPriorityFrom(this.f_21845_);
|
||||
+ builder.setSchedule(this.m_21932_());
|
||||
+ builder.addActivityRequirementsFrom(this.f_21847_);
|
||||
+ builder.addActivityMemoriesToEraseWhenStoppedFrom(this.f_21848_);
|
||||
+ builder.getCoreActivities().addAll(this.f_21849_);
|
||||
+ builder.setDefaultActivity(this.f_21851_);
|
||||
+ builder.setActiveActivites(this.f_21850_);
|
||||
+ return builder;
|
||||
+ }
|
||||
+
|
||||
+ public void copyFromBuilder(net.minecraftforge.common.util.BrainBuilder<E> builder){
|
||||
+ builder.addAvailableBehaviorsByPriorityTo(this.f_21845_);
|
||||
+ this.m_21912_(builder.getSchedule());
|
||||
+ builder.addActivityRequirementsTo(this.f_21847_);
|
||||
+ builder.addActivityMemoriesToEraseWhenStoppedTo(this.f_21848_);
|
||||
+ this.m_21930_(builder.getCoreActivities());
|
||||
+ this.m_21944_(builder.getDefaultActivity());
|
||||
+ this.f_21850_.addAll(builder.getActiveActivites());
|
||||
+ }
|
||||
+
|
||||
static final class MemoryValue<U> {
|
||||
private final MemoryModuleType<U> f_22030_;
|
||||
private final Optional<? extends ExpirableValue<U>> f_22031_;
|
||||
@@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
+++ b/net/minecraft/world/entity/projectile/AbstractArrow.java
|
||||
@@ -66,6 +_,8 @@
|
||||
@Nullable
|
||||
private List<Entity> f_36702_;
|
||||
|
||||
+ private final IntOpenHashSet ignoredEntities = new IntOpenHashSet();
|
||||
+
|
||||
protected AbstractArrow(EntityType<? extends AbstractArrow> p_36721_, Level p_36722_) {
|
||||
super(p_36721_, p_36722_);
|
||||
}
|
||||
@@ -150,7 +_,7 @@
|
||||
--this.f_36706_;
|
||||
}
|
||||
@@ -9,14 +18,54 @@
|
||||
this.m_20095_();
|
||||
}
|
||||
|
||||
@@ -186,7 +_,9 @@
|
||||
@@ -186,9 +_,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
- if (hitresult != null && !flag) {
|
||||
- this.m_6532_(hitresult);
|
||||
- this.f_19812_ = true;
|
||||
+ if (hitresult != null && hitresult.m_6662_() != HitResult.Type.MISS && !flag) {
|
||||
+ if (net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, hitresult))
|
||||
+ break;
|
||||
this.m_6532_(hitresult);
|
||||
this.f_19812_ = true;
|
||||
+ switch (net.minecraftforge.event.ForgeEventFactory.onProjectileImpactResult(this, hitresult)) {
|
||||
+ case SKIP_ENTITY:
|
||||
+ if (hitresult.m_6662_() != HitResult.Type.ENTITY) { // If there is no entity, we just return default behaviour
|
||||
+ this.m_6532_(hitresult);
|
||||
+ this.f_19812_ = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ ignoredEntities.add(entityhitresult.m_82443_().m_19879_());
|
||||
+ entityhitresult = null; // Don't process any further
|
||||
+ break;
|
||||
+ case STOP_AT_CURRENT_NO_DAMAGE:
|
||||
+ this.m_146870_();
|
||||
+ entityhitresult = null; // Don't process any further
|
||||
+ break;
|
||||
+ case STOP_AT_CURRENT:
|
||||
+ this.m_36767_((byte) 0);
|
||||
+ case DEFAULT:
|
||||
+ this.m_6532_(hitresult);
|
||||
+ this.f_19812_ = true;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (entityhitresult == null || this.m_36796_() <= 0) {
|
||||
@@ -198,6 +_,9 @@
|
||||
hitresult = null;
|
||||
}
|
||||
|
||||
+ if (this.m_213877_())
|
||||
+ return;
|
||||
+
|
||||
vec3 = this.m_20184_();
|
||||
double d5 = vec3.f_82479_;
|
||||
double d6 = vec3.f_82480_;
|
||||
@@ -422,7 +_,7 @@
|
||||
}
|
||||
|
||||
protected boolean m_5603_(Entity p_36743_) {
|
||||
- return super.m_5603_(p_36743_) && (this.f_36701_ == null || !this.f_36701_.contains(p_36743_.m_19879_()));
|
||||
+ return super.m_5603_(p_36743_) && (this.f_36701_ == null || !this.f_36701_.contains(p_36743_.m_19879_())) && !this.ignoredEntities.contains(p_36743_.m_19879_());
|
||||
}
|
||||
|
||||
public void m_7380_(CompoundTag p_36772_) {
|
||||
@@ -60,7 +60,7 @@
|
||||
return new IllegalStateException("Unregistered creative tab: " + this);
|
||||
});
|
||||
- this.f_256824_.m_257865_(p_270156_, creativemodetab$itemdisplaybuilder);
|
||||
+ net.minecraftforge.client.ForgeHooksClient.onCreativeModeTabBuildContents(this, resourcekey, this.f_256824_, p_270156_, creativemodetab$itemdisplaybuilder);
|
||||
+ net.minecraftforge.common.ForgeHooks.onCreativeModeTabBuildContents(this, resourcekey, this.f_256824_, p_270156_, creativemodetab$itemdisplaybuilder);
|
||||
this.f_243839_ = creativemodetab$itemdisplaybuilder.f_244363_;
|
||||
this.f_243841_ = creativemodetab$itemdisplaybuilder.f_244585_;
|
||||
this.m_257466_();
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
--- a/net/minecraft/world/item/FireworkRocketItem.java
|
||||
+++ b/net/minecraft/world/item/FireworkRocketItem.java
|
||||
@@ -107,7 +_,7 @@
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
- public static enum Shape {
|
||||
+ public static enum Shape implements net.minecraftforge.common.IExtensibleEnum {
|
||||
SMALL_BALL(0, "small_ball"),
|
||||
LARGE_BALL(1, "large_ball"),
|
||||
STAR(2, "star"),
|
||||
@@ -131,8 +_,28 @@
|
||||
return this.f_41228_;
|
||||
}
|
||||
|
||||
+ public void save(net.minecraft.nbt.CompoundTag tag) {
|
||||
+ tag.m_128344_("Type", (byte)m_41236_());
|
||||
+ tag.m_128359_("forge:shape_type", name());
|
||||
+ }
|
||||
+
|
||||
+ /** Use {getShape(ComoundTag)} */
|
||||
+ @Deprecated
|
||||
public static FireworkRocketItem.Shape m_41237_(int p_41238_) {
|
||||
return f_41226_.apply(p_41238_);
|
||||
+ }
|
||||
+
|
||||
+ public static FireworkRocketItem.Shape getShape(net.minecraft.nbt.CompoundTag tag) {
|
||||
+ var name = tag.m_128425_("forge:shape_type", 8) ? tag.m_128461_("forge:shape_type") : null;
|
||||
+ if (name == null) return m_41237_(tag.m_128445_("Type"));
|
||||
+ for (var ret : values())
|
||||
+ if (ret.name().equals(name))
|
||||
+ return ret;
|
||||
+ return SMALL_BALL;
|
||||
+ }
|
||||
+
|
||||
+ public static Shape create(String registryName, int id, String shapeName) {
|
||||
+ throw new IllegalStateException("Enum not extended");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/item/FireworkStarItem.java
|
||||
+++ b/net/minecraft/world/item/FireworkStarItem.java
|
||||
@@ -23,7 +_,7 @@
|
||||
}
|
||||
|
||||
public static void m_41256_(CompoundTag p_41257_, List<Component> p_41258_) {
|
||||
- FireworkRocketItem.Shape fireworkrocketitem$shape = FireworkRocketItem.Shape.m_41237_(p_41257_.m_128445_("Type"));
|
||||
+ FireworkRocketItem.Shape fireworkrocketitem$shape = FireworkRocketItem.Shape.getShape(p_41257_);
|
||||
p_41258_.add(Component.m_237115_("item.minecraft.firework_star.shape." + fireworkrocketitem$shape.m_41241_()).m_130940_(ChatFormatting.GRAY));
|
||||
int[] aint = p_41257_.m_128465_("Colors");
|
||||
if (aint.length > 0) {
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/item/crafting/FireworkStarRecipe.java
|
||||
+++ b/net/minecraft/world/item/crafting/FireworkStarRecipe.java
|
||||
@@ -107,7 +_,7 @@
|
||||
}
|
||||
|
||||
compoundtag.m_128408_("Colors", list);
|
||||
- compoundtag.m_128344_("Type", (byte)fireworkrocketitem$shape.m_41236_());
|
||||
+ fireworkrocketitem$shape.save(compoundtag);
|
||||
return itemstack;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
@@ -42,19 +_,22 @@
|
||||
for(ServerPlayer serverplayer : p_64576_.m_6907_()) {
|
||||
if (!serverplayer.m_5833_()) {
|
||||
BlockPos blockpos = serverplayer.m_20183_();
|
||||
- if (!p_64576_.m_6042_().f_223549_() || blockpos.m_123342_() >= p_64576_.m_5736_() && p_64576_.m_45527_(blockpos)) {
|
||||
- DifficultyInstance difficultyinstance = p_64576_.m_6436_(blockpos);
|
||||
+ DifficultyInstance difficultyinstance = p_64576_.m_6436_(blockpos);
|
||||
+ var event = new net.minecraftforge.event.entity.player.PlayerSpawnPhantomsEvent(serverplayer, 1 + randomsource.m_188503_(difficultyinstance.m_19048_().m_19028_() + 1));
|
||||
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(event);
|
||||
+ if (event.getResult() == net.minecraftforge.eventbus.api.Event.Result.DENY) continue;
|
||||
+ if (event.getResult() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || !p_64576_.m_6042_().f_223549_() || blockpos.m_123342_() >= p_64576_.m_5736_() && p_64576_.m_45527_(blockpos)) {
|
||||
if (difficultyinstance.m_19049_(randomsource.m_188501_() * 3.0F)) {
|
||||
ServerStatsCounter serverstatscounter = serverplayer.m_8951_();
|
||||
int j = Mth.m_14045_(serverstatscounter.m_13015_(Stats.f_12988_.m_12902_(Stats.f_12992_)), 1, Integer.MAX_VALUE);
|
||||
int k = 24000;
|
||||
- if (randomsource.m_188503_(j) >= 72000) {
|
||||
+ if (event.getResult() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || randomsource.m_188503_(j) >= 72000) {
|
||||
BlockPos blockpos1 = blockpos.m_6630_(20 + randomsource.m_188503_(15)).m_122030_(-10 + randomsource.m_188503_(21)).m_122020_(-10 + randomsource.m_188503_(21));
|
||||
BlockState blockstate = p_64576_.m_8055_(blockpos1);
|
||||
FluidState fluidstate = p_64576_.m_6425_(blockpos1);
|
||||
if (NaturalSpawner.m_47056_(p_64576_, blockpos1, blockstate, fluidstate, EntityType.f_20509_)) {
|
||||
SpawnGroupData spawngroupdata = null;
|
||||
- int l = 1 + randomsource.m_188503_(difficultyinstance.m_19048_().m_19028_() + 1);
|
||||
+ int l = event.getPhantomsToSpawn();
|
||||
|
||||
for(int i1 = 0; i1 < l; ++i1) {
|
||||
Phantom phantom = EntityType.f_20509_.m_20615_(p_64576_);
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/world/level/levelgen/feature/treedecorators/AlterGroundDecorator.java
|
||||
+++ b/net/minecraft/world/level/levelgen/feature/treedecorators/AlterGroundDecorator.java
|
||||
@@ -72,7 +_,7 @@
|
||||
for(int i = 2; i >= -3; --i) {
|
||||
BlockPos blockpos = p_225975_.m_6630_(i);
|
||||
if (Feature.m_65788_(p_225974_.m_226058_(), blockpos)) {
|
||||
- p_225974_.m_226061_(blockpos, this.f_69303_.m_213972_(p_225974_.m_226067_(), p_225975_));
|
||||
+ p_225974_.m_226061_(blockpos, net.minecraftforge.event.ForgeEventFactory.alterGround(p_225974_.m_226058_(), p_225974_.m_226067_(), blockpos, this.f_69303_.m_213972_(p_225974_.m_226067_(), p_225975_)));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"tag": "forge:rods/wooden"
|
||||
},
|
||||
"X": {
|
||||
"item": "minecraft:string"
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"key": {
|
||||
"H": {
|
||||
"item": "minecraft:honeycomb"
|
||||
},
|
||||
"S": {
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
"S",
|
||||
"H"
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:candle"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
"tag": "forge:ingots/iron"
|
||||
},
|
||||
"~": {
|
||||
"item": "minecraft:string"
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"tag": "forge:rods/wooden"
|
||||
},
|
||||
"X": {
|
||||
"item": "minecraft:string"
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "equipment",
|
||||
"key": {
|
||||
"O": {
|
||||
"item": "minecraft:slime_ball"
|
||||
},
|
||||
"~": {
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
"~~ ",
|
||||
"~O ",
|
||||
" ~"
|
||||
],
|
||||
"result": {
|
||||
"count": 2,
|
||||
"item": "minecraft:lead"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"key": {
|
||||
"#": {
|
||||
"tag": "minecraft:planks"
|
||||
},
|
||||
"@": {
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
"@@",
|
||||
"##"
|
||||
],
|
||||
"result": {
|
||||
"item": "minecraft:loom"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"key": {
|
||||
"I": {
|
||||
"item": "minecraft:bamboo"
|
||||
},
|
||||
"~": {
|
||||
"tag": "forge:string"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
"I~I",
|
||||
"I I",
|
||||
"I I"
|
||||
],
|
||||
"result": {
|
||||
"count": 6,
|
||||
"item": "minecraft:scaffolding"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"textures": [
|
||||
"minecraft:generic_7",
|
||||
"minecraft:generic_6",
|
||||
"minecraft:generic_5",
|
||||
"minecraft:generic_4",
|
||||
"minecraft:generic_3",
|
||||
"minecraft:generic_2",
|
||||
"minecraft:generic_1",
|
||||
"minecraft:generic_0"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"textures": [
|
||||
"minecraft:drip_hang"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"textures": [
|
||||
"minecraft:sga_a",
|
||||
"minecraft:sga_b",
|
||||
"minecraft:sga_c",
|
||||
"minecraft:sga_d",
|
||||
"minecraft:sga_e",
|
||||
"minecraft:sga_f",
|
||||
"minecraft:sga_g",
|
||||
"minecraft:sga_h",
|
||||
"minecraft:sga_i",
|
||||
"minecraft:sga_j",
|
||||
"minecraft:sga_k",
|
||||
"minecraft:sga_l",
|
||||
"minecraft:sga_m",
|
||||
"minecraft:sga_n",
|
||||
"minecraft:sga_o",
|
||||
"minecraft:sga_p",
|
||||
"minecraft:sga_q",
|
||||
"minecraft:sga_r",
|
||||
"minecraft:sga_s",
|
||||
"minecraft:sga_t",
|
||||
"minecraft:sga_u",
|
||||
"minecraft:sga_v",
|
||||
"minecraft:sga_w",
|
||||
"minecraft:sga_x",
|
||||
"minecraft:sga_y",
|
||||
"minecraft:sga_z"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"textures": [
|
||||
"minecraft:splash_0",
|
||||
"minecraft:splash_1",
|
||||
"minecraft:splash_2",
|
||||
"minecraft:splash_3"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,14 @@
|
||||
{
|
||||
"remove": [
|
||||
"minecraft:dirt",
|
||||
"minecraft:oak_door",
|
||||
"minecraft:dark_oak_door",
|
||||
"minecraft:anvil",
|
||||
"minecraft:basalt",
|
||||
"minecraft:polished_andesite",
|
||||
"#minecraft:beehives",
|
||||
"#minecraft:banners",
|
||||
"#minecraft:beds"
|
||||
],
|
||||
"values": []
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"remove": [
|
||||
"minecraft:music_disc_cat"
|
||||
],
|
||||
"values": []
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"remove": [
|
||||
"minecraft:spruce_planks"
|
||||
],
|
||||
"values": []
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.client.particle.FireworkParticles;
|
||||
import net.minecraft.world.item.FireworkRocketItem;
|
||||
|
||||
/**
|
||||
* Keeps track of custom firework shape types, because Particle is client side only this can't be on the Shape itself.
|
||||
* So sometime during your client initalization call register.
|
||||
*/
|
||||
public class FireworkShapeFactoryRegistry {
|
||||
private static final Map<FireworkRocketItem.Shape, Factory> factories = new HashMap<>();
|
||||
|
||||
public static interface Factory {
|
||||
void build(FireworkParticles.Starter starter, boolean trail, boolean flicker, int[] colors, int[] fadecolors);
|
||||
}
|
||||
|
||||
public static void register(FireworkRocketItem.Shape shape, Factory factory) {
|
||||
factories.put(shape, factory);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Factory get(FireworkRocketItem.Shape shape) {
|
||||
return factories.get(shape);
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,10 @@ import com.mojang.blaze3d.shaders.FogShape;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.math.Constants;
|
||||
import net.minecraft.FileUtil;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
@@ -146,6 +148,8 @@ import net.minecraftforge.client.gui.overlay.GuiOverlayManager;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import net.minecraftforge.client.textures.ForgeTextureMetadata;
|
||||
import net.minecraftforge.client.textures.TextureAtlasSpriteLoaderManager;
|
||||
import net.minecraftforge.common.ForgeConfig;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.ForgeI18n;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
@@ -496,21 +500,30 @@ public class ForgeHooksClient
|
||||
return new Material(TextureAtlas.LOCATION_BLOCKS, loc);
|
||||
}
|
||||
|
||||
public static void fillNormal(int[] faceData, Direction facing)
|
||||
{
|
||||
fillNormal(faceData, facing, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* internal, relies on fixed format of FaceBakery
|
||||
*/
|
||||
// TODO Do we need this?
|
||||
public static void fillNormal(int[] faceData, Direction facing)
|
||||
public static void fillNormal(int[] faceData, Direction facing, boolean calculateNormals)
|
||||
{
|
||||
Vector3f v1 = getVertexPos(faceData, 3);
|
||||
Vector3f t1 = getVertexPos(faceData, 1);
|
||||
Vector3f v2 = getVertexPos(faceData, 2);
|
||||
Vector3f t2 = getVertexPos(faceData, 0);
|
||||
v1.sub(t1);
|
||||
v2.sub(t2);
|
||||
v2.cross(v1);
|
||||
v2.normalize();
|
||||
|
||||
Vector3f v2;
|
||||
if (calculateNormals || ForgeConfig.CLIENT.calculateAllNormals.get()) {
|
||||
Vector3f v1 = getVertexPos(faceData, 3);
|
||||
Vector3f t1 = getVertexPos(faceData, 1);
|
||||
v2 = getVertexPos(faceData, 2);
|
||||
Vector3f t2 = getVertexPos(faceData, 0);
|
||||
v1.sub(t1);
|
||||
v2.sub(t2);
|
||||
v2.cross(v1);
|
||||
v2.normalize();
|
||||
} else {
|
||||
v2 = new Vector3f(facing.getNormal().getX(), facing.getNormal().getY(), facing.getNormal().getZ());
|
||||
}
|
||||
int x = ((byte) Math.round(v2.x() * 127)) & 0xFF;
|
||||
int y = ((byte) Math.round(v2.y() * 127)) & 0xFF;
|
||||
int z = ((byte) Math.round(v2.z() * 127)) & 0xFF;
|
||||
@@ -1192,27 +1205,46 @@ public class ForgeHooksClient
|
||||
return new ResourceLocation(loc.getNamespace(), normalised);
|
||||
}
|
||||
|
||||
// Use ForgeHooks.onCreativeModeTabBuildContents()
|
||||
// since calling this will crash if called on server
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
public static void onCreativeModeTabBuildContents(CreativeModeTab tab, ResourceKey<CreativeModeTab> tabKey, CreativeModeTab.DisplayItemsGenerator originalGenerator, CreativeModeTab.ItemDisplayParameters params, CreativeModeTab.Output output)
|
||||
{
|
||||
final var entries = new MutableHashedLinkedMap<ItemStack, CreativeModeTab.TabVisibility>(ItemStackLinkedSet.TYPE_AND_TAG,
|
||||
(key, left, right) -> {
|
||||
//throw new IllegalStateException("Accidentally adding the same item stack twice " + key.getDisplayName().getString() + " to a Creative Mode Tab: " + tab.getDisplayName().getString());
|
||||
// Vanilla adds enchanting books twice in both visibilities.
|
||||
// This is just code cleanliness for them. For us lets just increase the visibility and merge the entries.
|
||||
return CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS;
|
||||
}
|
||||
);
|
||||
// Bounce to ForgeHooks.onCreativeModeBuildContents(...)
|
||||
ForgeHooks.onCreativeModeTabBuildContents(tab, tabKey, originalGenerator, params, output);
|
||||
}
|
||||
|
||||
originalGenerator.accept(params, (stack, vis) -> {
|
||||
if (stack.getCount() != 1)
|
||||
throw new IllegalArgumentException("The stack count must be 1");
|
||||
entries.put(stack, vis);
|
||||
});
|
||||
|
||||
ModLoader.get().postEvent(new BuildCreativeModeTabContentsEvent(tab, tabKey, params, entries));
|
||||
|
||||
for (var entry : entries)
|
||||
output.accept(entry.getKey(), entry.getValue());
|
||||
/**
|
||||
* This function is a clone of {@link Direction#getNearest(float, float, float)} designed to return a consistent
|
||||
* direction when the normal is at an inflection point (ie 45 degrees) rounding errors
|
||||
* from associated matrix multiplication (such as during {@link SheetedDecalTextureGenerator#endVertex()}
|
||||
* can cause the direction chosen to be unstable.
|
||||
*
|
||||
* The function will only take effect if the Forge Client config option "stabilizeDirectionGetNearest" is enabled.
|
||||
*
|
||||
* This is a port of the downstream changes from https://github.com/neoforged/NeoForge PR #26
|
||||
*
|
||||
* @param nX X component of the normal
|
||||
* @param nY Y component of the normal
|
||||
* @param nZ Z component of the normal
|
||||
* @return the nearest Direction to the passed in normal, biased slightly in favor of the order of declaration
|
||||
*/
|
||||
public static Direction getNearestStable(float nX, float nY, float nZ)
|
||||
{
|
||||
if (ForgeConfig.CLIENT.stabilizeDirectionGetNearest.get()) {
|
||||
Direction ret = Direction.NORTH;
|
||||
float sum = Float.MIN_VALUE;
|
||||
for(Direction dir : Direction.values()) {
|
||||
float newSum = nX * (float)dir.getNormal().getX() + nY * (float)dir.getNormal().getY() + nZ * (float)dir.getNormal().getZ();
|
||||
if (newSum > sum + Constants.EPSILON) {
|
||||
sum = newSum;
|
||||
ret = dir;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
return Direction.getNearest(nX, nY, nZ);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the below method is only ever called once (by forge).
|
||||
|
||||
@@ -22,8 +22,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static net.minecraft.client.RecipeBookCategories.*;
|
||||
|
||||
/**
|
||||
* Manager for {@link RecipeBookType recipe book types} and {@link RecipeBookCategories categories}.
|
||||
* <p>
|
||||
@@ -63,7 +61,13 @@ public final class RecipeBookManager
|
||||
public static void init()
|
||||
{
|
||||
// The ImmutableMap is the patched out value of AGGREGATE_CATEGORIES
|
||||
var aggregateCategories = new HashMap<>(ImmutableMap.of(CRAFTING_SEARCH, ImmutableList.of(CRAFTING_EQUIPMENT, CRAFTING_BUILDING_BLOCKS, CRAFTING_MISC, CRAFTING_REDSTONE), FURNACE_SEARCH, ImmutableList.of(FURNACE_FOOD, FURNACE_BLOCKS, FURNACE_MISC), BLAST_FURNACE_SEARCH, ImmutableList.of(BLAST_FURNACE_BLOCKS, BLAST_FURNACE_MISC), SMOKER_SEARCH, ImmutableList.of(SMOKER_FOOD)));
|
||||
var aggregateCategories = new HashMap<>(ImmutableMap.of(
|
||||
RecipeBookCategories.CRAFTING_SEARCH, ImmutableList.of(RecipeBookCategories.CRAFTING_EQUIPMENT, RecipeBookCategories.CRAFTING_BUILDING_BLOCKS, RecipeBookCategories.CRAFTING_MISC, RecipeBookCategories.CRAFTING_REDSTONE),
|
||||
RecipeBookCategories.FURNACE_SEARCH, ImmutableList.of(RecipeBookCategories.FURNACE_FOOD, RecipeBookCategories.FURNACE_BLOCKS, RecipeBookCategories.FURNACE_MISC),
|
||||
RecipeBookCategories.BLAST_FURNACE_SEARCH, ImmutableList.of(RecipeBookCategories.BLAST_FURNACE_BLOCKS, RecipeBookCategories.BLAST_FURNACE_MISC),
|
||||
RecipeBookCategories.SMOKER_SEARCH, ImmutableList.of(RecipeBookCategories.SMOKER_FOOD)
|
||||
));
|
||||
|
||||
var typeCategories = new HashMap<RecipeBookType, ImmutableList<RecipeBookCategories>>();
|
||||
var recipeCategoryLookups = new HashMap<RecipeType<?>, Function<Recipe<?>, RecipeBookCategories>>();
|
||||
var event = new RegisterRecipeBookCategoriesEvent(aggregateCategories, typeCategories, recipeCategoryLookups);
|
||||
|
||||
+9
-9
@@ -67,15 +67,15 @@ public interface IForgeDimensionSpecialEffects
|
||||
* Allows for manipulating the coloring of the lightmap texture.
|
||||
* Will be called for each 16*16 combination of sky/block light values.
|
||||
*
|
||||
* @param level The current level (client-side).
|
||||
* @param partialTicks Progress between ticks.
|
||||
* @param skyDarken Current darkness of the sky.
|
||||
* @param skyLight Sky light brightness factor.
|
||||
* @param blockLight Block light brightness factor.
|
||||
* @param pixelX X-coordinate of the lightmap texture.
|
||||
* @param pixelY Y-coordinate of the lightmap texture.
|
||||
* @param colors The color values that will be used: [r, g, b].
|
||||
* @param level The current level (client-side).
|
||||
* @param partialTicks Progress between ticks.
|
||||
* @param skyDarken Current darkness of the sky (can be used to calculate sky light).
|
||||
* @param blockLightRedFlicker Block light flicker factor (red color) (can be used to calculate block light).
|
||||
* @param skyLight Sky light brightness (accounting for sky darkness).
|
||||
* @param pixelX X-coordinate of the lightmap texture (block).
|
||||
* @param pixelY Y-coordinate of the lightmap texture (sky).
|
||||
* @param colors The color values that will be used: [r, g, b].
|
||||
* @see LightTexture#updateLightTexture(float)
|
||||
*/
|
||||
default void adjustLightmapColors(ClientLevel level, float partialTicks, float skyDarken, float skyLight, float blockLight, int pixelX, int pixelY, Vector3f colors) {}
|
||||
default void adjustLightmapColors(ClientLevel level, float partialTicks, float skyDarken, float blockLightRedFlicker, float skyLight, int pixelX, int pixelY, Vector3f colors) {}
|
||||
}
|
||||
@@ -136,4 +136,63 @@ public interface IForgeGuiGraphics
|
||||
|
||||
self().blit(texture, x, y, boundsWidth, boundsHeight, 0.0f,0.0f, rectWidth, rectHeight, rectWidth, rectHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link GuiGraphics#blitNineSliced(ResourceLocation, int, int, int, int, int, int, int, int, int)} that supports specifying the texture's size.
|
||||
*/
|
||||
default void blitNineSlicedSized(ResourceLocation texture, int x, int y, int width, int height, int sliceSize, int uWidth, int vHeight, int uOffset, int vOffset,
|
||||
int textureWidth, int textureHeight)
|
||||
{
|
||||
blitNineSlicedSized(texture, x, y, width, height, sliceSize, sliceSize, uWidth, vHeight, uOffset, vOffset, textureWidth, textureHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link GuiGraphics#blitNineSliced(ResourceLocation, int, int, int, int, int, int, int, int, int, int)} that supports specifying the texture's size.
|
||||
*/
|
||||
default void blitNineSlicedSized(ResourceLocation texture, int x, int y, int width, int height, int sliceWidth, int sliceHeight, int uWidth, int vHeight,
|
||||
int uOffset, int vOffset, int textureWidth, int textureHeight)
|
||||
{
|
||||
blitNineSlicedSized(texture, x, y, width, height, sliceWidth, sliceHeight, sliceWidth, sliceHeight, uWidth, vHeight, uOffset, vOffset, textureWidth, textureHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of {@link GuiGraphics#blitNineSliced(ResourceLocation, int, int, int, int, int, int, int, int, int, int, int, int)} that supports specifying the texture's size.
|
||||
*/
|
||||
default void blitNineSlicedSized(ResourceLocation texture, int x, int y, int width, int height, int cornerWidth, int cornerHeight, int edgeWidth, int edgeHeight,
|
||||
int uWidth, int vHeight, int uOffset, int vOffset, int textureWidth, int textureHeight)
|
||||
{
|
||||
cornerWidth = Math.min(cornerWidth, width / 2);
|
||||
edgeWidth = Math.min(edgeWidth, width / 2);
|
||||
cornerHeight = Math.min(cornerHeight, height / 2);
|
||||
edgeHeight = Math.min(edgeHeight, height / 2);
|
||||
GuiGraphics self = self();
|
||||
if (width == uWidth && height == vHeight)
|
||||
{
|
||||
self.blit(texture, x, y, uOffset, vOffset, width, height, textureWidth, textureHeight);
|
||||
}
|
||||
else if (height == vHeight)
|
||||
{
|
||||
self.blit(texture, x, y, uOffset, vOffset, cornerWidth, height, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x + cornerWidth, y, width - edgeWidth - cornerWidth, height, uOffset + cornerWidth, vOffset, uWidth - edgeWidth - cornerWidth, vHeight, textureWidth, textureHeight);
|
||||
self.blit(texture, x + width - edgeWidth, y, uOffset + uWidth - edgeWidth, vOffset, edgeWidth, height, textureWidth, textureHeight);
|
||||
}
|
||||
else if (width == uWidth)
|
||||
{
|
||||
self.blit(texture, x, y, uOffset, vOffset, width, cornerHeight, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x, y + cornerHeight, width, height - edgeHeight - cornerHeight, uOffset, vOffset + cornerHeight, uWidth, vHeight - edgeHeight - cornerHeight, textureWidth, textureHeight);
|
||||
self.blit(texture, x, y + height - edgeHeight, uOffset, vOffset + vHeight - edgeHeight, width, edgeHeight, textureWidth, textureHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.blit(texture, x, y, uOffset, vOffset, cornerWidth, cornerHeight, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x + cornerWidth, y, width - edgeWidth - cornerWidth, cornerHeight, uOffset + cornerWidth, vOffset, uWidth - edgeWidth - cornerWidth, cornerHeight, textureWidth, textureHeight);
|
||||
self.blit(texture, x + width - edgeWidth, y, uOffset + uWidth - edgeWidth, vOffset, edgeWidth, cornerHeight, textureWidth, textureHeight);
|
||||
self.blit(texture, x, y + height - edgeHeight, uOffset, vOffset + vHeight - edgeHeight, cornerWidth, edgeHeight, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x + cornerWidth, y + height - edgeHeight, width - edgeWidth - cornerWidth, edgeHeight, uOffset + cornerWidth, vOffset + vHeight - edgeHeight, uWidth - edgeWidth - cornerWidth, edgeHeight, textureWidth, textureHeight);
|
||||
self.blit(texture, x + width - edgeWidth, y + height - edgeHeight, uOffset + uWidth - edgeWidth, vOffset + vHeight - edgeHeight, edgeWidth, edgeHeight, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x, y + cornerHeight, cornerWidth, height - edgeHeight - cornerHeight, uOffset, vOffset + cornerHeight, cornerWidth, vHeight - edgeHeight - cornerHeight, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x + cornerWidth, y + cornerHeight, width - edgeWidth - cornerWidth, height - edgeHeight - cornerHeight, uOffset + cornerWidth, vOffset + cornerHeight, uWidth - edgeWidth - cornerWidth, vHeight - edgeHeight - cornerHeight, textureWidth, textureHeight);
|
||||
self.blitRepeating(texture, x + width - edgeWidth, y + cornerHeight, cornerWidth, height - edgeHeight - cornerHeight, uOffset + uWidth - edgeWidth, vOffset + cornerHeight, edgeWidth, vHeight - edgeHeight - cornerHeight, textureWidth, textureHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.client.extensions.common;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.particle.ParticleEngine;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
@@ -15,6 +16,7 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
@@ -113,4 +115,17 @@ public interface IClientBlockExtensions
|
||||
}
|
||||
return originalColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the breaking particles created from the {@link BlockState} passed should be tinted with biome colors.
|
||||
*
|
||||
* @param state The state of this block
|
||||
* @param level The level the particles are spawning in
|
||||
* @param pos The position of the block
|
||||
* @return {@code true} if the particles should be tinted.
|
||||
*/
|
||||
default boolean areBreakingParticlesTinted(BlockState state, ClientLevel level, BlockPos pos)
|
||||
{
|
||||
return !state.is(Blocks.GRASS_BLOCK);
|
||||
}
|
||||
}
|
||||
@@ -474,6 +474,13 @@ public class ForgeGui extends Gui
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache()
|
||||
{
|
||||
super.clearCache();
|
||||
this.debugOverlay.clearChunkCache();
|
||||
}
|
||||
|
||||
protected void renderRecordOverlay(int width, int height, float partialTick, GuiGraphics guiGraphics)
|
||||
{
|
||||
if (overlayMessageTime > 0)
|
||||
@@ -485,8 +492,12 @@ public class ForgeGui extends Gui
|
||||
|
||||
if (opacity > 8)
|
||||
{
|
||||
//Include a shift based on the bar height plus the difference between the height that renderSelectedItemName
|
||||
// renders at (59) and the height that the overlay/status bar renders at (68) by default
|
||||
int yShift = Math.max(leftHeight, rightHeight) + (68 - 59);
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().translate(width / 2D, height - 68, 0.0D);
|
||||
//If y shift is smaller less than the default y level, just render it at the base y level
|
||||
guiGraphics.pose().translate(width / 2D, height - Math.max(yShift, 68), 0.0D);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
int color = (animateOverlayMessageColor ? Mth.hsvToRgb(hue / 50.0F, 0.7F, 0.6F) & WHITE : WHITE);
|
||||
|
||||
@@ -144,7 +144,7 @@ public enum VanillaGuiOverlay
|
||||
gui.setupOverlayRenderState(true, false);
|
||||
if (gui.getMinecraft().gameMode.getPlayerMode() != GameType.SPECTATOR)
|
||||
{
|
||||
gui.renderSelectedItemName(guiGraphics);
|
||||
gui.renderSelectedItemName(guiGraphics, Math.max(gui.leftHeight, gui.rightHeight));
|
||||
}
|
||||
else if (gui.getMinecraft().player.isSpectator())
|
||||
{
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
package net.minecraftforge.client.loading;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.CORE;
|
||||
import static net.minecraftforge.fml.Logging.LOADING;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.Consumer;
|
||||
@@ -34,11 +34,8 @@ import net.minecraftforge.resource.PathPackResources;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.ClientPackSource;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
|
||||
@@ -121,7 +118,7 @@ public class ClientModLoader
|
||||
|
||||
public static boolean completeModLoading()
|
||||
{
|
||||
List<ModLoadingWarning> warnings = ModLoader.get().getWarnings();
|
||||
var warnings = ModLoader.get().getWarnings();
|
||||
boolean showWarnings = true;
|
||||
try {
|
||||
showWarnings = ForgeConfig.CLIENT.showLoadWarnings.get();
|
||||
@@ -131,8 +128,8 @@ public class ClientModLoader
|
||||
if (!showWarnings) {
|
||||
//User disabled warning screen, as least log them
|
||||
if (!warnings.isEmpty()) {
|
||||
LOGGER.warn(LOADING, "Mods loaded with {} warning(s)", warnings.size());
|
||||
warnings.forEach(warning -> LOGGER.warn(LOADING, warning.formatToString()));
|
||||
LOGGER.warn(Logging.LOADING, "Mods loaded with {} warning(s)", warnings.size());
|
||||
warnings.forEach(warning -> LOGGER.warn(Logging.LOADING, warning.formatToString()));
|
||||
}
|
||||
warnings = Collections.emptyList(); //Clear warnings, as the user does not want to see them
|
||||
}
|
||||
@@ -163,7 +160,7 @@ public class ClientModLoader
|
||||
}
|
||||
|
||||
private static void clientPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks, Consumer<Pack> packAcceptor) {
|
||||
List<PathPackResources> hiddenPacks = new ArrayList<>();
|
||||
var hiddenPacks = new ArrayList<PathPackResources>();
|
||||
for (Entry<IModFile, ? extends PathPackResources> e : modResourcePacks.entrySet())
|
||||
{
|
||||
IModInfo mod = e.getKey().getModInfos().get(0);
|
||||
@@ -174,7 +171,7 @@ public class ClientModLoader
|
||||
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
|
||||
continue;
|
||||
}
|
||||
LOGGER.debug(CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
|
||||
LOGGER.debug(Logging.CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
|
||||
if (mod.getOwningFile().showAsResourcePack()) {
|
||||
packAcceptor.accept(modPack);
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.client.loading;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlConst;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
@@ -21,22 +22,19 @@ import net.minecraft.client.gui.screens.LoadingOverlay;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ReloadInstance;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraftforge.fml.StartupMessageManager;
|
||||
import net.minecraftforge.fml.earlydisplay.ColourScheme;
|
||||
import net.minecraftforge.fml.earlydisplay.DisplayWindow;
|
||||
import net.minecraftforge.fml.loading.progress.ProgressMeter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.opengl.GL30C;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.mojang.blaze3d.platform.GlConst.*;
|
||||
import static net.minecraft.util.Mth.clamp;
|
||||
import static org.lwjgl.opengl.GL30C.glViewport;
|
||||
import static org.lwjgl.opengl.GL30C.glTexParameterIi;
|
||||
|
||||
/**
|
||||
* This is an implementation of the LoadingOverlay that calls back into the early window rendering, as part of the
|
||||
* game loading cycle. We completely replace the {@link #render(GuiGraphics, int, int, float)} call from the parent
|
||||
@@ -71,8 +69,8 @@ public class ForgeLoadingOverlay extends LoadingOverlay {
|
||||
public void render(final @NotNull GuiGraphics graphics, final int mouseX, final int mouseY, final float partialTick) {
|
||||
long millis = Util.getMillis();
|
||||
float fadeouttimer = this.fadeOutStart > -1L ? (float)(millis - this.fadeOutStart) / 1000.0F : -1.0F;
|
||||
progress.setAbsolute(clamp((int)(this.reload.getActualProgress() * 100f), 0, 100));
|
||||
var fade = 1.0F - clamp(fadeouttimer - 1.0F, 0.0F, 1.0F);
|
||||
progress.setAbsolute(Mth.clamp((int)(this.reload.getActualProgress() * 100f), 0, 100));
|
||||
var fade = 1.0F - Mth.clamp(fadeouttimer - 1.0F, 0.0F, 1.0F);
|
||||
var colour = this.displayWindow.context().colourScheme().background();
|
||||
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, fade);
|
||||
if (fadeouttimer >= 1.0F) {
|
||||
@@ -82,24 +80,24 @@ public class ForgeLoadingOverlay extends LoadingOverlay {
|
||||
displayWindow.render(0xff);
|
||||
} else {
|
||||
GlStateManager._clearColor(colour.redf(), colour.greenf(), colour.bluef(), 1f);
|
||||
GlStateManager._clear(GL_COLOR_BUFFER_BIT, Minecraft.ON_OSX);
|
||||
GlStateManager._clear(GlConst.GL_COLOR_BUFFER_BIT, Minecraft.ON_OSX);
|
||||
displayWindow.render(0xFF);
|
||||
}
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
RenderSystem.blendFunc(GlConst.GL_SRC_ALPHA, GlConst.GL_ONE_MINUS_SRC_ALPHA);
|
||||
var fbWidth = this.minecraft.getWindow().getWidth();
|
||||
var fbHeight = this.minecraft.getWindow().getHeight();
|
||||
glViewport(0, 0, fbWidth, fbHeight);
|
||||
GL30C.glViewport(0, 0, fbWidth, fbHeight);
|
||||
final var twidth = this.displayWindow.context().width();
|
||||
final var theight = this.displayWindow.context().height();
|
||||
var wscale = (float)fbWidth / twidth;
|
||||
var hscale = (float)fbHeight / theight;
|
||||
var scale = this.displayWindow.context().scale() * Math.min(wscale, hscale) / 2f;
|
||||
var wleft = clamp(fbWidth * 0.5f - scale * twidth, 0, fbWidth);
|
||||
var wtop = clamp(fbHeight * 0.5f - scale * theight, 0, fbHeight);
|
||||
var wright = clamp(fbWidth * 0.5f + scale * twidth, 0, fbWidth);
|
||||
var wbottom = clamp(fbHeight * 0.5f + scale * theight, 0, fbHeight);
|
||||
GlStateManager.glActiveTexture(GL_TEXTURE0);
|
||||
var wleft = Mth.clamp(fbWidth * 0.5f - scale * twidth, 0, fbWidth);
|
||||
var wtop = Mth.clamp(fbHeight * 0.5f - scale * theight, 0, fbHeight);
|
||||
var wright = Mth.clamp(fbWidth * 0.5f + scale * twidth, 0, fbWidth);
|
||||
var wbottom = Mth.clamp(fbHeight * 0.5f + scale * theight, 0, fbHeight);
|
||||
GlStateManager.glActiveTexture(GlConst.GL_TEXTURE0);
|
||||
RenderSystem.disableCull();
|
||||
BufferBuilder bufferbuilder = Tesselator.getInstance().getBuilder();
|
||||
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, fade);
|
||||
@@ -120,7 +118,7 @@ public class ForgeLoadingOverlay extends LoadingOverlay {
|
||||
|
||||
// This is the actual screen data from the loading screen
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
RenderSystem.blendFunc(GlConst.GL_SRC_ALPHA, GlConst.GL_ONE_MINUS_SRC_ALPHA);
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
|
||||
RenderSystem.setShaderTexture(0, displayWindow.getFramebufferTextureId());
|
||||
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
|
||||
@@ -128,8 +126,8 @@ public class ForgeLoadingOverlay extends LoadingOverlay {
|
||||
bufferbuilder.vertex(wright, wbottom, 0f).uv(1, 0).color(1f, 1f, 1f, fade).endVertex();
|
||||
bufferbuilder.vertex(wright, wtop, 0f).uv(1, 1).color(1f, 1f, 1f, fade).endVertex();
|
||||
bufferbuilder.vertex(wleft, wtop, 0f).uv(0, 1).color(1f, 1f, 1f, fade).endVertex();
|
||||
glTexParameterIi(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameterIi(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
GL30C.glTexParameterIi(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MIN_FILTER, GlConst.GL_NEAREST);
|
||||
GL30C.glTexParameterIi(GlConst.GL_TEXTURE_2D, GlConst.GL_TEXTURE_MAG_FILTER, GlConst.GL_NEAREST);
|
||||
BufferUploader.drawWithShader(bufferbuilder.end());
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.disableBlend();
|
||||
|
||||
@@ -11,14 +11,18 @@ import net.minecraft.client.gui.screens.LoadingOverlay;
|
||||
import net.minecraft.server.packs.resources.ReloadInstance;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public final class NoVizFallback {
|
||||
private static long WINDOW;
|
||||
public static LongSupplier windowHandoff(IntSupplier width, IntSupplier height, Supplier<String> title, LongSupplier monitor) {
|
||||
return () -> WINDOW = glfwCreateWindow(width.getAsInt(), height.getAsInt(), title.get(), monitor.getAsLong(), 0L);
|
||||
return () -> WINDOW = GLFW.glfwCreateWindow(width.getAsInt(), height.getAsInt(), title.get(), monitor.getAsLong(), 0L);
|
||||
}
|
||||
|
||||
public static Supplier<LoadingOverlay> loadingOverlay(Supplier<Minecraft> mc, Supplier<ReloadInstance> ri, Consumer<Optional<Throwable>> ex, boolean fadein) {
|
||||
@@ -31,8 +35,8 @@ public final class NoVizFallback {
|
||||
|
||||
public static String glVersion() {
|
||||
if (WINDOW != 0) {
|
||||
var maj = glfwGetWindowAttrib(WINDOW, GLFW_CONTEXT_VERSION_MAJOR);
|
||||
var min = glfwGetWindowAttrib(WINDOW, GLFW_CONTEXT_VERSION_MINOR);
|
||||
var maj = GLFW.glfwGetWindowAttrib(WINDOW, GLFW.GLFW_CONTEXT_VERSION_MAJOR);
|
||||
var min = GLFW.glfwGetWindowAttrib(WINDOW, GLFW.GLFW_CONTEXT_VERSION_MINOR);
|
||||
return maj+"."+min;
|
||||
} else {
|
||||
return "3.2";
|
||||
|
||||
@@ -28,11 +28,16 @@ import net.minecraft.util.ExtraCodecs;
|
||||
* @param blockLight Block Light for this face from 0-15 (inclusive)
|
||||
* @param skyLight Sky Light for this face from 0-15 (inclusive)
|
||||
* @param ambientOcclusion If this face has AO
|
||||
* @param calculateNormals If we should manually calculate the normals for this block or inherit facing normals like vanilla
|
||||
*/
|
||||
public record ForgeFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion)
|
||||
public record ForgeFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion, boolean calculateNormals)
|
||||
{
|
||||
public ForgeFaceData(int color, int blockLight, int skyLight, boolean ambientOcclusion)
|
||||
{
|
||||
this(color, blockLight, skyLight, ambientOcclusion, false);
|
||||
}
|
||||
|
||||
public static final ForgeFaceData DEFAULT = new ForgeFaceData(0xFFFFFFFF, 0, 0, true);
|
||||
public static final ForgeFaceData DEFAULT = new ForgeFaceData(0xFFFFFFFF, 0, 0, true, false);
|
||||
|
||||
public static final Codec<Integer> COLOR = new ExtraCodecs.EitherCodec<>(Codec.INT, Codec.STRING).xmap(
|
||||
either -> either.map(Function.identity(), str -> (int) Long.parseLong(str, 16)),
|
||||
@@ -42,7 +47,8 @@ public record ForgeFaceData(int color, int blockLight, int skyLight, boolean amb
|
||||
COLOR.optionalFieldOf("color", 0xFFFFFFFF).forGetter(ForgeFaceData::color),
|
||||
Codec.intRange(0, 15).optionalFieldOf("block_light", 0).forGetter(ForgeFaceData::blockLight),
|
||||
Codec.intRange(0, 15).optionalFieldOf("sky_light", 0).forGetter(ForgeFaceData::skyLight),
|
||||
Codec.BOOL.optionalFieldOf("ambient_occlusion", true).forGetter(ForgeFaceData::ambientOcclusion))
|
||||
Codec.BOOL.optionalFieldOf("ambient_occlusion", true).forGetter(ForgeFaceData::ambientOcclusion),
|
||||
Codec.BOOL.optionalFieldOf("calculate_normals", false).forGetter(ForgeFaceData::calculateNormals))
|
||||
.apply(builder, ForgeFaceData::new));
|
||||
|
||||
/**
|
||||
|
||||
@@ -388,6 +388,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
private int color = 0xFFFFFFFF;
|
||||
private int blockLight = 0, skyLight = 0;
|
||||
private boolean hasAmbientOcclusion = true;
|
||||
private boolean calculateNormals = false;
|
||||
|
||||
private void validateCoordinate(float coord, char name) {
|
||||
Preconditions.checkArgument(!(coord < -16.0F) && !(coord > 32.0F), "Position " + name + " out of range, must be within [-16, 32]. Found: %d", coord);
|
||||
@@ -556,6 +557,17 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether we should calculate actual normals for the faces of this model or inherit them from facing the
|
||||
* way vanilla does
|
||||
* @param calc whether to calculate normals
|
||||
* @return this builder
|
||||
*/
|
||||
public ElementBuilder calculateNormals(boolean calc) {
|
||||
this.calculateNormals = calc;
|
||||
return this;
|
||||
}
|
||||
|
||||
private BiConsumer<Direction, FaceBuilder> addTexture(String texture) {
|
||||
return ($, f) -> f.texture(texture);
|
||||
}
|
||||
@@ -563,7 +575,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
BlockElement build() {
|
||||
Map<Direction, BlockElementFace> faces = this.faces.entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().build(), (k1, k2) -> { throw new IllegalArgumentException(); }, LinkedHashMap::new));
|
||||
return new BlockElement(from, to, faces, rotation == null ? null : rotation.build(), shade, new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion));
|
||||
return new BlockElement(from, to, faces, rotation == null ? null : rotation.build(), shade, new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion, this.calculateNormals));
|
||||
}
|
||||
|
||||
public T end() { return self(); }
|
||||
@@ -578,6 +590,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
private int color = 0xFFFFFFFF;
|
||||
private int blockLight = 0, skyLight = 0;
|
||||
private boolean hasAmbientOcclusion = true;
|
||||
private boolean calculateNormals = false;
|
||||
|
||||
FaceBuilder(Direction dir) {
|
||||
// param unused for functional match
|
||||
@@ -660,11 +673,22 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether we should calculate actual normals for this face or inherit them from facing the
|
||||
* way vanilla does
|
||||
* @param calc whether to calculate normals
|
||||
* @return this builder
|
||||
*/
|
||||
public FaceBuilder calculateNormals(boolean calc) {
|
||||
this.calculateNormals = calc;
|
||||
return this;
|
||||
}
|
||||
|
||||
BlockElementFace build() {
|
||||
if (this.texture == null) {
|
||||
throw new IllegalStateException("A model face must have a texture");
|
||||
}
|
||||
return new BlockElementFace(cullface, tintindex, texture, new BlockFaceUV(uvs, rotation.rotation), new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion));
|
||||
return new BlockElementFace(cullface, tintindex, texture, new BlockFaceUV(uvs, rotation.rotation), new ForgeFaceData(this.color, this.blockLight, this.skyLight, this.hasAmbientOcclusion, this.calculateNormals));
|
||||
}
|
||||
|
||||
public ElementBuilder end() { return ElementBuilder.this; }
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ public class ItemLayerModelBuilder<T extends ModelBuilder<T>> extends CustomLoad
|
||||
{
|
||||
faceData.compute(i, (key, value) -> {
|
||||
ForgeFaceData fallback = value == null ? ForgeFaceData.DEFAULT : value;
|
||||
return new ForgeFaceData(fallback.color(), blockLight, skyLight, fallback.ambientOcclusion());
|
||||
return new ForgeFaceData(fallback.color(), blockLight, skyLight, fallback.ambientOcclusion(), fallback.calculateNormals());
|
||||
});
|
||||
}
|
||||
return this;
|
||||
@@ -85,7 +85,7 @@ public class ItemLayerModelBuilder<T extends ModelBuilder<T>> extends CustomLoad
|
||||
{
|
||||
faceData.compute(i, (key, value) -> {
|
||||
ForgeFaceData fallback = value == null ? ForgeFaceData.DEFAULT : value;
|
||||
return new ForgeFaceData(color, fallback.blockLight(), fallback.skyLight(), fallback.ambientOcclusion());
|
||||
return new ForgeFaceData(color, fallback.blockLight(), fallback.skyLight(), fallback.ambientOcclusion(), fallback.calculateNormals());
|
||||
});
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -38,7 +38,7 @@ public class FlatQuadLighter extends QuadLighter
|
||||
isFullCube = Block.isShapeFullBlock(state.getCollisionShape(level, pos));
|
||||
for (Direction side : SIDES)
|
||||
{
|
||||
packedLight[side.ordinal()] = getLightColor(level, pos.relative(side), state);
|
||||
packedLight[side.ordinal()] = LevelRenderer.getLightColor(level, state, pos.relative(side));
|
||||
}
|
||||
//Note: We can just use the LevelRenderer method as we know the state is the state at the given position
|
||||
packedLight[6] = LevelRenderer.getLightColor(level, state, pos);
|
||||
|
||||
@@ -14,12 +14,12 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.LightLayer;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.IQuadTransformer;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static net.minecraftforge.client.model.IQuadTransformer.*;
|
||||
|
||||
/**
|
||||
* Base class for all quad lighting providers.
|
||||
* <p>
|
||||
@@ -84,15 +84,15 @@ public abstract class QuadLighter
|
||||
var vertices = quad.getVertices();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int offset = i * STRIDE;
|
||||
positions[i][0] = Float.intBitsToFloat(vertices[offset + POSITION]);
|
||||
positions[i][1] = Float.intBitsToFloat(vertices[offset + POSITION + 1]);
|
||||
positions[i][2] = Float.intBitsToFloat(vertices[offset + POSITION + 2]);
|
||||
int packedNormal = vertices[offset + NORMAL];
|
||||
int offset = i * IQuadTransformer.STRIDE;
|
||||
positions[i][0] = Float.intBitsToFloat(vertices[offset + IQuadTransformer.POSITION]);
|
||||
positions[i][1] = Float.intBitsToFloat(vertices[offset + IQuadTransformer.POSITION + 1]);
|
||||
positions[i][2] = Float.intBitsToFloat(vertices[offset + IQuadTransformer.POSITION + 2]);
|
||||
int packedNormal = vertices[offset + IQuadTransformer.NORMAL];
|
||||
normals[i][0] = (byte) (packedNormal & 0xFF);
|
||||
normals[i][1] = (byte) ((packedNormal >> 8) & 0xFF);
|
||||
normals[i][2] = (byte) ((packedNormal >> 16) & 0xFF);
|
||||
packedLightmaps[i] = vertices[offset + UV2];
|
||||
packedLightmaps[i] = vertices[offset + IQuadTransformer.UV2];
|
||||
}
|
||||
if (normals[0][0] == 0 && normals[0][1] == 0 && normals[0][2] == 0)
|
||||
{
|
||||
@@ -158,6 +158,7 @@ public abstract class QuadLighter
|
||||
* as it only uses the state for querying if the state has emissive rendering but instead looks up the state at the given position for checking the
|
||||
* light emission.
|
||||
*/
|
||||
@Deprecated(since = "1.20.1")
|
||||
protected static int getLightColor(BlockAndTintGetter level, BlockPos pos, BlockState state)
|
||||
{
|
||||
if (state.emissiveRendering(level, pos))
|
||||
|
||||
@@ -50,7 +50,7 @@ public class SmoothQuadLighter extends QuadLighter
|
||||
pos.setWithOffset(origin, x - 1, y - 1, z - 1);
|
||||
BlockState neighborState = level.getBlockState(pos);
|
||||
t[x][y][z] = neighborState.getLightBlock(level, pos) < 15;
|
||||
int brightness = getLightColor(level, pos, state);
|
||||
int brightness = LevelRenderer.getLightColor(level, neighborState, pos);
|
||||
s[x][y][z] = LightTexture.sky(brightness);
|
||||
b[x][y][z] = LightTexture.block(brightness);
|
||||
ao[x][y][z] = neighborState.getShadeBrightness(level, pos);
|
||||
|
||||
+10
-11
@@ -13,14 +13,13 @@ import net.minecraft.Util;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraftforge.client.model.IQuadTransformer;
|
||||
import net.minecraftforge.client.textures.UnitTextureAtlasSprite;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static net.minecraftforge.client.model.IQuadTransformer.*;
|
||||
|
||||
/**
|
||||
* Vertex consumer that outputs {@linkplain BakedQuad baked quads}.
|
||||
* <p>
|
||||
@@ -34,7 +33,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
for (var element : DefaultVertexFormat.BLOCK.getElements())
|
||||
map.put(element, DefaultVertexFormat.BLOCK.getOffset(i++) / 4); // Int offset
|
||||
});
|
||||
private static final int QUAD_DATA_SIZE = STRIDE * 4;
|
||||
private static final int QUAD_DATA_SIZE = IQuadTransformer.STRIDE * 4;
|
||||
|
||||
private final Consumer<BakedQuad> quadConsumer;
|
||||
|
||||
@@ -55,7 +54,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
@Override
|
||||
public VertexConsumer vertex(double x, double y, double z)
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + POSITION;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.POSITION;
|
||||
quadData[offset] = Float.floatToRawIntBits((float) x);
|
||||
quadData[offset + 1] = Float.floatToRawIntBits((float) y);
|
||||
quadData[offset + 2] = Float.floatToRawIntBits((float) z);
|
||||
@@ -65,7 +64,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
@Override
|
||||
public VertexConsumer normal(float x, float y, float z)
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + NORMAL;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.NORMAL;
|
||||
quadData[offset] = ((int) (x * 127.0f) & 0xFF) |
|
||||
(((int) (y * 127.0f) & 0xFF) << 8) |
|
||||
(((int) (z * 127.0f) & 0xFF) << 16);
|
||||
@@ -75,7 +74,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
@Override
|
||||
public VertexConsumer color(int r, int g, int b, int a)
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + COLOR;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.COLOR;
|
||||
quadData[offset] = ((a & 0xFF) << 24) |
|
||||
((b & 0xFF) << 16) |
|
||||
((g & 0xFF) << 8) |
|
||||
@@ -86,7 +85,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
@Override
|
||||
public VertexConsumer uv(float u, float v)
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + UV0;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.UV0;
|
||||
quadData[offset] = Float.floatToRawIntBits(u);
|
||||
quadData[offset + 1] = Float.floatToRawIntBits(v);
|
||||
return this;
|
||||
@@ -95,9 +94,9 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
@Override
|
||||
public VertexConsumer overlayCoords(int u, int v)
|
||||
{
|
||||
if (UV1 >= 0) // Vanilla doesn't support this, but it may be added by a 3rd party
|
||||
if (IQuadTransformer.UV1 >= 0) // Vanilla doesn't support this, but it may be added by a 3rd party
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + UV1;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.UV1;
|
||||
quadData[offset] = (u & 0xFFFF) | ((v & 0xFFFF) << 16);
|
||||
}
|
||||
return this;
|
||||
@@ -106,7 +105,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
@Override
|
||||
public VertexConsumer uv2(int u, int v)
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + UV2;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + IQuadTransformer.UV2;
|
||||
quadData[offset] = (u & 0xFFFF) | ((v & 0xFFFF) << 16);
|
||||
return this;
|
||||
}
|
||||
@@ -117,7 +116,7 @@ public class QuadBakingVertexConsumer implements VertexConsumer
|
||||
Integer baseOffset = ELEMENT_OFFSETS.get(element);
|
||||
if (baseOffset != null)
|
||||
{
|
||||
int offset = vertexIndex * STRIDE + baseOffset;
|
||||
int offset = vertexIndex * IQuadTransformer.STRIDE + baseOffset;
|
||||
System.arraycopy(rawData, 0, quadData, offset, rawData.length);
|
||||
}
|
||||
return this;
|
||||
|
||||
@@ -27,6 +27,8 @@ public class KeyMappingLookup
|
||||
}
|
||||
}
|
||||
|
||||
/** Replaced by {@link #getAll(InputConstants.Key) getAll} */
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
@Nullable
|
||||
public KeyMapping get(InputConstants.Key keyCode)
|
||||
{
|
||||
@@ -43,6 +45,7 @@ public class KeyMappingLookup
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
private KeyMapping get(InputConstants.Key keyCode, KeyModifier keyModifier)
|
||||
{
|
||||
Collection<KeyMapping> bindings = map.get(keyModifier).get(keyCode);
|
||||
@@ -59,6 +62,13 @@ public class KeyMappingLookup
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all active keys associated with the given key code and the active
|
||||
* modifiers and conflict context.
|
||||
*
|
||||
* @param keyCode the key being pressed
|
||||
* @return the list of key mappings
|
||||
*/
|
||||
public List<KeyMapping> getAll(InputConstants.Key keyCode)
|
||||
{
|
||||
List<KeyMapping> matchingBindings = new ArrayList<KeyMapping>();
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.FORGEMOD;
|
||||
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.Logging;
|
||||
import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -16,7 +15,6 @@ import net.minecraftforge.common.ForgeConfigSpec.BooleanValue;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.DoubleValue;
|
||||
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue;
|
||||
|
||||
|
||||
public class ForgeConfig {
|
||||
public static class Server {
|
||||
public final BooleanValue removeErroringBlockEntities;
|
||||
@@ -30,6 +28,8 @@ public class ForgeConfig {
|
||||
|
||||
public final ConfigValue<String> permissionHandler;
|
||||
|
||||
public final BooleanValue advertiseDedicatedServerToLan;
|
||||
|
||||
Server(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Server configuration settings")
|
||||
.push("server");
|
||||
@@ -69,6 +69,11 @@ public class ForgeConfig {
|
||||
.translation("forge.configgui.permissionHandler")
|
||||
.define("permissionHandler", "forge:default_handler");
|
||||
|
||||
advertiseDedicatedServerToLan = builder
|
||||
.comment("Set this to true to enable advertising the dedicated server to local LAN clients so that it shows up in the Multiplayer screen automatically.")
|
||||
.translation("forge.configgui.advertiseDedicatedServerToLan")
|
||||
.define("advertiseDedicatedServerToLan", true);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
@@ -98,8 +103,14 @@ public class ForgeConfig {
|
||||
|
||||
public final BooleanValue useCombinedDepthStencilAttachment;
|
||||
|
||||
@Deprecated(since = "1.20.1", forRemoval = true) // Config option ignored.
|
||||
public final BooleanValue compressLanIPv6Addresses;
|
||||
|
||||
public final BooleanValue calculateAllNormals;
|
||||
|
||||
public final BooleanValue stabilizeDirectionGetNearest;
|
||||
|
||||
|
||||
Client(ForgeConfigSpec.Builder builder) {
|
||||
builder.comment("Client only settings, mostly things related to rendering")
|
||||
.push("client");
|
||||
@@ -127,10 +138,24 @@ public class ForgeConfig {
|
||||
.define("useCombinedDepthStencilAttachment", false);
|
||||
|
||||
compressLanIPv6Addresses = builder
|
||||
.comment("When enabled, Forge will convert discovered 'Open to LAN' IPv6 addresses to their more compact, compressed representation")
|
||||
.comment("[DEPRECATED] Does nothing anymore, IPv6 addresses will be compressed always")
|
||||
.translation("forge.configgui.compressLanIPv6Addresses")
|
||||
.define("compressLanIPv6Addresses", true);
|
||||
|
||||
calculateAllNormals = builder
|
||||
.comment("During block model baking, manually calculates the normal for all faces.",
|
||||
"This was the default behavior of forge between versions 31.0 and 47.1.",
|
||||
"May result in differences between vanilla rendering and forge rendering.",
|
||||
"Will only produce differences for blocks that contain non-axis aligned faces.",
|
||||
"You will need to reload your resources to see results.")
|
||||
.translation("forge.configgui.calculateAllNormals")
|
||||
.define("calculateAllNormals", false);
|
||||
|
||||
stabilizeDirectionGetNearest = builder
|
||||
.comment("When enabled, a slightly biased Direction#getNearest calculation will be used to prevent normal fighting on 45 degree angle faces.")
|
||||
.translation("forge.configgui.stabilizeDirectionGetNearest")
|
||||
.define("stabilizeDirectionGetNearest", true);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
@@ -163,12 +188,12 @@ public class ForgeConfig {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLoad(final ModConfigEvent.Loading configEvent) {
|
||||
LogManager.getLogger().debug(FORGEMOD, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
LogManager.getLogger().debug(Logging.FORGEMOD, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onFileChange(final ModConfigEvent.Reloading configEvent) {
|
||||
LogManager.getLogger().debug(FORGEMOD, "Forge config just got changed on the file system!");
|
||||
LogManager.getLogger().debug(Logging.FORGEMOD, "Forge config just got changed on the file system!");
|
||||
}
|
||||
|
||||
//General
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.ADD;
|
||||
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.REMOVE;
|
||||
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.REPLACE;
|
||||
import static net.minecraftforge.fml.Logging.CORE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -26,6 +21,7 @@ import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraftforge.fml.Logging;
|
||||
import net.minecraftforge.fml.config.IConfigSpec;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -82,12 +78,12 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
this.childConfig = config;
|
||||
if (config != null && !isCorrect(config)) {
|
||||
String configName = config instanceof FileConfig ? ((FileConfig) config).getNioPath().toString() : config.toString();
|
||||
LOGGER.warn(CORE, "Configuration file {} is not correct. Correcting", configName);
|
||||
LOGGER.warn(Logging.CORE, "Configuration file {} is not correct. Correcting", configName);
|
||||
correct(config,
|
||||
(action, path, incorrectValue, correctedValue) ->
|
||||
LOGGER.warn(CORE, "Incorrect key {} was corrected from {} to its default, {}. {}", DOT_JOINER.join( path ), incorrectValue, correctedValue, incorrectValue == correctedValue ? "This seems to be an error." : ""),
|
||||
LOGGER.warn(Logging.CORE, "Incorrect key {} was corrected from {} to its default, {}. {}", DOT_JOINER.join( path ), incorrectValue, correctedValue, incorrectValue == correctedValue ? "This seems to be an error." : ""),
|
||||
(action, path, incorrectValue, correctedValue) ->
|
||||
LOGGER.debug(CORE, "The comment on key {} does not match the spec. This may create a backup.", DOT_JOINER.join( path )));
|
||||
LOGGER.debug(Logging.CORE, "The comment on key {} does not match the spec. This may create a backup.", DOT_JOINER.join( path )));
|
||||
|
||||
if (config instanceof FileConfig) {
|
||||
((FileConfig) config).save();
|
||||
@@ -178,7 +174,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
final String key = specEntry.getKey();
|
||||
final Object specValue = specEntry.getValue();
|
||||
final Object configValue = configMap.get(key);
|
||||
final CorrectionAction action = configValue == null ? ADD : REPLACE;
|
||||
final CorrectionAction action = configValue == null ? CorrectionAction.ADD : CorrectionAction.REPLACE;
|
||||
|
||||
parentPath.addLast(key);
|
||||
|
||||
@@ -256,7 +252,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
|
||||
ittr.remove();
|
||||
parentPath.addLast(entry.getKey());
|
||||
listener.onCorrect(REMOVE, parentPathUnmodifiable, entry.getValue(), null);
|
||||
listener.onCorrect(CorrectionAction.REMOVE, parentPathUnmodifiable, entry.getValue(), null);
|
||||
parentPath.removeLast();
|
||||
count++;
|
||||
}
|
||||
@@ -367,13 +363,13 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
@Override
|
||||
public Object correct(Object value) {
|
||||
if (value == null || !(value instanceof List) || ((List<?>)value).isEmpty()) {
|
||||
LOGGER.debug(CORE, "List on key {} is deemed to need correction. It is null, not a list, or an empty list. Modders, consider defineListAllowEmpty?", path.get(path.size() - 1));
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction. It is null, not a list, or an empty list. Modders, consider defineListAllowEmpty?", path.get(path.size() - 1));
|
||||
return getDefault();
|
||||
}
|
||||
List<?> list = Lists.newArrayList((List<?>) value);
|
||||
list.removeIf(elementValidator.negate());
|
||||
if (list.isEmpty()) {
|
||||
LOGGER.debug(CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
|
||||
return getDefault();
|
||||
}
|
||||
return list;
|
||||
@@ -395,13 +391,13 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
@Override
|
||||
public Object correct(Object value) {
|
||||
if (value == null || !(value instanceof List)) {
|
||||
LOGGER.debug(CORE, "List on key {} is deemed to need correction, as it is null or not a list.", path.get(path.size() - 1));
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction, as it is null or not a list.", path.get(path.size() - 1));
|
||||
return getDefault();
|
||||
}
|
||||
List<?> list = Lists.newArrayList((List<?>) value);
|
||||
list.removeIf(elementValidator.negate());
|
||||
if (list.isEmpty()) {
|
||||
LOGGER.debug(CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
|
||||
LOGGER.debug(Logging.CORE, "List on key {} is deemed to need correction. It failed validation.", path.get(path.size() - 1));
|
||||
return getDefault();
|
||||
}
|
||||
return list;
|
||||
@@ -654,7 +650,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
if (comment.stream().allMatch(String::isBlank))
|
||||
{
|
||||
if (FMLEnvironment.production)
|
||||
LOGGER.warn(CORE, "Detected a comment that is all whitespace for config option {}, which causes obscure bugs in Forge's config system and will cause a crash in the future. Please report this to the mod author.",
|
||||
LOGGER.warn(Logging.CORE, "Detected a comment that is all whitespace for config option {}, which causes obscure bugs in Forge's config system and will cause a crash in the future. Please report this to the mod author.",
|
||||
DOT_JOINER.join(path));
|
||||
else
|
||||
throw new IllegalStateException("Can not build comment for config option " + DOT_JOINER.join(path) + " as it comprises entirely of blank lines/whitespace. This is not allowed as it causes a \"constantly correcting config\" bug with NightConfig in Forge's config system.");
|
||||
@@ -730,7 +726,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
boolean result = ((Number)min).doubleValue() <= n.doubleValue() && n.doubleValue() <= ((Number)max).doubleValue();
|
||||
if(!result)
|
||||
{
|
||||
LOGGER.debug(CORE, "Range value {} is not within its bounds {}-{}", n.doubleValue(), ((Number)min).doubleValue(), ((Number)max).doubleValue());
|
||||
LOGGER.debug(Logging.CORE, "Range value {} is not within its bounds {}-{}", n.doubleValue(), ((Number)min).doubleValue(), ((Number)max).doubleValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -740,7 +736,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfi
|
||||
boolean result = c.compareTo(min) >= 0 && c.compareTo(max) <= 0;
|
||||
if(!result)
|
||||
{
|
||||
LOGGER.debug(CORE, "Range value {} is not within its bounds {}-{}", c, min, max);
|
||||
LOGGER.debug(Logging.CORE, "Range value {} is not within its bounds {}-{}", c, min, max);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
@@ -47,6 +48,7 @@ import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.ChatDecorator;
|
||||
import net.minecraft.network.chat.ClickEvent;
|
||||
@@ -70,11 +72,13 @@ import net.minecraft.world.Difficulty;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.effect.MobEffectUtil;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.ExperienceOrb;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.ai.attributes.Attribute;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
@@ -89,6 +93,7 @@ import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.RecipeType;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
@@ -108,6 +113,7 @@ import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.syncher.EntityDataSerializer;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket;
|
||||
import net.minecraft.world.item.alchemy.Potion;
|
||||
import net.minecraft.world.item.alchemy.PotionUtils;
|
||||
import net.minecraft.stats.Stats;
|
||||
@@ -125,9 +131,12 @@ import net.minecraftforge.common.loot.IGlobalLootModifier;
|
||||
import net.minecraftforge.common.loot.LootModifierManager;
|
||||
import net.minecraftforge.common.loot.LootTableIdCondition;
|
||||
import net.minecraftforge.common.util.BlockSnapshot;
|
||||
import net.minecraftforge.common.util.BrainBuilder;
|
||||
import net.minecraftforge.common.util.Lazy;
|
||||
import net.minecraftforge.common.util.MavenVersionStringHelper;
|
||||
import net.minecraftforge.common.util.MutableHashedLinkedMap;
|
||||
import net.minecraftforge.event.AnvilUpdateEvent;
|
||||
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
|
||||
import net.minecraftforge.event.DifficultyChangeEvent;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
import net.minecraftforge.event.GrindstoneEvent;
|
||||
@@ -144,10 +153,12 @@ import net.minecraftforge.event.entity.EntityTravelToDimensionEvent;
|
||||
import net.minecraftforge.event.entity.item.ItemTossEvent;
|
||||
import net.minecraftforge.event.entity.living.EnderManAngerEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingAttackEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingBreatheEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingChangeTargetEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingDamageEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingDeathEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingDropsEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingDrownEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingJumpEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent;
|
||||
@@ -155,6 +166,8 @@ import net.minecraftforge.event.entity.living.LivingChangeTargetEvent.ILivingTar
|
||||
import net.minecraftforge.event.entity.living.LivingFallEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingKnockBackEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingMakeBrainEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingSwapItemsEvent;
|
||||
import net.minecraftforge.event.entity.living.LivingUseTotemEvent;
|
||||
import net.minecraftforge.event.entity.living.LootingLevelEvent;
|
||||
import net.minecraftforge.event.entity.living.ShieldBlockEvent;
|
||||
@@ -238,6 +251,14 @@ public class ForgeHooks
|
||||
return event;
|
||||
}
|
||||
|
||||
public static Brain<?> onLivingMakeBrain(LivingEntity entity, Brain<?> originalBrain, Dynamic<?> dynamic)
|
||||
{
|
||||
BrainBuilder<?> brainBuilder = originalBrain.createBuilder();
|
||||
LivingMakeBrainEvent event = new LivingMakeBrainEvent(entity, brainBuilder);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
return brainBuilder.makeBrain(dynamic);
|
||||
}
|
||||
|
||||
public static boolean onLivingTick(LivingEntity entity)
|
||||
{
|
||||
return MinecraftForge.EVENT_BUS.post(new LivingTickEvent(entity));
|
||||
@@ -751,9 +772,25 @@ public class ForgeHooks
|
||||
return evt.isCanceled() ? evt.getCancellationResult() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onLeftClickBlock(Player, BlockPos, Direction, ServerboundPlayerActionPacket.Action)} instead
|
||||
*/
|
||||
@Deprecated(since = "1.20.1", forRemoval = true)
|
||||
public static PlayerInteractEvent.LeftClickBlock onLeftClickBlock(Player player, BlockPos pos, Direction face)
|
||||
{
|
||||
PlayerInteractEvent.LeftClickBlock evt = new PlayerInteractEvent.LeftClickBlock(player, pos, face);
|
||||
return onLeftClickBlock(player, pos, face, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK);
|
||||
}
|
||||
|
||||
public static PlayerInteractEvent.LeftClickBlock onLeftClickBlock(Player player, BlockPos pos, Direction face, ServerboundPlayerActionPacket.Action action)
|
||||
{
|
||||
PlayerInteractEvent.LeftClickBlock evt = new PlayerInteractEvent.LeftClickBlock(player, pos, face, PlayerInteractEvent.LeftClickBlock.Action.convert(action));
|
||||
MinecraftForge.EVENT_BUS.post(evt);
|
||||
return evt;
|
||||
}
|
||||
|
||||
public static PlayerInteractEvent.LeftClickBlock onClientMineHold(Player player, BlockPos pos, Direction face)
|
||||
{
|
||||
PlayerInteractEvent.LeftClickBlock evt = new PlayerInteractEvent.LeftClickBlock(player, pos, face, PlayerInteractEvent.LeftClickBlock.Action.CLIENT_HOLD);
|
||||
MinecraftForge.EVENT_BUS.post(evt);
|
||||
return evt;
|
||||
}
|
||||
@@ -1046,22 +1083,8 @@ public class ForgeHooks
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T> void deserializeTagAdditions(List<TagEntry> list, JsonObject json, List<TagEntry> allList)
|
||||
{
|
||||
if (json.has("remove"))
|
||||
{
|
||||
for (JsonElement entry : GsonHelper.getAsJsonArray(json, "remove"))
|
||||
{
|
||||
String s = GsonHelper.convertToString(entry, "value");
|
||||
TagEntry dummy;
|
||||
if (!s.startsWith("#"))
|
||||
dummy = TagEntry.optionalElement(new ResourceLocation(s));
|
||||
else
|
||||
dummy = TagEntry.tag(new ResourceLocation(s.substring(1)));
|
||||
allList.removeIf(e -> e.equals(dummy));
|
||||
}
|
||||
}
|
||||
}
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Tags use a codec now This was never used in 1.20
|
||||
public static <T> void deserializeTagAdditions(List<TagEntry> list, JsonObject json, List<TagEntry> allList) {}
|
||||
|
||||
@Nullable
|
||||
public static EntityDataSerializer<?> getSerializer(int id, CrudeIncrementalIntIdentityHashBiMap<EntityDataSerializer<?>> vanilla)
|
||||
@@ -1221,6 +1244,13 @@ public class ForgeHooks
|
||||
return e;
|
||||
}
|
||||
|
||||
public static LivingSwapItemsEvent.Hands onLivingSwapHandItems(LivingEntity livingEntity)
|
||||
{
|
||||
LivingSwapItemsEvent.Hands event = new LivingSwapItemsEvent.Hands(livingEntity);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
public static void writeAdditionalLevelSaveData(WorldData worldData, CompoundTag levelTag)
|
||||
{
|
||||
CompoundTag fmlData = new CompoundTag();
|
||||
@@ -1526,4 +1556,83 @@ public class ForgeHooks
|
||||
@Override public Optional<HolderSet.Named<T>> get(TagKey<T> key) { return Optional.of(HolderSet.emptyNamed(lookup, key)); }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles living entities being under water. This fires the {@link LivingBreatheEvent} and if the entity's air supply
|
||||
* is less than or equal to zero also the {@link LivingDrownEvent}. Additionally when the entity is under water it will
|
||||
* dismount if {@link IForgeEntity#canBeRiddenUnderFluidType(FluidType, Entity)} returns false.
|
||||
*
|
||||
* @param entity The living entity which is currently updated
|
||||
* @param consumeAirAmount The amount of air to consume when the entity is unable to breathe
|
||||
* @param refillAirAmount The amount of air to refill when the entity is able to breathe
|
||||
* @implNote This method needs to closely replicate the logic found right after the call site in {@link LivingEntity#baseTick()} as it overrides it.
|
||||
*/
|
||||
public static void onLivingBreathe(LivingEntity entity, int consumeAirAmount, int refillAirAmount)
|
||||
{
|
||||
// Check things that vanilla considers to be air - these will cause the air supply to be increased.
|
||||
boolean isAir = entity.getEyeInFluidType().isAir() || entity.level().getBlockState(BlockPos.containing(entity.getX(), entity.getEyeY(), entity.getZ())).is(Blocks.BUBBLE_COLUMN);
|
||||
// The following effects cause the entity to not drown, but do not cause the air supply to be increased.
|
||||
boolean canBreathe = !entity.canDrownInFluidType(entity.getEyeInFluidType()) || MobEffectUtil.hasWaterBreathing(entity) || (entity instanceof Player && ((Player) entity).getAbilities().invulnerable);
|
||||
LivingBreatheEvent breatheEvent = new LivingBreatheEvent(entity, isAir || canBreathe, consumeAirAmount, refillAirAmount, isAir);
|
||||
MinecraftForge.EVENT_BUS.post(breatheEvent);
|
||||
if (breatheEvent.canBreathe())
|
||||
{
|
||||
if (breatheEvent.canRefillAir())
|
||||
{
|
||||
entity.setAirSupply(Math.min(entity.getAirSupply() + breatheEvent.getRefillAirAmount(), entity.getMaxAirSupply()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.setAirSupply(entity.getAirSupply() - breatheEvent.getConsumeAirAmount());
|
||||
}
|
||||
|
||||
if (entity.getAirSupply() <= 0)
|
||||
{
|
||||
LivingDrownEvent drownEvent = new LivingDrownEvent(entity, entity.getAirSupply() <= -20, 2.0F, 8);
|
||||
if (!MinecraftForge.EVENT_BUS.post(drownEvent) && drownEvent.isDrowning())
|
||||
{
|
||||
entity.setAirSupply(0);
|
||||
Vec3 vec3 = entity.getDeltaMovement();
|
||||
|
||||
for (int i = 0; i < drownEvent.getBubbleCount(); ++i)
|
||||
{
|
||||
double d2 = entity.getRandom().nextDouble() - entity.getRandom().nextDouble();
|
||||
double d3 = entity.getRandom().nextDouble() - entity.getRandom().nextDouble();
|
||||
double d4 = entity.getRandom().nextDouble() - entity.getRandom().nextDouble();
|
||||
entity.level().addParticle(ParticleTypes.BUBBLE, entity.getX() + d2, entity.getY() + d3, entity.getZ() + d4, vec3.x, vec3.y, vec3.z);
|
||||
}
|
||||
|
||||
if (drownEvent.getDamageAmount() > 0) entity.hurt(entity.damageSources().drown(), drownEvent.getDamageAmount());
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAir && !entity.level().isClientSide && entity.isPassenger() && entity.getVehicle() != null && !entity.getVehicle().canBeRiddenUnderFluidType(entity.getEyeInFluidType(), entity))
|
||||
{
|
||||
entity.stopRiding();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onCreativeModeTabBuildContents(CreativeModeTab tab, ResourceKey<CreativeModeTab> tabKey, CreativeModeTab.DisplayItemsGenerator originalGenerator, CreativeModeTab.ItemDisplayParameters params, CreativeModeTab.Output output)
|
||||
{
|
||||
final var entries = new MutableHashedLinkedMap<ItemStack, CreativeModeTab.TabVisibility>(ItemStackLinkedSet.TYPE_AND_TAG,
|
||||
(key, left, right) -> {
|
||||
//throw new IllegalStateException("Accidentally adding the same item stack twice " + key.getDisplayName().getString() + " to a Creative Mode Tab: " + tab.getDisplayName().getString());
|
||||
// Vanilla adds enchanting books twice in both visibilities.
|
||||
// This is just code cleanliness for them. For us lets just increase the visibility and merge the entries.
|
||||
return CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS;
|
||||
}
|
||||
);
|
||||
|
||||
originalGenerator.accept(params, (stack, vis) -> {
|
||||
if (stack.getCount() != 1)
|
||||
throw new IllegalArgumentException("The stack count must be 1");
|
||||
entries.put(stack, vis);
|
||||
});
|
||||
|
||||
ModLoader.get().postEvent(new BuildCreativeModeTabContentsEvent(tab, tabKey, params, entries));
|
||||
|
||||
for (var entry : entries)
|
||||
output.accept(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.common;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import net.minecraftforge.common.util.MavenVersionStringHelper;
|
||||
import net.minecraftforge.fml.Logging;
|
||||
import net.minecraftforge.fml.loading.StringUtils;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import org.apache.commons.lang3.text.ExtendedMessageFormat;
|
||||
@@ -23,8 +24,6 @@ import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.CORE;
|
||||
|
||||
//TODO, this should be re-evaluated now that ITextComponents are passed everywhere instaed of strings.
|
||||
public class ForgeI18n {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -81,7 +80,7 @@ public class ForgeI18n {
|
||||
}
|
||||
|
||||
public static void loadLanguageData(final Map<String, String> properties) {
|
||||
LOGGER.debug(CORE,"Loading I18N data entries: {}", properties.size());
|
||||
LOGGER.debug(Logging.CORE,"Loading I18N data entries: {}", properties.size());
|
||||
i18n = properties;
|
||||
}
|
||||
|
||||
@@ -90,7 +89,7 @@ public class ForgeI18n {
|
||||
try {
|
||||
return parseFormat(pattern, args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.error(CORE,"Illegal format found `{}`", pattern);
|
||||
LOGGER.error(Logging.CORE,"Illegal format found `{}`", pattern);
|
||||
return pattern;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BiomeTags;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.FluidTags;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
@@ -19,7 +17,6 @@ import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
public class Tags
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.common.capabilities;
|
||||
|
||||
import net.minecraftforge.fml.Logging;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -15,8 +16,6 @@ import java.util.Comparator;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.CAPABILITIES;
|
||||
|
||||
public enum CapabilityManager
|
||||
{
|
||||
INSTANCE;
|
||||
@@ -46,7 +45,7 @@ public enum CapabilityManager
|
||||
{
|
||||
if (cap.isRegistered())
|
||||
{
|
||||
LOGGER.error(CAPABILITIES, "Cannot register capability implementation multiple times : {}", realName);
|
||||
LOGGER.error(Logging.CAPABILITIES, "Cannot register capability implementation multiple times : {}", realName);
|
||||
throw new IllegalArgumentException("Cannot register a capability implementation multiple times : "+ realName);
|
||||
}
|
||||
else
|
||||
@@ -74,7 +73,7 @@ public enum CapabilityManager
|
||||
|
||||
for (var auto : autos)
|
||||
{
|
||||
LOGGER.debug(CAPABILITIES, "Attempting to automatically register: " + auto);
|
||||
LOGGER.debug(Logging.CAPABILITIES, "Attempting to automatically register: " + auto);
|
||||
get(auto.getInternalName(), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import static net.minecraftforge.common.capabilities.CapabilityManager.get;
|
||||
|
||||
/*
|
||||
* References to Forge's built in capabilities.
|
||||
* Modders are recommended to use their own CapabilityTokens for 3rd party caps to maintain soft dependencies.
|
||||
@@ -19,8 +17,8 @@ import static net.minecraftforge.common.capabilities.CapabilityManager.get;
|
||||
*/
|
||||
public class ForgeCapabilities
|
||||
{
|
||||
public static final Capability<IEnergyStorage> ENERGY = get(new CapabilityToken<>(){});
|
||||
public static final Capability<IFluidHandler> FLUID_HANDLER = get(new CapabilityToken<>(){});
|
||||
public static final Capability<IFluidHandlerItem> FLUID_HANDLER_ITEM = get(new CapabilityToken<>(){});
|
||||
public static final Capability<IItemHandler> ITEM_HANDLER = get(new CapabilityToken<>(){});
|
||||
public static final Capability<IEnergyStorage> ENERGY = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
public static final Capability<IFluidHandler> FLUID_HANDLER = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
public static final Capability<IFluidHandlerItem> FLUID_HANDLER_ITEM = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
public static final Capability<IItemHandler> ITEM_HANDLER = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
}
|
||||
@@ -6,9 +6,7 @@
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.IntrinsicHolderTagsProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.TagKey;
|
||||
@@ -23,6 +21,7 @@ import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
// We typically don't do static imports as S2S can't remap them {as they are not qualified}, however this conflicts with vanilla and our tag class names, and our tags don't get obfed so its one line of warning.
|
||||
import static net.minecraftforge.common.Tags.Blocks.*;
|
||||
|
||||
public final class ForgeBlockTagsProvider extends BlockTagsProvider
|
||||
|
||||
@@ -9,11 +9,10 @@ import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.FluidTagsProvider;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.Tags.Fluids;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.minecraftforge.common.Tags.Fluids.MILK;
|
||||
|
||||
public final class ForgeFluidTagsProvider extends FluidTagsProvider
|
||||
{
|
||||
public ForgeFluidTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, ExistingFileHelper existingFileHelper)
|
||||
@@ -24,7 +23,7 @@ public final class ForgeFluidTagsProvider extends FluidTagsProvider
|
||||
@Override
|
||||
public void addTags(HolderLookup.Provider lookupProvider)
|
||||
{
|
||||
tag(MILK).addOptional(ForgeMod.MILK.getId()).addOptional(ForgeMod.FLOWING_MILK.getId());
|
||||
tag(Fluids.MILK).addOptional(ForgeMod.MILK.getId()).addOptional(ForgeMod.FLOWING_MILK.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,34 +29,37 @@ import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
{
|
||||
public final class ForgeRecipeProvider extends VanillaRecipeProvider {
|
||||
private final Map<Item, TagKey<Item>> replacements = new HashMap<>();
|
||||
private final Set<ResourceLocation> excludes = new HashSet<>();
|
||||
|
||||
public ForgeRecipeProvider(PackOutput packOutput)
|
||||
{
|
||||
public ForgeRecipeProvider(PackOutput packOutput) {
|
||||
super(packOutput);
|
||||
}
|
||||
|
||||
private void exclude(ItemLike item)
|
||||
{
|
||||
private void exclude(ItemLike item) {
|
||||
excludes.add(ForgeRegistries.ITEMS.getKey(item.asItem()));
|
||||
}
|
||||
|
||||
private void replace(ItemLike item, TagKey<Item> tag)
|
||||
{
|
||||
private void exclude(String name) {
|
||||
excludes.add(new ResourceLocation(name));
|
||||
}
|
||||
|
||||
private void replace(ItemLike item, TagKey<Item> tag) {
|
||||
replacements.put(item.asItem(), tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildRecipes(Consumer<FinishedRecipe> consumer)
|
||||
{
|
||||
protected void buildRecipes(Consumer<FinishedRecipe> consumer) {
|
||||
replace(Items.STICK, Tags.Items.RODS_WOODEN);
|
||||
replace(Items.GOLD_INGOT, Tags.Items.INGOTS_GOLD);
|
||||
replace(Items.IRON_INGOT, Tags.Items.INGOTS_IRON);
|
||||
@@ -69,6 +72,9 @@ public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
replace(Blocks.COBBLESTONE, Tags.Items.COBBLESTONE_NORMAL);
|
||||
replace(Blocks.COBBLED_DEEPSLATE, Tags.Items.COBBLESTONE_DEEPSLATE);
|
||||
|
||||
replace(Items.STRING, Tags.Items.STRING);
|
||||
exclude(getConversionRecipeName(Blocks.WHITE_WOOL, Items.STRING));
|
||||
|
||||
exclude(Blocks.GOLD_BLOCK);
|
||||
exclude(Items.GOLD_NUGGET);
|
||||
exclude(Blocks.IRON_BLOCK);
|
||||
@@ -94,8 +100,7 @@ public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FinishedRecipe enhance(FinishedRecipe vanilla)
|
||||
{
|
||||
private FinishedRecipe enhance(FinishedRecipe vanilla) {
|
||||
if (vanilla instanceof ShapelessRecipeBuilder.Result shapeless)
|
||||
return enhance(shapeless);
|
||||
if (vanilla instanceof ShapedRecipeBuilder.Result shaped)
|
||||
@@ -104,15 +109,12 @@ public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FinishedRecipe enhance(ShapelessRecipeBuilder.Result vanilla)
|
||||
{
|
||||
private FinishedRecipe enhance(ShapelessRecipeBuilder.Result vanilla) {
|
||||
List<Ingredient> ingredients = getField(ShapelessRecipeBuilder.Result.class, vanilla, 4);
|
||||
boolean modified = false;
|
||||
for (int x = 0; x < ingredients.size(); x++)
|
||||
{
|
||||
for (int x = 0; x < ingredients.size(); x++) {
|
||||
Ingredient ing = enhance(vanilla.getId(), ingredients.get(x));
|
||||
if (ing != null)
|
||||
{
|
||||
if (ing != null) {
|
||||
ingredients.set(x, ing);
|
||||
modified = true;
|
||||
}
|
||||
@@ -122,29 +124,24 @@ public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected CompletableFuture<?> saveAdvancement(CachedOutput output, FinishedRecipe finishedRecipe, JsonObject advancementJson)
|
||||
{
|
||||
protected CompletableFuture<?> saveAdvancement(CachedOutput output, FinishedRecipe recipe, JsonObject json) {
|
||||
// NOOP - We don't replace any of the advancement things yet...
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<?> buildAdvancement(CachedOutput p_253674_, ResourceLocation p_254102_, Advancement.Builder p_253712_)
|
||||
{
|
||||
protected CompletableFuture<?> buildAdvancement(CachedOutput output, ResourceLocation name, Advancement.Builder builder) {
|
||||
// NOOP - We don't replace any of the advancement things yet...
|
||||
return CompletableFuture.allOf();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FinishedRecipe enhance(ShapedRecipeBuilder.Result vanilla)
|
||||
{
|
||||
private FinishedRecipe enhance(ShapedRecipeBuilder.Result vanilla) {
|
||||
Map<Character, Ingredient> ingredients = getField(ShapedRecipeBuilder.Result.class, vanilla, 5);
|
||||
boolean modified = false;
|
||||
for (Character x : ingredients.keySet())
|
||||
{
|
||||
for (Character x : ingredients.keySet()) {
|
||||
Ingredient ing = enhance(vanilla.getId(), ingredients.get(x));
|
||||
if (ing != null)
|
||||
{
|
||||
if (ing != null) {
|
||||
ingredients.put(x, ing);
|
||||
modified = true;
|
||||
}
|
||||
@@ -153,22 +150,18 @@ public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Ingredient enhance(ResourceLocation name, Ingredient vanilla)
|
||||
{
|
||||
private Ingredient enhance(ResourceLocation name, Ingredient vanilla) {
|
||||
if (excludes.contains(name))
|
||||
return null;
|
||||
|
||||
boolean modified = false;
|
||||
List<Value> items = new ArrayList<>();
|
||||
Value[] vanillaItems = getField(Ingredient.class, vanilla, 2); //This will probably crash between versions, if null fix index
|
||||
for (Value entry : vanillaItems)
|
||||
{
|
||||
if (entry instanceof ItemValue)
|
||||
{
|
||||
for (Value entry : vanillaItems) {
|
||||
if (entry instanceof ItemValue) {
|
||||
ItemStack stack = entry.getItems().stream().findFirst().orElse(ItemStack.EMPTY);
|
||||
TagKey<Item> replacement = replacements.get(stack.getItem());
|
||||
if (replacement != null)
|
||||
{
|
||||
if (replacement != null) {
|
||||
items.add(new TagValue(replacement));
|
||||
modified = true;
|
||||
} else
|
||||
@@ -180,15 +173,12 @@ public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T, R> R getField(Class<T> clz, T inst, int index)
|
||||
{
|
||||
private <T, R> R getField(Class<T> clz, T inst, int index) {
|
||||
Field fld = clz.getDeclaredFields()[index];
|
||||
fld.setAccessible(true);
|
||||
try
|
||||
{
|
||||
try {
|
||||
return (R) fld.get(inst);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e)
|
||||
{
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.particle.ParticleEngine;
|
||||
import net.minecraft.client.particle.ParticleProvider;
|
||||
import net.minecraft.core.particles.ParticleType;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A data provider for {@link net.minecraft.client.particle.ParticleDescription}s.
|
||||
*
|
||||
* <p>To use this provider, extend this class and implement {@link #addDescriptions()}.
|
||||
* Then, register an instance using {@link net.minecraft.data.DataGenerator#addProvider(boolean, Factory)}
|
||||
* via the {@link net.minecraftforge.data.event.GatherDataEvent} on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod event bus}.
|
||||
*
|
||||
* <p>A description can be added to a {@link ParticleType} which uses a {@linkplain #sprite(ParticleType, ResourceLocation) sprite}
|
||||
* or {@linkplain #spriteSet(ParticleType, Iterable) sprite set}.
|
||||
*
|
||||
* <pre>{@code
|
||||
* @Override
|
||||
* protected void addDescriptions() {
|
||||
* // Single sprite
|
||||
* this.sprite(ParticleTypes.DRIPPING_LAVA, new ResourceLocation("drip_hang"));
|
||||
*
|
||||
* // Multiple sprites
|
||||
* this.spriteSet(ParticleTypes.CLOUD, new ResourceLocation("generic"), 8, true);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p>A particle description holds a list of textures used when rendering the
|
||||
* particle to the screen. All registered particle descriptions are stitched
|
||||
* together into a texture atlas called {@link net.minecraft.client.renderer.texture.TextureAtlas#LOCATION_PARTICLES}.
|
||||
* A {@link ParticleType} whose particle uses the texture atlas, typically via
|
||||
* the {@link net.minecraft.client.particle.ParticleRenderType}, can then reference
|
||||
* the necessary texture during rendering.
|
||||
*
|
||||
* <p>Particles with a particle description must have their particle providers
|
||||
* attached to a {@link ParticleType} as a {@linkplain net.minecraftforge.client.event.RegisterParticleProvidersEvent#registerSprite(ParticleType, ParticleProvider.Sprite) sprite}
|
||||
* or {@linkplain net.minecraftforge.client.event.RegisterParticleProvidersEvent#registerSpriteSet(ParticleType, ParticleEngine.SpriteParticleRegistration) sprite set}
|
||||
* consumer.
|
||||
*
|
||||
* @see DataProvider
|
||||
* @see net.minecraft.client.particle.ParticleDescription
|
||||
*/
|
||||
public abstract class ParticleDescriptionProvider implements DataProvider {
|
||||
|
||||
private final PackOutput.PathProvider particlesPath;
|
||||
@VisibleForTesting
|
||||
protected final ExistingFileHelper fileHelper;
|
||||
@VisibleForTesting
|
||||
protected final Map<ResourceLocation, List<String>> descriptions;
|
||||
|
||||
/**
|
||||
* Creates an instance of the data provider.
|
||||
*
|
||||
* @param output the expected root directory the data generator outputs to
|
||||
* @param fileHelper the helper used to validate a texture's existence
|
||||
*/
|
||||
protected ParticleDescriptionProvider(PackOutput output, ExistingFileHelper fileHelper) {
|
||||
this.particlesPath = output.createPathProvider(PackOutput.Target.RESOURCE_PACK, "particles");
|
||||
this.fileHelper = fileHelper;
|
||||
this.descriptions = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the particle descriptions generated by {@link #sprite(ParticleType, ResourceLocation)}
|
||||
* or one of the {@link #spriteSet(ParticleType, Iterable) sprite set methods}.
|
||||
*/
|
||||
protected abstract void addDescriptions();
|
||||
|
||||
/**
|
||||
* Creates a new particle description that contains a single texture for the
|
||||
* associated {@link ParticleType}.
|
||||
*
|
||||
* <p>Particle types with this description should be attached to a particle provider
|
||||
* via {@link net.minecraftforge.client.event.RegisterParticleProvidersEvent#registerSprite(ParticleType, ParticleProvider.Sprite)}.
|
||||
*
|
||||
* @param type the particle type the textures are applied
|
||||
* for
|
||||
* @param texture the texture to render for the particle type
|
||||
* @throws NullPointerException if the particle type is not registered
|
||||
* @throws IllegalArgumentException if a texture does not have an associated PNG
|
||||
* file, or the particle type has already been
|
||||
* provided
|
||||
*/
|
||||
protected void sprite(ParticleType<?> type, ResourceLocation texture) {
|
||||
this.spriteSet(type, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new particle description that contains multiple textures for the
|
||||
* associated {@link ParticleType}. The textures are generated from a common
|
||||
* name and appended with a number representing the state of the animation.
|
||||
*
|
||||
* <pre>{@code
|
||||
* minecraft:generic_0
|
||||
* minecraft:generic_1
|
||||
* minecraft:generic_2
|
||||
* // ...
|
||||
* }</pre>
|
||||
*
|
||||
* <p>Particle types with this description should be attached to a particle provider
|
||||
* via {@link net.minecraftforge.client.event.RegisterParticleProvidersEvent#registerSpriteSet(ParticleType, ParticleEngine.SpriteParticleRegistration)}.
|
||||
*
|
||||
* @param type the particle type the textures are applied
|
||||
* for
|
||||
* @param baseName the common name of all the textures
|
||||
* @param numOfTextures the number of textures within the set
|
||||
* @param reverse when {@code true}, the textures will be
|
||||
* listed in descending order
|
||||
* @throws NullPointerException if the particle type is not registered
|
||||
* @throws IllegalArgumentException if a texture does not have an associated PNG
|
||||
* file, or the particle type has already been
|
||||
* provided
|
||||
*/
|
||||
protected void spriteSet(ParticleType<?> type, ResourceLocation baseName, int numOfTextures, boolean reverse) {
|
||||
Preconditions.checkArgument(numOfTextures > 0, "The number of textures to generate must be positive");
|
||||
this.spriteSet(type, () -> new Iterator<>() {
|
||||
|
||||
private int counter = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.counter < numOfTextures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation next() {
|
||||
var texture = baseName.withSuffix("_" + (reverse ? numOfTextures - this.counter - 1 : this.counter));
|
||||
this.counter++;
|
||||
return texture;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new particle description that contains multiple textures for the
|
||||
* associated {@link ParticleType}. The textures are passed as varargs with
|
||||
* at least one texture present.
|
||||
*
|
||||
* <p>Particle types with this description should be attached to a particle provider
|
||||
* via {@link net.minecraftforge.client.event.RegisterParticleProvidersEvent#registerSpriteSet(ParticleType, ParticleEngine.SpriteParticleRegistration)}.
|
||||
*
|
||||
* @param type the particle type the textures are applied
|
||||
* for
|
||||
* @param texture the first texture in the description
|
||||
* @param textures a list of subsequent textures to render for
|
||||
* the particle type
|
||||
* @throws NullPointerException if the particle type is not registered
|
||||
* @throws IllegalArgumentException if a texture does not have an associated PNG
|
||||
* file, or the particle type has already been
|
||||
* provided
|
||||
*/
|
||||
protected void spriteSet(ParticleType<?> type, ResourceLocation texture, ResourceLocation... textures) {
|
||||
this.spriteSet(type, Stream.concat(Stream.of(texture), Arrays.stream(textures))::iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new particle description that contains multiple textures for the
|
||||
* associated {@link ParticleType}. The textures are passed as an iterable.
|
||||
*
|
||||
* <p>Particle types with this description should be attached to a particle provider
|
||||
* via {@link net.minecraftforge.client.event.RegisterParticleProvidersEvent#registerSpriteSet(ParticleType, ParticleEngine.SpriteParticleRegistration)}.
|
||||
*
|
||||
* @param type the particle type the textures are applied
|
||||
* for
|
||||
* @param textures a list of textures to render for the
|
||||
* particle type
|
||||
* @throws NullPointerException if the particle type is not registered
|
||||
* @throws IllegalArgumentException if there are no textures provided, a texture
|
||||
* does not have an associated PNG file, or
|
||||
* the particle type has already been provided
|
||||
*/
|
||||
protected void spriteSet(ParticleType<?> type, Iterable<ResourceLocation> textures) {
|
||||
// Make sure particle type is registered
|
||||
var particle = Preconditions.checkNotNull(ForgeRegistries.PARTICLE_TYPES.getKey(type), "The particle type is not registered");
|
||||
|
||||
// Validate textures
|
||||
List<String> desc = new ArrayList<>();
|
||||
for (var texture : textures) {
|
||||
Preconditions.checkArgument(this.fileHelper.exists(texture, PackType.CLIENT_RESOURCES, ".png", "textures/particle"),
|
||||
"Texture '%s' does not exist in any known resource pack", texture);
|
||||
desc.add(texture.toString());
|
||||
}
|
||||
Preconditions.checkArgument(desc.size() > 0, "The particle type '%s' must have one texture", particle);
|
||||
|
||||
// Insert into map
|
||||
if (this.descriptions.putIfAbsent(particle, desc) != null) {
|
||||
throw new IllegalArgumentException(String.format("The particle type '%s' already has a description associated with it", particle));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<?> run(CachedOutput cache) {
|
||||
this.addDescriptions();
|
||||
|
||||
return CompletableFuture.allOf(
|
||||
this.descriptions.entrySet().stream().map(entry -> {
|
||||
// Map entries to the description format
|
||||
var textures = new JsonArray();
|
||||
entry.getValue().forEach(textures::add);
|
||||
return DataProvider.saveStable(cache,
|
||||
Util.make(new JsonObject(), obj -> obj.add("textures", textures)),
|
||||
this.particlesPath.json(entry.getKey())
|
||||
);
|
||||
}).toArray(CompletableFuture[]::new)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Particle Descriptions";
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.vehicle.Boat;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraftforge.fluids.FluidType;
|
||||
@@ -37,4 +38,17 @@ public interface IForgeBoat
|
||||
{
|
||||
return type.supportsBoating(self());
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@code false}, the fluid will no longer update its height value while
|
||||
* within a boat while it is not within a fluid ({@link Boat#isUnderWater()}.
|
||||
*
|
||||
* @param state the state of the fluid the rider is within
|
||||
* @param rider the rider of the boat
|
||||
* @return {@code true} if the fluid height should be updated, {@code false} otherwise
|
||||
*/
|
||||
default boolean shouldUpdateFluidWhileRiding(FluidState state, Entity rider)
|
||||
{
|
||||
return state.shouldUpdateWhileBoating(self(), rider);
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,13 @@ 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.entity.vehicle.Boat;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.SpawnEggItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -26,9 +29,11 @@ import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.ForgeSpawnEggItem;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.SoundAction;
|
||||
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||
import net.minecraftforge.entity.PartEntity;
|
||||
import net.minecraftforge.event.entity.EntityEvent;
|
||||
import net.minecraftforge.fluids.FluidType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -424,4 +429,23 @@ public interface IForgeEntity extends ICapabilitySerializable<CompoundTag>
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Remove Entity Eye/Size hooks, as they need to be redesigned
|
||||
default float getEyeHeightForge(Pose pose, EntityDimensions size)
|
||||
{
|
||||
return self().getEyeHeightAccess(pose, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@code false}, the fluid will no longer update its height value while
|
||||
* within a boat while it is not within a fluid ({@link Boat#isUnderWater()}.
|
||||
*
|
||||
* @param state the state of the fluid the rider is within
|
||||
* @param boat the boat the rider is within that is not inside a fluid
|
||||
* @return {@code true} if the fluid height should be updated, {@code false} otherwise
|
||||
*/
|
||||
default boolean shouldUpdateFluidWhileBoating(FluidState state, Boat boat)
|
||||
{
|
||||
return boat.shouldUpdateFluidWhileRiding(state, self());
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.vehicle.Boat;
|
||||
@@ -94,6 +95,20 @@ public interface IForgeFluid
|
||||
return getFluidType().supportsBoating(state, boat);
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@code false}, the fluid will no longer update its height value while
|
||||
* within a boat while it is not within a fluid ({@link Boat#isUnderWater()}.
|
||||
*
|
||||
* @param state the state of the fluid the rider is within
|
||||
* @param boat the boat the rider is within that is not inside a fluid
|
||||
* @param rider the rider of the boat
|
||||
* @return {@code true} if the fluid height should be updated, {@code false} otherwise
|
||||
*/
|
||||
default boolean shouldUpdateWhileBoating(FluidState state, Boat boat, Entity rider)
|
||||
{
|
||||
return getFluidType().shouldUpdateWhileBoating(state, boat, rider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path type of this fluid when an entity is pathfinding. When
|
||||
* {@code null}, uses vanilla behavior.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.vehicle.Boat;
|
||||
@@ -88,6 +89,19 @@ public interface IForgeFluidState
|
||||
return self().getType().supportsBoating(self(), boat);
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@code false}, the fluid will no longer update its height value while
|
||||
* within a boat while it is not within a fluid ({@link Boat#isUnderWater()}.
|
||||
*
|
||||
* @param boat the boat the rider is within that is not inside a fluid
|
||||
* @param rider the rider of the boat
|
||||
* @return {@code true} if the fluid height should be updated, {@code false} otherwise
|
||||
*/
|
||||
default boolean shouldUpdateWhileBoating(Boat boat, Entity rider)
|
||||
{
|
||||
return self().getType().shouldUpdateWhileBoating(self(), boat, rider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path type of this fluid when an entity is pathfinding. When
|
||||
* {@code null}, uses vanilla behavior.
|
||||
|
||||
+12
-26
@@ -10,8 +10,7 @@ import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
|
||||
public interface IForgeIntrinsicHolderTagAppender<T> extends IForgeTagAppender<T>
|
||||
{
|
||||
public interface IForgeIntrinsicHolderTagAppender<T> extends IForgeTagAppender<T> {
|
||||
private IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> self() {
|
||||
return (IntrinsicHolderTagsProvider.IntrinsicTagAppender<T>) this;
|
||||
}
|
||||
@@ -24,8 +23,7 @@ public interface IForgeIntrinsicHolderTagAppender<T> extends IForgeTagAppender<T
|
||||
* @param entry The entry to remove
|
||||
* @return The builder for chaining
|
||||
*/
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final T entry)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final T entry) {
|
||||
return remove(this.getKey(entry));
|
||||
}
|
||||
|
||||
@@ -36,78 +34,66 @@ public interface IForgeIntrinsicHolderTagAppender<T> extends IForgeTagAppender<T
|
||||
* @return The builder for chaining
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final T first, final T...entries)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final T first, final T...entries) {
|
||||
this.remove(first);
|
||||
for (T entry : entries)
|
||||
{
|
||||
this.remove(entry);
|
||||
}
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> addTags(TagKey<T>... values)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> addTags(TagKey<T>... values) {
|
||||
IForgeTagAppender.super.addTags(values);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> replace()
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> replace() {
|
||||
IForgeTagAppender.super.replace();
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> replace(boolean value)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> replace(boolean value) {
|
||||
IForgeTagAppender.super.replace(value);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceLocation location)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceLocation location) {
|
||||
IForgeTagAppender.super.remove(location);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceLocation first, final ResourceLocation... locations)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceLocation first, final ResourceLocation... locations) {
|
||||
IForgeTagAppender.super.remove(first, locations);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceKey<T> resourceKey)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceKey<T> resourceKey) {
|
||||
IForgeTagAppender.super.remove(resourceKey);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceKey<T> firstResourceKey, final ResourceKey<T>... resourceKeys)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(final ResourceKey<T> firstResourceKey, final ResourceKey<T>... resourceKeys) {
|
||||
IForgeTagAppender.super.remove(firstResourceKey, resourceKeys);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(TagKey<T> tag)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(TagKey<T> tag) {
|
||||
IForgeTagAppender.super.remove(tag);
|
||||
return self();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(TagKey<T> first, TagKey<T>...tags)
|
||||
{
|
||||
default IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> remove(TagKey<T> first, TagKey<T>...tags) {
|
||||
IForgeTagAppender.super.remove(first, tags);
|
||||
return self();
|
||||
}
|
||||
|
||||
@@ -330,10 +330,28 @@ public interface IForgeItem
|
||||
/**
|
||||
* Called to tick armor in the armor slot. Override to do something
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Use onInventoryTick
|
||||
default void onArmorTick(ItemStack stack, Level level, Player player)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to tick this items in a players inventory, the indexes are the global slot index.
|
||||
*/
|
||||
default void onInventoryTick(ItemStack stack, Level level, Player player, int slotIndex, int selectedIndex)
|
||||
{
|
||||
// For compatibility reasons we have to use non-local index values, I think this is a vanilla bug but lets maintain compatibility
|
||||
int vanillaIndex = slotIndex;
|
||||
if (slotIndex >= 36) {
|
||||
vanillaIndex -= 36;
|
||||
if (vanillaIndex >= 4)
|
||||
vanillaIndex -= 4;
|
||||
else
|
||||
onArmorTick(stack, level, player);
|
||||
}
|
||||
stack.inventoryTick(level, player, vanillaIndex, selectedIndex == vanillaIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specific ItemStack can be placed in the specified armor
|
||||
* slot, for the entity.
|
||||
|
||||
@@ -292,11 +292,21 @@ public interface IForgeItemStack extends ICapabilitySerializable<CompoundTag>
|
||||
/**
|
||||
* Called to tick armor in the armor slot. Override to do something
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Use onInventoryTick
|
||||
default void onArmorTick(Level level, Player player)
|
||||
{
|
||||
self().getItem().onArmorTick(self(), level, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to tick this items in a players inventory, the indexes are the global slot index.
|
||||
*/
|
||||
default void onInventoryTick(Level level, Player player, int slotIndex, int selectedIndex)
|
||||
{
|
||||
self().getItem().onInventoryTick(self(), level, player, slotIndex, selectedIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called every tick from {@code Horse#playGallopSound(SoundEvent)} on the item in the
|
||||
* armor slot.
|
||||
|
||||
@@ -5,37 +5,22 @@
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagBuilder;
|
||||
import net.minecraft.tags.TagEntry;
|
||||
|
||||
public interface IForgeRawTagBuilder
|
||||
{
|
||||
default TagBuilder getRawBuilder()
|
||||
{
|
||||
public interface IForgeRawTagBuilder {
|
||||
default TagBuilder getRawBuilder() {
|
||||
return (TagBuilder)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* internal, called when a raw builder is written to json to add forge additions (e.g. the remove list)
|
||||
* @deprecated Never used, tags use a Codec now, so remove this later.
|
||||
*/
|
||||
default void serializeTagAdditions(final JsonObject tagJson)
|
||||
{
|
||||
TagBuilder rawBuilder = this.getRawBuilder();
|
||||
Stream<TagEntry> removeEntries = rawBuilder.getRemoveEntries();
|
||||
JsonArray removeEntriesAsJsonArray = new JsonArray();
|
||||
//removeEntries.forEach(proxy ->proxy.serializeTo(removeEntriesAsJsonArray)); // TODO: Figure out what the replacement for this is. -C
|
||||
if (removeEntriesAsJsonArray.size() > 0)
|
||||
{
|
||||
tagJson.add("remove", removeEntriesAsJsonArray);
|
||||
}
|
||||
|
||||
}
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
default void serializeTagAdditions(final JsonObject tagJson) {}
|
||||
|
||||
/**
|
||||
* Adds a tag entry to the remove list.
|
||||
@@ -43,8 +28,7 @@ public interface IForgeRawTagBuilder
|
||||
* @param source The source of the caller for logging purposes (generally a modid)
|
||||
* @return The builder for chaining purposes
|
||||
*/
|
||||
default TagBuilder remove(final TagEntry tagEntry, final String source)
|
||||
{
|
||||
default TagBuilder remove(final TagEntry tagEntry, final String source) {
|
||||
return this.getRawBuilder().remove(tagEntry);
|
||||
}
|
||||
|
||||
@@ -54,20 +38,17 @@ public interface IForgeRawTagBuilder
|
||||
* @param source The source of the caller for logging purposes (generally a modid)
|
||||
* @return The builder for chaining purposes
|
||||
*/
|
||||
default TagBuilder removeElement(final ResourceLocation elementID, final String source)
|
||||
{
|
||||
default TagBuilder removeElement(final ResourceLocation elementID, final String source) {
|
||||
return this.remove(TagEntry.element(elementID), source);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a tag to the remove list.
|
||||
* @param tagID The ID of the tag to add to the remove list
|
||||
* @param source The source of the caller for logging purposes (generally a modid)
|
||||
* @return The builder for chaining purposes
|
||||
*/
|
||||
default TagBuilder removeTag(final ResourceLocation tagID, final String source)
|
||||
{
|
||||
default TagBuilder removeTag(final ResourceLocation tagID, final String source) {
|
||||
return this.remove(TagEntry.tag(tagID), source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.util;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus;
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor;
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType;
|
||||
import net.minecraft.world.entity.schedule.Activity;
|
||||
import net.minecraft.world.entity.schedule.Schedule;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* This object is used to encapsulate state found inside a {@link Brain} instance,
|
||||
* to make it easily accessible for modders to manipulate during {@link net.minecraftforge.event.entity.living.LivingMakeBrainEvent}.<br>
|
||||
* <br>
|
||||
* Provided are a variety of getter/setter methods to access and manipulate the encapsulated state.<br>
|
||||
* <br>
|
||||
* Methods marked with "INTENDED FOR INTERNAL USE" are only meant to be used inside:
|
||||
* <ul>
|
||||
* <li>{@link net.minecraftforge.common.ForgeHooks#onLivingMakeBrain(LivingEntity, Brain, Dynamic)}
|
||||
* <li>{@link Brain#createBuilder()}
|
||||
* <li>{@link Brain#copyFromBuilder(BrainBuilder)}
|
||||
* </ul>
|
||||
* Of course, nothing egregious will happen should a modder choose to use them for their own purposes.<br>
|
||||
*/
|
||||
public class BrainBuilder<E extends LivingEntity> {
|
||||
private final Collection<MemoryModuleType<?>> memoryTypes = new HashSet<>();
|
||||
private final Collection<SensorType<? extends Sensor<? super E>>> sensorTypes = new HashSet<>();
|
||||
private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = Maps.newTreeMap();
|
||||
private Schedule schedule = Schedule.EMPTY;
|
||||
private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap();
|
||||
private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = Maps.newHashMap();
|
||||
private final Set<Activity> coreActivities = Sets.newHashSet();
|
||||
private final Set<Activity> activeActivites = Sets.newHashSet();
|
||||
private Activity defaultActivity = Activity.IDLE;
|
||||
|
||||
public BrainBuilder(Brain<E> ignoredBrain) {}
|
||||
|
||||
public Brain.Provider<E> provider() {
|
||||
return Brain.provider(this.memoryTypes, this.sensorTypes);
|
||||
}
|
||||
|
||||
public Collection<MemoryModuleType<?>> getMemoryTypes() {
|
||||
return this.memoryTypes;
|
||||
}
|
||||
|
||||
public Collection<SensorType<? extends Sensor<? super E>>> getSensorTypes() {
|
||||
return this.sensorTypes;
|
||||
}
|
||||
|
||||
public Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> getAvailableBehaviorsByPriority() {
|
||||
return this.availableBehaviorsByPriority;
|
||||
}
|
||||
|
||||
public Schedule getSchedule() {
|
||||
return this.schedule;
|
||||
}
|
||||
|
||||
public void setSchedule(Schedule schedule) {
|
||||
this.schedule = schedule;
|
||||
}
|
||||
|
||||
public Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> getActivityRequirements() {
|
||||
return this.activityRequirements;
|
||||
}
|
||||
|
||||
public Map<Activity, Set<MemoryModuleType<?>>> getActivityMemoriesToEraseWhenStopped() {
|
||||
return this.activityMemoriesToEraseWhenStopped;
|
||||
}
|
||||
|
||||
public Set<Activity> getCoreActivities() {
|
||||
return this.coreActivities;
|
||||
}
|
||||
|
||||
public Activity getDefaultActivity() {
|
||||
return this.defaultActivity;
|
||||
}
|
||||
|
||||
public void setDefaultActivity(Activity defaultActivity) {
|
||||
this.defaultActivity = defaultActivity;
|
||||
}
|
||||
|
||||
public Set<Activity> getActiveActivites() {
|
||||
return this.activeActivites;
|
||||
}
|
||||
|
||||
public void setActiveActivites(Set<Activity> value) {
|
||||
this.activeActivites.clear();
|
||||
this.activeActivites.addAll(value);
|
||||
}
|
||||
|
||||
/** You may use this as a helper method for adding a behavior to an Activity by priority to an entity's brain. */
|
||||
public void addBehaviorToActivityByPriority(Integer priority, Activity activity, BehaviorControl<? super E> behaviorControl) {
|
||||
this.availableBehaviorsByPriority.computeIfAbsent(priority, (i) -> Maps.newHashMap()).computeIfAbsent(activity, (a) -> Sets.newLinkedHashSet()).add(behaviorControl);
|
||||
}
|
||||
|
||||
/** You may use this as a helper method for adding memory requirements for an Activity to an entity's brain. */
|
||||
public void addRequirementsToActivity(Activity activity, Collection<Pair<MemoryModuleType<?>, MemoryStatus>> requirements) {
|
||||
addRequirementsToActivityInternal(this.activityRequirements, activity, requirements);
|
||||
}
|
||||
|
||||
/** You may use this as a helper method for adding a collection of memories to erase when an Activity is stopped to entity's brain. */
|
||||
public void addMemoriesToEraseWhenActivityStopped(Activity activity, Collection<MemoryModuleType<?>> memories) {
|
||||
addMemoriesToEraseWhenActivityStoppedInternal(this.activityMemoriesToEraseWhenStopped, activity, memories);
|
||||
}
|
||||
|
||||
//====================================================================================================================//
|
||||
// Everything below this is just to implement Brain.createBuilder and Brain.copyFromBuilder, hence marked as internal //
|
||||
//====================================================================================================================//
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void addAvailableBehaviorsByPriorityFrom(Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> addFrom) {
|
||||
addFrom.forEach(((priority, activitySetMap) -> activitySetMap.forEach(((activity, behaviorControls) -> this.availableBehaviorsByPriority.computeIfAbsent(priority, (p) -> Maps.newHashMap()).computeIfAbsent(activity, (a) -> Sets.newLinkedHashSet()).addAll(behaviorControls)))));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void addAvailableBehaviorsByPriorityTo(Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> addTo){
|
||||
this.availableBehaviorsByPriority.forEach(((priority, activitySetMap) -> activitySetMap.forEach(((activity, behaviorControls) -> addTo.computeIfAbsent(priority, (p) -> Maps.newHashMap()).computeIfAbsent(activity, (a) -> Sets.newLinkedHashSet()).addAll(behaviorControls)))));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void addActivityRequirementsFrom(Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> addFrom) {
|
||||
addFrom.forEach(this::addRequirementsToActivity);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void addActivityRequirementsTo(Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> addTo) {
|
||||
this.activityRequirements.forEach(((activity, requirements) -> addRequirementsToActivityInternal(addTo, activity, requirements)));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void addActivityMemoriesToEraseWhenStoppedFrom(Map<Activity, Set<MemoryModuleType<?>>> addFrom) {
|
||||
addFrom.forEach(this::addMemoriesToEraseWhenActivityStopped);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void addActivityMemoriesToEraseWhenStoppedTo(Map<Activity, Set<MemoryModuleType<?>>> addTo) {
|
||||
this.activityMemoriesToEraseWhenStopped.forEach(((activity, memories) -> addMemoriesToEraseWhenActivityStoppedInternal(addTo, activity, memories)));
|
||||
}
|
||||
|
||||
private static void addMemoriesToEraseWhenActivityStoppedInternal(Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped, Activity activity, Collection<MemoryModuleType<?>> memories) {
|
||||
activityMemoriesToEraseWhenStopped.computeIfAbsent(activity, (a) -> Sets.newHashSet()).addAll(memories);
|
||||
}
|
||||
|
||||
private static void addRequirementsToActivityInternal(Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements, Activity activity, Collection<Pair<MemoryModuleType<?>, MemoryStatus>> requirements) {
|
||||
activityRequirements.computeIfAbsent(activity, (a) -> Sets.newHashSet()).addAll(requirements);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public Brain<E> makeBrain(Dynamic<?> dynamic) {
|
||||
Brain<E> brain = Brain.provider(this.memoryTypes, this.sensorTypes).makeBrain(dynamic);
|
||||
brain.copyFromBuilder(this);
|
||||
return brain;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.common.util;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@@ -40,8 +41,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
*/
|
||||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
public class LazyOptional<T>
|
||||
{
|
||||
public class LazyOptional<T> {
|
||||
private final NonNullSupplier<T> supplier;
|
||||
private final Object lock = new Object();
|
||||
// null -> not resolved yet
|
||||
@@ -62,16 +62,14 @@ public class LazyOptional<T>
|
||||
* null, but can be null itself. If null, this method
|
||||
* returns {@link #empty()}.
|
||||
*/
|
||||
public static <T> LazyOptional<T> of(final @Nullable NonNullSupplier<T> instanceSupplier)
|
||||
{
|
||||
public static <T> LazyOptional<T> of(final @Nullable NonNullSupplier<T> instanceSupplier) {
|
||||
return instanceSupplier == null ? empty() : new LazyOptional<>(instanceSupplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The singleton empty instance
|
||||
*/
|
||||
public static <T> LazyOptional<T> empty()
|
||||
{
|
||||
public static <T> LazyOptional<T> empty() {
|
||||
return EMPTY.cast();
|
||||
}
|
||||
|
||||
@@ -83,27 +81,21 @@ public class LazyOptional<T>
|
||||
* @return This {@link LazyOptional}, cast to the inferred generic type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> LazyOptional<X> cast()
|
||||
{
|
||||
public <X> LazyOptional<X> cast() {
|
||||
return (LazyOptional<X>)this;
|
||||
}
|
||||
|
||||
private LazyOptional(@Nullable NonNullSupplier<T> instanceSupplier)
|
||||
{
|
||||
private LazyOptional(@Nullable NonNullSupplier<T> instanceSupplier) {
|
||||
this.supplier = instanceSupplier;
|
||||
}
|
||||
|
||||
private @Nullable T getValue()
|
||||
{
|
||||
private @Nullable T getValue() {
|
||||
if (!isValid || supplier == null)
|
||||
return null;
|
||||
if (resolved == null)
|
||||
{
|
||||
synchronized (lock)
|
||||
{
|
||||
if (resolved == null) {
|
||||
synchronized (lock) {
|
||||
// resolved == null: Double checked locking to prevent two threads from resolving
|
||||
if (resolved == null)
|
||||
{
|
||||
if (resolved == null) {
|
||||
T temp = supplier.get();
|
||||
if (temp == null)
|
||||
LOGGER.catching(Level.WARN, new NullPointerException("Supplier should not return null value"));
|
||||
@@ -114,13 +106,10 @@ public class LazyOptional<T>
|
||||
return resolved.getValue();
|
||||
}
|
||||
|
||||
private T getValueUnsafe()
|
||||
{
|
||||
private T getValueUnsafe() {
|
||||
T ret = getValue();
|
||||
if (ret == null)
|
||||
{
|
||||
throw new IllegalStateException("LazyOptional is empty or otherwise returned null from getValue() unexpectedly");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -130,8 +119,7 @@ public class LazyOptional<T>
|
||||
* @return {@code true} if this {@link LazyOptional} is non-empty, i.e. holds a
|
||||
* non-null supplier
|
||||
*/
|
||||
public boolean isPresent()
|
||||
{
|
||||
public boolean isPresent() {
|
||||
return supplier != null && isValid;
|
||||
}
|
||||
|
||||
@@ -142,8 +130,7 @@ public class LazyOptional<T>
|
||||
* @param consumer The {@link NonNullConsumer} to run if this optional is non-empty.
|
||||
* @throws NullPointerException if {@code consumer} is null and this {@link LazyOptional} is non-empty
|
||||
*/
|
||||
public void ifPresent(NonNullConsumer<? super T> consumer)
|
||||
{
|
||||
public void ifPresent(NonNullConsumer<? super T> consumer) {
|
||||
Objects.requireNonNull(consumer);
|
||||
T val = getValue();
|
||||
if (isValid && val != null)
|
||||
@@ -169,8 +156,7 @@ public class LazyOptional<T>
|
||||
* present, otherwise an empty {@link LazyOptional}
|
||||
* @throws NullPointerException if {@code mapper} is null.
|
||||
*/
|
||||
public <U> LazyOptional<U> lazyMap(NonNullFunction<? super T, ? extends U> mapper)
|
||||
{
|
||||
public <U> LazyOptional<U> lazyMap(NonNullFunction<? super T, ? extends U> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
return isPresent() ? of(() -> mapper.apply(getValueUnsafe())) : empty();
|
||||
}
|
||||
@@ -189,8 +175,7 @@ public class LazyOptional<T>
|
||||
* present, otherwise an empty {@link Optional}
|
||||
* @throws NullPointerException if {@code mapper} is null.
|
||||
*/
|
||||
public <U> Optional<U> map(NonNullFunction<? super T, ? extends U> mapper)
|
||||
{
|
||||
public <U> Optional<U> map(NonNullFunction<? super T, ? extends U> mapper) {
|
||||
Objects.requireNonNull(mapper);
|
||||
return isPresent() ? Optional.of(mapper.apply(getValueUnsafe())) : Optional.empty();
|
||||
}
|
||||
@@ -211,8 +196,7 @@ public class LazyOptional<T>
|
||||
* @throws NullPointerException If {@code predicate} is null and this
|
||||
* {@link Optional} is non-empty
|
||||
*/
|
||||
public Optional<T> filter(NonNullPredicate<? super T> predicate)
|
||||
{
|
||||
public Optional<T> filter(NonNullPredicate<? super T> predicate) {
|
||||
Objects.requireNonNull(predicate);
|
||||
final T value = getValue(); // To keep the non-null contract we have to evaluate right now. Should we allow this function at all?
|
||||
return value != null && predicate.test(value) ? Optional.of(value) : Optional.empty();
|
||||
@@ -222,8 +206,7 @@ public class LazyOptional<T>
|
||||
* Resolves the value of this LazyOptional, turning it into a standard non-lazy {@link Optional<T>}
|
||||
* @return The resolved optional.
|
||||
*/
|
||||
public Optional<T> resolve()
|
||||
{
|
||||
public Optional<T> resolve() {
|
||||
return isPresent() ? Optional.of(getValueUnsafe()) : Optional.empty();
|
||||
}
|
||||
|
||||
@@ -234,8 +217,7 @@ public class LazyOptional<T>
|
||||
* @param other the value to be returned if this {@link LazyOptional} is empty
|
||||
* @return the result of the supplier, if non-empty, otherwise {@code other}
|
||||
*/
|
||||
public T orElse(T other)
|
||||
{
|
||||
public T orElse(T other) {
|
||||
T val = getValue();
|
||||
return val != null ? val : other;
|
||||
}
|
||||
@@ -251,8 +233,7 @@ public class LazyOptional<T>
|
||||
* @throws NullPointerException If {@code other} is null and this
|
||||
* {@link LazyOptional} is non-empty
|
||||
*/
|
||||
public T orElseGet(NonNullSupplier<? extends T> other)
|
||||
{
|
||||
public T orElseGet(NonNullSupplier<? extends T> other) {
|
||||
T val = getValue();
|
||||
return val != null ? val : other.get();
|
||||
}
|
||||
@@ -273,8 +254,7 @@ public class LazyOptional<T>
|
||||
* @throws NullPointerException If {@code exceptionSupplier} is null and this
|
||||
* {@link LazyOptional} is empty
|
||||
*/
|
||||
public <X extends Throwable> T orElseThrow(NonNullSupplier<? extends X> exceptionSupplier) throws X
|
||||
{
|
||||
public <X extends Throwable> T orElseThrow(NonNullSupplier<? extends X> exceptionSupplier) throws X {
|
||||
T val = getValue();
|
||||
if (val != null)
|
||||
return val;
|
||||
@@ -286,16 +266,19 @@ public class LazyOptional<T>
|
||||
* <p>
|
||||
* If this {@link LazyOptional} is empty, the listener will be called immediately.
|
||||
*/
|
||||
public void addListener(NonNullConsumer<LazyOptional<T>> listener)
|
||||
{
|
||||
public void addListener(NonNullConsumer<LazyOptional<T>> listener) {
|
||||
if (isPresent())
|
||||
{
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
else
|
||||
{
|
||||
listener.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a {@link NonNullConsumer listener} from the list to be notified when this {@link LazyOptional} becomes invalid (via {@link #invalidate()}).<br>
|
||||
* This allows modder who know they will not need to be notified, to remove the hard reference that this holds to their listener.
|
||||
*/
|
||||
public void removeListener(NonNullConsumer<LazyOptional<T>> listener) {
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,12 +295,11 @@ public class LazyOptional<T>
|
||||
* etc... This allows modders to keep a cache of capability objects instead of
|
||||
* re-checking them every tick.
|
||||
*/
|
||||
public void invalidate()
|
||||
{
|
||||
if (this.isValid)
|
||||
{
|
||||
public void invalidate() {
|
||||
if (this.isValid) {
|
||||
this.isValid = false;
|
||||
this.listeners.forEach(e -> e.accept(this));
|
||||
this.listeners.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.energy;
|
||||
|
||||
/**
|
||||
* Implementation of {@link IEnergyStorage} that cannot store, receive, or provide energy.
|
||||
* Use the {@link #INSTANCE}, don't instantiate. Example:
|
||||
* <pre>{@code
|
||||
* ItemStack stack = ...;
|
||||
* IEnergyStorage storage = stack.getCapability(ForgeCapabilities.ENERGY).orElse(EmptyEnergyStorage.INSTANCE);
|
||||
* // Use storage without checking whether it's present.
|
||||
* }</pre>
|
||||
*/
|
||||
public class EmptyEnergyStorage implements IEnergyStorage
|
||||
{
|
||||
public static final EmptyEnergyStorage INSTANCE = new EmptyEnergyStorage();
|
||||
|
||||
protected EmptyEnergyStorage() {}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.entity.projectile.Projectile;
|
||||
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
|
||||
import net.minecraft.world.level.LevelSimulatedReader;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
@@ -39,13 +40,13 @@ import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.entity.SpawnGroupData;
|
||||
import net.minecraft.world.entity.SpawnPlacements;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.LightningBolt;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
@@ -128,6 +129,7 @@ import net.minecraftforge.event.entity.player.PlayerWakeUpEvent;
|
||||
import net.minecraftforge.event.entity.player.SleepingLocationCheckEvent;
|
||||
import net.minecraftforge.event.entity.player.SleepingTimeCheckEvent;
|
||||
import net.minecraftforge.event.furnace.FurnaceFuelBurnTimeEvent;
|
||||
import net.minecraftforge.event.level.AlterGroundEvent;
|
||||
import net.minecraftforge.event.level.BlockEvent;
|
||||
import net.minecraftforge.event.level.BlockEvent.BlockToolModificationEvent;
|
||||
import net.minecraftforge.event.level.BlockEvent.CreateFluidSourceEvent;
|
||||
@@ -269,7 +271,7 @@ public class ForgeEventFactory
|
||||
* @see MobSpawnEvent.FinalizeSpawn
|
||||
* @see Mob#finalizeSpawn(ServerLevelAccessor, DifficultyInstance, MobSpawnType, SpawnGroupData, CompoundTag)
|
||||
* @apiNote Callers do not need to check if the entity's spawn was cancelled, as the spawn will be blocked by Forge.
|
||||
* @implNote Changes to the signature of this method must be reflected in the method redirector coremod.
|
||||
* @implNote Changes to the signature of this method must be reflected in the method redirector coremod.
|
||||
*/
|
||||
@Nullable
|
||||
@SuppressWarnings("deprecation") // Call to deprecated Mob#finalizeSpawn is expected.
|
||||
@@ -667,9 +669,20 @@ public class ForgeEventFactory
|
||||
return event.getCharge();
|
||||
}
|
||||
|
||||
public static ProjectileImpactEvent.ImpactResult onProjectileImpactResult(Projectile projectile, HitResult ray)
|
||||
{
|
||||
ProjectileImpactEvent event = new ProjectileImpactEvent(projectile, ray);
|
||||
|
||||
// Remove this when the event is no longer cancelable
|
||||
if (MinecraftForge.EVENT_BUS.post(event))
|
||||
return ProjectileImpactEvent.ImpactResult.SKIP_ENTITY;
|
||||
|
||||
return event.getImpactResult();
|
||||
}
|
||||
|
||||
public static boolean onProjectileImpact(Projectile projectile, HitResult ray)
|
||||
{
|
||||
return MinecraftForge.EVENT_BUS.post(new ProjectileImpactEvent(projectile, ray));
|
||||
return onProjectileImpactResult(projectile, ray) != ProjectileImpactEvent.ImpactResult.DEFAULT;
|
||||
}
|
||||
|
||||
public static LootTable loadLootTable(ResourceLocation name, LootTable table)
|
||||
@@ -726,6 +739,13 @@ public class ForgeEventFactory
|
||||
return event;
|
||||
}
|
||||
|
||||
public static BlockState alterGround(LevelSimulatedReader level, RandomSource random, BlockPos pos, BlockState altered)
|
||||
{
|
||||
AlterGroundEvent event = new AlterGroundEvent(level, random, pos, altered);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
return event.getNewAlteredState();
|
||||
}
|
||||
|
||||
public static void fireChunkTicketLevelUpdated(ServerLevel level, long chunkPos, int oldTicketLevel, int newTicketLevel, @Nullable ChunkHolder chunkHolder)
|
||||
{
|
||||
if (oldTicketLevel != newTicketLevel)
|
||||
@@ -772,16 +792,18 @@ public class ForgeEventFactory
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Remove Entity Eye/Size hooks, as they need to be redesigned
|
||||
public static net.minecraftforge.event.entity.EntityEvent.Size getEntitySizeForge(Entity entity, Pose pose, EntityDimensions size, float eyeHeight)
|
||||
{
|
||||
EntityEvent.Size evt = new EntityEvent.Size(entity, pose, size, eyeHeight);
|
||||
var evt = new EntityEvent.Size(entity, pose, size, eyeHeight);
|
||||
MinecraftForge.EVENT_BUS.post(evt);
|
||||
return evt;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Remove Entity Eye/Size hooks, as they need to be redesigned
|
||||
public static net.minecraftforge.event.entity.EntityEvent.Size getEntitySizeForge(Entity entity, Pose pose, EntityDimensions oldSize, EntityDimensions newSize, float newEyeHeight)
|
||||
{
|
||||
EntityEvent.Size evt = new EntityEvent.Size(entity, pose, oldSize, newSize, entity.getEyeHeight(), newEyeHeight);
|
||||
var evt = new EntityEvent.Size(entity, pose, oldSize, newSize, entity.getEyeHeight(), newEyeHeight);
|
||||
MinecraftForge.EVENT_BUS.post(evt);
|
||||
return evt;
|
||||
}
|
||||
|
||||
@@ -14,8 +14,7 @@ import net.minecraftforge.eventbus.api.Event;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* Fired for registering structure conversions for pre-1.18.2 worlds. This is used by {@link StructuresBecomeConfiguredFix}
|
||||
@@ -92,11 +91,11 @@ public class RegisterStructureConversionsEvent extends Event
|
||||
*/
|
||||
public void register(String oldStructureID, StructuresBecomeConfiguredFix.Conversion conversion)
|
||||
{
|
||||
checkNotNull(oldStructureID, "Original structure ID must not be null");
|
||||
checkArgument(oldStructureID.toLowerCase(Locale.ROOT).equals(oldStructureID),
|
||||
Preconditions.checkNotNull(oldStructureID, "Original structure ID must not be null");
|
||||
Preconditions.checkArgument(oldStructureID.toLowerCase(Locale.ROOT).equals(oldStructureID),
|
||||
"Original structure ID should be in all lowercase");
|
||||
checkNotNull(conversion, "Structure conversion must not be null");
|
||||
checkNotNull(conversion.fallback(), "Fallback structure ID in structure conversion must not be null");
|
||||
Preconditions.checkNotNull(conversion, "Structure conversion must not be null");
|
||||
Preconditions.checkNotNull(conversion.fallback(), "Fallback structure ID in structure conversion must not be null");
|
||||
if (map.putIfAbsent(oldStructureID.toLowerCase(Locale.ROOT), conversion) != null)
|
||||
{
|
||||
throw new IllegalArgumentException("Conversion has already been registered for structure " + oldStructureID);
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.extensions.IForgeEntity;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
@@ -127,8 +128,7 @@ public class EntityEvent extends Event
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired whenever the {@link Pose} changes, and in a few other hardcoded scenarios.<br>
|
||||
* CAREFUL: This is also fired in the Entity constructor. Therefore the entity(subclass) might not be fully initialized. Check Entity#isAddedToWorld() or !Entity#firstUpdate.<br>
|
||||
* CAREFUL: This is also fired in the Entity constructor. Therefore, the entity (subclass) might not be fully initialized. Check {@link Entity#isAddedToWorld()} or {@code !Entity.firstUpdate}.<br>
|
||||
* If you change the player's size, you probably want to set the eye height accordingly as well<br>
|
||||
* <br>
|
||||
* This event is not {@link Cancelable}.<br>
|
||||
@@ -137,51 +137,70 @@ public class EntityEvent extends Event
|
||||
* <br>
|
||||
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.<br>
|
||||
**/
|
||||
public static class Size extends EntityEvent
|
||||
{
|
||||
@Deprecated(forRemoval = true, since = "1.20.1") // Remove Entity Eye/Size hooks, as they need to be redesigned
|
||||
public static class Size extends EntityEvent {
|
||||
private final Pose pose;
|
||||
private final EntityDimensions oldSize;
|
||||
private final EntityDimensions originalSize;
|
||||
private EntityDimensions newSize;
|
||||
private final float oldEyeHeight;
|
||||
private float newEyeHeight;
|
||||
|
||||
public Size(Entity entity, Pose pose, EntityDimensions size, float defaultEyeHeight)
|
||||
{
|
||||
public Size(Entity entity, Pose pose, EntityDimensions size) {
|
||||
this(entity, pose, size, 1.0f); // Eye height doesn't matter this is just for binary compatibility.
|
||||
}
|
||||
|
||||
public Size(Entity entity, Pose pose, EntityDimensions size, float defaultEyeHeight) {
|
||||
this(entity, pose, size, size, defaultEyeHeight, defaultEyeHeight);
|
||||
}
|
||||
|
||||
public Size(Entity entity, Pose pose, EntityDimensions oldSize, EntityDimensions newSize, float oldEyeHeight, float newEyeHeight)
|
||||
{
|
||||
public Size(Entity entity, Pose pose, EntityDimensions oldSize, EntityDimensions newSize, float oldEyeHeight, float newEyeHeight) {
|
||||
super(entity);
|
||||
this.pose = pose;
|
||||
this.oldSize = oldSize;
|
||||
this.originalSize = oldSize;
|
||||
this.newSize = newSize;
|
||||
this.oldEyeHeight = oldEyeHeight;
|
||||
this.newEyeHeight = newEyeHeight;
|
||||
}
|
||||
|
||||
|
||||
public Pose getPose() { return pose; }
|
||||
public EntityDimensions getOldSize() { return oldSize; }
|
||||
public EntityDimensions getOldSize() { return this.getOriginalSize(); }
|
||||
public EntityDimensions getOriginalSize() { return originalSize; }
|
||||
public EntityDimensions getNewSize() { return newSize; }
|
||||
public void setNewSize(EntityDimensions size)
|
||||
{
|
||||
setNewSize(size, false);
|
||||
}
|
||||
public void setNewSize(EntityDimensions size) { this.newSize = size; }
|
||||
|
||||
/**
|
||||
* Set the new size of the entity. Set updateEyeHeight to true to also update the eye height according to the new size.
|
||||
*/
|
||||
public void setNewSize(EntityDimensions size, boolean updateEyeHeight)
|
||||
{
|
||||
this.newSize = size;
|
||||
if (updateEyeHeight)
|
||||
{
|
||||
public void setNewSize(EntityDimensions size, boolean updateEyeHeight) {
|
||||
this.setNewSize(size);
|
||||
if (updateEyeHeight) {
|
||||
this.newEyeHeight = this.getEntity().getEyeHeightAccess(this.getPose(), this.newSize);
|
||||
}
|
||||
}
|
||||
public float getOldEyeHeight() { return oldEyeHeight; }
|
||||
public float getNewEyeHeight() { return newEyeHeight; }
|
||||
public void setNewEyeHeight(float newHeight) { this.newEyeHeight = newHeight; }
|
||||
public void setNewEyeHeight(float eyeHeight) { this.newEyeHeight = eyeHeight; }
|
||||
}
|
||||
|
||||
/**
|
||||
*Remove Entity Eye/Size hooks, as they need to be redesigned, this is no longer fired in any forge/vanilla code.
|
||||
**/
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
public static class EyeHeight extends EntityEvent {
|
||||
private final Pose pose;
|
||||
private final EntityDimensions size;
|
||||
private final float originalEyeHeight;
|
||||
private float newEyeHeight;
|
||||
|
||||
public EyeHeight(Entity entity, Pose pose, EntityDimensions size, float eyeHeight) {
|
||||
super(entity);
|
||||
this.pose = pose;
|
||||
this.size = size;
|
||||
this.originalEyeHeight = eyeHeight;
|
||||
this.newEyeHeight = eyeHeight;
|
||||
}
|
||||
|
||||
public Pose getPose() { return pose; }
|
||||
public EntityDimensions getSize() { return size; }
|
||||
public float getOriginalEyeHeight() { return originalEyeHeight; }
|
||||
public float getNewEyeHeight() { return newEyeHeight; }
|
||||
public void setNewEyeHeight(float newEyeHeight) { this.newEyeHeight = newEyeHeight; }
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,9 @@ import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.<br>
|
||||
@@ -19,6 +22,8 @@ import net.minecraftforge.eventbus.api.Cancelable;
|
||||
* custom projectiles should fire this event and check the result in a similar fashion.
|
||||
* This event is cancelable. When canceled, the impact will not be processed and the projectile will continue flying.
|
||||
* Killing or other handling of the entity after event cancellation is up to the modder.
|
||||
* You can also directly set the {@link ImpactResult} to change the impact behaviour.
|
||||
* @see #setImpactResult(ImpactResult)
|
||||
*/
|
||||
@Cancelable
|
||||
public class ProjectileImpactEvent extends EntityEvent
|
||||
@@ -26,6 +31,8 @@ public class ProjectileImpactEvent extends EntityEvent
|
||||
private final HitResult ray;
|
||||
private final Projectile projectile;
|
||||
|
||||
private ImpactResult result = ImpactResult.DEFAULT;
|
||||
|
||||
public ProjectileImpactEvent(Projectile projectile, HitResult ray)
|
||||
{
|
||||
super(projectile);
|
||||
@@ -33,6 +40,16 @@ public class ProjectileImpactEvent extends EntityEvent
|
||||
this.projectile = projectile;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @deprecated Use {@link #setImpactResult(ImpactResult)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
public void setCanceled(boolean cancel)
|
||||
{
|
||||
super.setCanceled(cancel);
|
||||
}
|
||||
|
||||
public HitResult getRayTraceResult()
|
||||
{
|
||||
return ray;
|
||||
@@ -42,4 +59,34 @@ public class ProjectileImpactEvent extends EntityEvent
|
||||
{
|
||||
return projectile;
|
||||
}
|
||||
|
||||
public void setImpactResult(@NotNull ImpactResult newResult)
|
||||
{
|
||||
this.result = Objects.requireNonNull(newResult, "ImpactResult cannot be null");
|
||||
}
|
||||
|
||||
public ImpactResult getImpactResult()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
public enum ImpactResult
|
||||
{
|
||||
/**
|
||||
* The default behaviour, the projectile will be destroyed and the hit will be processed.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* The projectile will pass through the current entity as if it wasn't there. This will return default behaviour if there is no entity.
|
||||
*/
|
||||
SKIP_ENTITY,
|
||||
/**
|
||||
* Damage the entity and stop the projectile here, the projectile will not pierce.
|
||||
*/
|
||||
STOP_AT_CURRENT,
|
||||
/**
|
||||
* Cancel the piercing aspect of the projectile, and do not damage the entity.
|
||||
*/
|
||||
STOP_AT_CURRENT_NO_DAMAGE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.event.entity.living;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
|
||||
/**
|
||||
* LivingBreatheEvent is fired whenever a living entity ticks.<br>
|
||||
* <br>
|
||||
* This event is fired via {@link ForgeHooks#onLivingBreathe(LivingEntity, int, int)}.<br>
|
||||
* <br>
|
||||
* This event is not {@link Cancelable}.<br>
|
||||
* <br>
|
||||
* This event does not have a result. {@link HasResult}
|
||||
* <br>
|
||||
* This event is fired on {@link MinecraftForge#EVENT_BUS}
|
||||
*/
|
||||
public class LivingBreatheEvent extends LivingEvent {
|
||||
private boolean canBreathe;
|
||||
private boolean canRefillAir;
|
||||
private int consumeAirAmount;
|
||||
private int refillAirAmount;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
public LivingBreatheEvent(LivingEntity entity, boolean canBreathe, int consumeAirAmount, int refillAirAmount) {
|
||||
this(entity, canBreathe, consumeAirAmount, refillAirAmount, canBreathe);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public LivingBreatheEvent(LivingEntity entity, boolean canBreathe, int consumeAirAmount, int refillAirAmount, boolean canRefillAir) {
|
||||
super(entity);
|
||||
this.canBreathe = canBreathe;
|
||||
this.canRefillAir = canRefillAir;
|
||||
this.consumeAirAmount = Math.max(consumeAirAmount, 0);
|
||||
this.refillAirAmount = Math.max(refillAirAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the entity can breathe and {@link #canRefillAir()} returns true, their air value will be increased by {@link #getRefillAirAmount()}.<br>
|
||||
* If the entity can breathe and {@link #canRefillAir()} returns false, their air value will stay the same.<br>
|
||||
* If the entity cannot breathe, their air value will be reduced by {@link #getConsumeAirAmount()}.
|
||||
* @return True if the entity can breathe
|
||||
*/
|
||||
public boolean canBreathe() {
|
||||
return canBreathe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the entity can breathe or not.
|
||||
* @param canBreathe The new value.
|
||||
*/
|
||||
public void setCanBreathe(boolean canBreathe) {
|
||||
this.canBreathe = canBreathe;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the entity can breathe, {@link #canRefillAir()} will be checked to see if their air value should be refilled.
|
||||
* @return True if the entity can refill its air value
|
||||
*/
|
||||
public boolean canRefillAir() {
|
||||
return canRefillAir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the entity can refill its air value or not.
|
||||
* @param canRefillAir The new value.
|
||||
*/
|
||||
public void setCanRefillAir(boolean canRefillAir) {
|
||||
this.canRefillAir = canRefillAir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The amount the entity's {@linkplain LivingEntity#getAirSupply() air supply} will be reduced by if the entity {@linkplain #canBreathe() cannot breathe}.
|
||||
*/
|
||||
public int getConsumeAirAmount() {
|
||||
return consumeAirAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new consumed air amount.
|
||||
* @param consumeAirAmount The new value.
|
||||
* @see #getConsumeAirAmount()
|
||||
*/
|
||||
public void setConsumeAirAmount(int consumeAirAmount) {
|
||||
this.consumeAirAmount = Math.max(consumeAirAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The amount the entity's {@linkplain LivingEntity#getAirSupply() air supply} will be increased by if the entity {@linkplain #canBreathe() can breathe}.
|
||||
*/
|
||||
public int getRefillAirAmount() {
|
||||
return refillAirAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new refilled air amount.
|
||||
*
|
||||
* @param refillAirAmount The new value.
|
||||
* @see #getRefillAirAmount()
|
||||
*/
|
||||
public void setRefillAirAmount(int refillAirAmount) {
|
||||
this.refillAirAmount = Math.max(refillAirAmount, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.event.entity.living;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.world.damagesource.DamageSources;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
|
||||
/**
|
||||
* LivingDrownEvent is fired whenever a living entity can't breathe and its air supply is less than or equal to zero.
|
||||
* <p>
|
||||
* This event is fired via {@link ForgeHooks#onLivingBreathe(LivingEntity, int, int)}.
|
||||
* <p>
|
||||
* This event is {@link Cancelable}. Effects of cancellation are noted in {@link #setCanceled(boolean)}.
|
||||
* <p>
|
||||
* This event does not {@linkplain HasResult have a result}.
|
||||
* This event is fired on {@link MinecraftForge#EVENT_BUS}
|
||||
**/
|
||||
@Cancelable
|
||||
public class LivingDrownEvent extends LivingEvent {
|
||||
private boolean isDrowning;
|
||||
private float damageAmount;
|
||||
private int bubbleCount;
|
||||
|
||||
/**
|
||||
* Constructs a new LivingDrownEvent.
|
||||
*
|
||||
* @param entity The entity that is drowning.
|
||||
* @param isDrowning If the entity is "actively" drowning, and would take damage.
|
||||
* @param damageAmount The amount of {@linkplain DamageSources#drown() drowning damage} the entity would take.
|
||||
* @param bubbleCount The number of {@linkplain ParticleTypes#BUBBLE} particles that will be spawned when actively drowning.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public LivingDrownEvent(LivingEntity entity, boolean isDrowning, float damageAmount, int bubbleCount) {
|
||||
super(entity);
|
||||
this.isDrowning = isDrowning;
|
||||
this.damageAmount = damageAmount;
|
||||
this.bubbleCount = bubbleCount;
|
||||
}
|
||||
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "1.20.1")
|
||||
public LivingDrownEvent(LivingEntity entity, boolean isDrowning) {
|
||||
this(entity, isDrowning, 2.0F, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns true if the entity is "actively" drowning.<br>
|
||||
* For most entities, this happens when their air supply reaches -20.<br>
|
||||
* When this is true, the entity will take damage, spawn particles, and reset their air supply to 0.
|
||||
*
|
||||
* @return If the entity is actively drowning.
|
||||
*/
|
||||
public boolean isDrowning() {
|
||||
return isDrowning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the entity is actively drowning.
|
||||
*
|
||||
* @param isDrowning The new value.
|
||||
* @see #isDrowning()
|
||||
*/
|
||||
public void setDrowning(boolean isDrowning) {
|
||||
this.isDrowning = isDrowning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of {@linkplain DamageSources#drown() drowning damage} the entity would take.<br>
|
||||
* Drowning damage is only inflicted if the entity is {@linkplain #isDrowning() actively drowning}.<br>
|
||||
* For vanilla entities, the default amount of damage is 2 (1 heart).
|
||||
* <p>
|
||||
* If the damage amount is less than or equal to zero, {@link Entity#hurt} will not be called.
|
||||
*
|
||||
* @return The amount of damage that will be dealt to the entity when actively drowning.
|
||||
*/
|
||||
public float getDamageAmount() {
|
||||
return damageAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of drowning damage that may be inflicted.
|
||||
*
|
||||
* @param damageAmount The new value.
|
||||
* @see #getDamageAmount()
|
||||
*/
|
||||
public void setDamageAmount(float damageAmount) {
|
||||
this.damageAmount = damageAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of {@linkplain ParticleTypes#BUBBLE} particles that would be spawned.<br>
|
||||
* Bubbles are only spawned if the entity is {@linkplain #isDrowning() actively drowning}.<br>
|
||||
* For vanilla entities, the default value is 8 particles.
|
||||
*
|
||||
* @return The number of bubble particles that will spawn when actively drowning.
|
||||
*/
|
||||
public int getBubbleCount() {
|
||||
return bubbleCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of bubbles that may be spawned.
|
||||
*
|
||||
* @param bubbleCount The new value.
|
||||
* @see #getBubbleCount()
|
||||
*/
|
||||
public void setBubbleCount(int bubbleCount) {
|
||||
this.bubbleCount = bubbleCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the drowning event.<br>
|
||||
* Cancellation is mostly equivalent to {@link #setDrowning(boolean)} with a value of false.<br>
|
||||
* However, this also incurs the usual side effects of cancellation.
|
||||
*/
|
||||
@Override
|
||||
public void setCanceled(boolean cancel) {
|
||||
super.setCanceled(cancel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.event.entity.living;
|
||||
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraftforge.common.ForgeHooks;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.BrainBuilder;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
|
||||
/**
|
||||
* LivingMakeBrainEvent is fired whenever a new {@link net.minecraft.world.entity.ai.Brain} instance is created using {@link LivingEntity#makeBrain(Dynamic)}.<br>
|
||||
* <br>
|
||||
* To access the internal {@link BrainBuilder}, call {@link LivingMakeBrainEvent#getTypedBrainBuilder(LivingEntity)} using the downcasted {@link LivingEntity} obtained from {@link LivingEvent#getEntity()}.<br>
|
||||
* <br>
|
||||
* The BrainBuilder will initially contain all the state found in the original Brain instance.<br>
|
||||
* <br>
|
||||
* After this event is posted, a fresh Brain instance will be created using the encapsulated state found in the BrainBuilder
|
||||
* and replace the previously created Brain instance for the entity.<br>
|
||||
* <br>
|
||||
* This event is fired via the {@link ForgeHooks#onLivingMakeBrain(LivingEntity, Brain, Dynamic)}.<br>
|
||||
* <br>
|
||||
* This event is not {@link Cancelable}.<br>
|
||||
* <br>
|
||||
* This event does not have a result. {@link HasResult}<br>
|
||||
* <br>
|
||||
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.
|
||||
**/
|
||||
public class LivingMakeBrainEvent extends LivingEvent
|
||||
{
|
||||
private final BrainBuilder<?> brainBuilder;
|
||||
|
||||
public LivingMakeBrainEvent(LivingEntity entity, BrainBuilder<?> brainBuilder)
|
||||
{
|
||||
super(entity);
|
||||
this.brainBuilder = brainBuilder;
|
||||
}
|
||||
|
||||
public <E extends LivingEntity> BrainBuilder<E> getTypedBrainBuilder(E ignoredEntity)
|
||||
{
|
||||
return (BrainBuilder<E>) this.brainBuilder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.event.entity.living;
|
||||
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
public class LivingSwapItemsEvent extends LivingEvent
|
||||
{
|
||||
|
||||
@ApiStatus.Internal
|
||||
public LivingSwapItemsEvent(LivingEntity entity)
|
||||
{
|
||||
super(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when a living entity is about to swap the items in their main and offhand.
|
||||
* This event is executed in {@link ServerGamePacketListenerImpl#handlePlayerAction}
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class Hands extends LivingSwapItemsEvent
|
||||
{
|
||||
private ItemStack toMainHand;
|
||||
private ItemStack toOffHand;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public Hands(LivingEntity entity)
|
||||
{
|
||||
super(entity);
|
||||
this.toMainHand = entity.getOffhandItem(); //the main hand will be swapped with the offhand
|
||||
this.toOffHand = entity.getMainHandItem(); //the offhand will be swapped with the main hand
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item that will be swapped to the main hand of the entity.
|
||||
* @return The item that will be swapped to the main hand.
|
||||
*/
|
||||
public ItemStack getItemSwappedToMainHand()
|
||||
{
|
||||
return toMainHand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item that will be swapped to the offhand of the entity.
|
||||
* @return The item that will be swapped to the offhand.
|
||||
*/
|
||||
public ItemStack getItemSwappedToOffHand()
|
||||
{
|
||||
return toOffHand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item that will be swapped to the main hand of the entity.
|
||||
* @param item The item to swap to the main hand.
|
||||
*/
|
||||
public void setItemSwappedToMainHand(ItemStack item)
|
||||
{
|
||||
this.toMainHand = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item that will be swapped to the offhand of the entity.
|
||||
* @param item The item to swap to the offhand.
|
||||
*/
|
||||
public void setItemSwappedToOffHand(ItemStack item)
|
||||
{
|
||||
this.toOffHand = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 136 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user