mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 09:05:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc2d0d1b25 | ||
|
|
e2c1da98be | ||
|
|
0f6d11b1ee | ||
|
|
340d332e19 | ||
|
|
56f19dd53d | ||
|
|
1fe420e4ab | ||
|
|
945209c283 | ||
|
|
3e5c3cabd5 | ||
|
|
b0f5a13f52 | ||
|
|
15fe8441f0 | ||
|
|
babef71616 | ||
|
|
1dd18ca27c | ||
|
|
65c7390874 | ||
|
|
fe3ad3b8f2 | ||
|
|
d05e76f7c4 | ||
|
|
bfa97bf097 | ||
|
|
469e9a6c1a | ||
|
|
58456c85af | ||
|
|
7fe5b02ef3 | ||
|
|
184392e02e | ||
|
|
d25a5466db | ||
|
|
b5073c10ef | ||
|
|
16bc7cf783 | ||
|
|
2d714f034f |
No files matched your search
+9
-1
@@ -47,7 +47,7 @@ ext {
|
||||
MODLAUNCHER_VERSION = '10.0.8'
|
||||
SECUREJARHANDLER_VERSION = '2.1.4'
|
||||
BOOTSTRAPLAUNCHER_VERSION = '1.1.2'
|
||||
ASM_VERSION = '9.3'
|
||||
ASM_VERSION = '9.5'
|
||||
INSTALLER_VERSION = '2.1.+'
|
||||
MIXIN_VERSION = '0.8.5'
|
||||
TERMINALCONSOLEAPPENDER_VERSION = '1.2.0'
|
||||
@@ -1241,6 +1241,14 @@ project(':forge') {
|
||||
dependsOn 'setupCheckJarCompatibility'
|
||||
|
||||
baseJar = project.tasks.named('mergeBaseForgeJar').flatMap { it.output }
|
||||
baseLibraries.from(project.tasks.named('createJoinedSRG').flatMap { it.output })
|
||||
|
||||
inputJar = project.tasks.named('reobfJar').flatMap { it.output }
|
||||
concreteLibraries.from(project.PACKED_DEPS.collect { project.rootProject.tasks.getByPath(it).archiveFile })
|
||||
|
||||
commonLibraries.from(project.configurations.minecraftImplementation)
|
||||
commonLibraries.from(project.configurations.installer)
|
||||
commonLibraries.from(project.configurations.moduleonly)
|
||||
}
|
||||
|
||||
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs, findFieldInstanceChecks, checkPatches, checkLicenses]){}
|
||||
|
||||
@@ -4,8 +4,8 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.ow2.asm:asm:9.3'
|
||||
implementation 'org.ow2.asm:asm-tree:9.3'
|
||||
implementation 'net.minecraftforge:srgutils:0.4.+'
|
||||
implementation 'org.ow2.asm:asm:9.5'
|
||||
implementation 'org.ow2.asm:asm-tree:9.5'
|
||||
implementation 'net.minecraftforge:srgutils:0.5.+'
|
||||
implementation 'commons-io:commons-io:2.8.0'
|
||||
}
|
||||
+1
-8
@@ -18,6 +18,7 @@ abstract class SetupCheckJarCompatibility extends DefaultTask {
|
||||
onlyIf {
|
||||
inputVersion.getOrNull() != null
|
||||
}
|
||||
outputs.upToDateWhen { false } // Never up to date, because this setup task should always run
|
||||
|
||||
baseBinPatchesOutput.convention(project.layout.buildDirectory.dir(name).map { it.file('joined.lzma') })
|
||||
}
|
||||
@@ -31,17 +32,9 @@ abstract class SetupCheckJarCompatibility extends DefaultTask {
|
||||
}.toArray(Dependency[]::new))
|
||||
|
||||
project.tasks.named('checkJarCompatibility') {
|
||||
baseLibraries.from(project.tasks.createJoinedSRG.output)
|
||||
baseLibraries.from(project.provider {
|
||||
fmlLibs.resolvedConfiguration.lenientConfiguration.files
|
||||
})
|
||||
|
||||
inputJar = project.tasks.reobfJar.output
|
||||
concreteLibraries.from(project.PACKED_DEPS.collect { project.rootProject.tasks.getByPath(it).archiveFile })
|
||||
|
||||
commonLibraries.from(project.configurations.minecraftImplementation)
|
||||
commonLibraries.from(project.configurations.installer)
|
||||
commonLibraries.from(project.configurations.moduleonly)
|
||||
}
|
||||
|
||||
def baseForgeUserdev = project.layout.buildDirectory.dir(name).map { it.file("forge-${inputVersion}-userdev.jar") }.get().asFile
|
||||
|
||||
+3
-2
@@ -10,8 +10,9 @@ Forge is a free, open-source modding API all of your favourite mods use!
|
||||
|
||||
| Version | Support |
|
||||
|---------| ------------- |
|
||||
| 1.19.x | Active |
|
||||
| 1.18.x | LTS |
|
||||
| 1.20.x | Active |
|
||||
| 1.19.4 | Legacy |
|
||||
| 1.19.2 | Legacy |
|
||||
|
||||
* [Download]
|
||||
* [Forum]
|
||||
|
||||
@@ -11,11 +11,17 @@ import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.*;
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
|
||||
|
||||
public class UniqueModListBuilder
|
||||
{
|
||||
@@ -66,28 +72,34 @@ public class UniqueModListBuilder
|
||||
|
||||
// Its theoretically possible that some mod has somehow moved an id to a secondary place, thus causing a dupe.
|
||||
// We can't handle this
|
||||
final List<IModInfo> dupedMods = modIds.values().stream()
|
||||
final List<String> dupedModErrors = modIds.values().stream()
|
||||
.filter(modInfos -> modInfos.size() > 1)
|
||||
.map(modInfos -> modInfos.get(0))
|
||||
.toList();
|
||||
.map(mods -> String.format("\tMod ID: '%s' from mod files: %s",
|
||||
mods.get(0).getModId(),
|
||||
mods.stream()
|
||||
.map(modInfo -> modInfo.getOwningFile().getFile().getFileName()).collect(joining(", "))
|
||||
)).toList();
|
||||
|
||||
if (!dupedMods.isEmpty()) {
|
||||
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods.stream()
|
||||
.map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod", dm, Objects.toString(dm)))
|
||||
.toList();
|
||||
throw new EarlyLoadingException("Duplicate mods found", null, duplicateModErrors);
|
||||
if (!dupedModErrors.isEmpty()) {
|
||||
LOGGER.error(LOADING, "Found duplicate mods:\n{}", dupedModErrors.stream().collect(joining("\n")));
|
||||
throw new EarlyLoadingException("Duplicate mods found", null, dupedModErrors.stream()
|
||||
.map(s -> new EarlyLoadingException.ExceptionData(s))
|
||||
.toList());
|
||||
}
|
||||
|
||||
final List<ModFile> dupedLibs = versionedLibIds.values().stream()
|
||||
final List<String> dupedLibErrors = versionedLibIds.values().stream()
|
||||
.filter(modFiles -> modFiles.size() > 1)
|
||||
.map(modFiles -> modFiles.get(0))
|
||||
.toList();
|
||||
.map(mods -> String.format("\tLibrary: '%s' from files: %s",
|
||||
getModId(mods.get(0)),
|
||||
mods.stream()
|
||||
.map(modFile -> modFile.getFileName()).collect(joining(", "))
|
||||
)).toList();
|
||||
|
||||
if (!dupedLibs.isEmpty()) {
|
||||
final List<EarlyLoadingException.ExceptionData> duplicateLibErrors = dupedLibs.stream()
|
||||
.map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedlib.versioned", dm, Objects.toString(dm)))
|
||||
.toList();
|
||||
throw new EarlyLoadingException("Duplicate plugins or libraries found", null, duplicateLibErrors);
|
||||
if (!dupedLibErrors.isEmpty()) {
|
||||
LOGGER.error(LOADING, "Found duplicate plugins or libraries:\n{}", dupedLibErrors.stream().collect(joining("\n")));
|
||||
throw new EarlyLoadingException("Duplicate plugins or libraries found", null, dupedLibErrors.stream()
|
||||
.map(s -> new EarlyLoadingException.ExceptionData(s))
|
||||
.toList());
|
||||
}
|
||||
|
||||
// Collect unique mod files by module name. This will be used for deduping purposes
|
||||
|
||||
@@ -342,6 +342,22 @@
|
||||
this.f_91026_.m_6180_("gui");
|
||||
this.f_240378_.m_240688_();
|
||||
this.f_91065_.m_193832_(this.f_91012_);
|
||||
@@ -1749,6 +_,7 @@
|
||||
|
||||
this.f_91005_.m_120596_();
|
||||
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPreLevelTick(this.f_91073_, () -> true);
|
||||
try {
|
||||
this.f_91073_.m_104726_(() -> {
|
||||
return true;
|
||||
@@ -1764,6 +_,7 @@
|
||||
|
||||
throw new ReportedException(crashreport);
|
||||
}
|
||||
+ net.minecraftforge.event.ForgeEventFactory.onPostLevelTick(this.f_91073_, () -> true);
|
||||
}
|
||||
|
||||
this.f_91026_.m_6182_("animateTick");
|
||||
@@ -1783,6 +_,8 @@
|
||||
this.f_91026_.m_6182_("keyboard");
|
||||
this.f_91068_.m_90931_();
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
--- a/net/minecraft/client/gui/screens/ConnectScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/ConnectScreen.java
|
||||
@@ -73,6 +_,8 @@
|
||||
}
|
||||
|
||||
if (!optional.isPresent()) {
|
||||
+ ConnectScreen.f_95683_.error("Couldn't connect to server: Unknown host \"{}\"", p_169266_.m_171863_());
|
||||
+ net.minecraftforge.network.DualStackUtils.logInitialPreferences();
|
||||
p_169265_.execute(() -> {
|
||||
p_169265_.m_91152_(new DisconnectedScreen(ConnectScreen.this.f_95686_, CommonComponents.f_130661_, ConnectScreen.f_169260_));
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
+++ b/net/minecraft/client/gui/screens/PauseScreen.java
|
||||
@@ -77,9 +_,10 @@
|
||||
this.f_96541_.m_91152_(new SocialInteractionsScreen());
|
||||
}));
|
||||
}
|
||||
+ this.m_142416_(new Button(this.f_96543_ / 2 - 102, this.f_96544_ / 4 + 120 - 16, 204, 20, Component.m_237115_("fml.menu.mods"), modButton -> this.f_96541_.m_91152_(new net.minecraftforge.client.gui.ModListScreen(this))));
|
||||
|
||||
Component component = this.f_96541_.m_91090_() ? Component.m_237115_("menu.returnToMenu") : Component.m_237115_("menu.disconnect");
|
||||
- this.m_142416_(new Button(this.f_96543_ / 2 - 102, this.f_96544_ / 4 + 120 + -16, 204, 20, component, (p_96315_) -> {
|
||||
+ this.m_142416_(new Button(this.f_96543_ / 2 - 102, this.f_96544_ / 4 + 144 + -16, 204, 20, component, (p_96315_) -> {
|
||||
boolean flag = this.f_96541_.m_91090_();
|
||||
boolean flag1 = this.f_96541_.m_91294_();
|
||||
p_96315_.f_93623_ = false;
|
||||
@@ -30,3 +30,12 @@
|
||||
this.m_241119_(p_241518_, p_241542_.m_237220_());
|
||||
this.m_240498_(p_241510_, p_241542_.m_241109_());
|
||||
this.f_240659_ = Util.m_137550_();
|
||||
@@ -263,6 +_,8 @@
|
||||
|
||||
public void m_240494_(Component p_240522_, boolean p_240642_) {
|
||||
if (!this.f_240348_.f_91066_.m_231833_().m_231551_() || !this.f_240348_.m_91246_(this.m_240473_(p_240522_))) {
|
||||
+ p_240522_ = net.minecraftforge.client.ForgeHooksClient.onClientSystemChat(p_240522_, p_240642_);
|
||||
+ if (p_240522_ == null) return;
|
||||
if (p_240642_) {
|
||||
this.f_240348_.f_91065_.m_93063_(p_240522_, false);
|
||||
} else {
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
--- a/net/minecraft/client/renderer/block/model/ItemModelGenerator.java
|
||||
+++ b/net/minecraft/client/renderer/block/model/ItemModelGenerator.java
|
||||
@@ -39,6 +_,7 @@
|
||||
@@ -39,6 +_,8 @@
|
||||
map.put("particle", p_111672_.m_111477_("particle") ? Either.left(p_111672_.m_111480_("particle")) : map.get("layer0"));
|
||||
BlockModel blockmodel = new BlockModel((ResourceLocation)null, list, map, false, p_111672_.m_111479_(), p_111672_.m_111491_(), p_111672_.m_111484_());
|
||||
blockmodel.f_111416_ = p_111672_.f_111416_;
|
||||
+ blockmodel.customData.copyFrom(p_111672_.customData);
|
||||
+ blockmodel.customData.setGui3d(false);
|
||||
return blockmodel;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -343,7 +_,7 @@
|
||||
DispensibleContainerItem dispensiblecontaineritem = (DispensibleContainerItem)p_123562_.m_41720_();
|
||||
BlockPos blockpos = p_123561_.m_7961_().m_121945_(p_123561_.m_6414_().m_61143_(DispenserBlock.f_52659_));
|
||||
Level level = p_123561_.m_7727_();
|
||||
- if (dispensiblecontaineritem.m_142073_((Player)null, level, blockpos, (BlockHitResult)null)) {
|
||||
+ if (dispensiblecontaineritem.emptyContents((Player)null, level, blockpos, (BlockHitResult)null, p_123562_)) {
|
||||
dispensiblecontaineritem.m_142131_((Player)null, level, p_123562_, blockpos);
|
||||
return new ItemStack(Items.f_42446_);
|
||||
} else {
|
||||
@@ -402,9 +_,10 @@
|
||||
level.m_46597_(blockpos, BaseFireBlock.m_49245_(level, blockpos));
|
||||
level.m_142346_((Entity)null, GameEvent.f_157797_, blockpos);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/server/commands/SummonCommand.java
|
||||
+++ b/net/minecraft/server/commands/SummonCommand.java
|
||||
@@ -55,6 +_,7 @@
|
||||
throw f_138810_.create();
|
||||
} else {
|
||||
if (p_138825_ && entity instanceof Mob) {
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn((Mob)entity, p_138821_.m_81372_(), (float)entity.m_20185_(), (float)entity.m_20186_(), (float)entity.m_20189_(), null, MobSpawnType.COMMAND))
|
||||
((Mob)entity).m_6518_(p_138821_.m_81372_(), p_138821_.m_81372_().m_6436_(entity.m_20183_()), MobSpawnType.COMMAND, (SpawnGroupData)null, (CompoundTag)null);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
public PackRepository(Pack.PackConstructor p_10502_, RepositorySource... p_10503_) {
|
||||
this.f_10500_ = p_10502_;
|
||||
- this.f_10497_ = ImmutableSet.copyOf(p_10503_);
|
||||
+ this.f_10497_ = new java.util.HashSet<>(java.util.Arrays.asList(p_10503_));
|
||||
+ this.f_10497_ = new java.util.LinkedHashSet<>(List.of(p_10503_)); //Forge: This needs to be a mutable set, so that we can add to it later on.
|
||||
}
|
||||
|
||||
public PackRepository(PackType p_143890_, RepositorySource... p_143891_) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
--- a/net/minecraft/util/SpawnUtil.java
|
||||
+++ b/net/minecraft/util/SpawnUtil.java
|
||||
@@ -24,7 +_,8 @@
|
||||
if (p_216406_.m_6857_().m_61937_(blockpos$mutableblockpos) && m_216398_(p_216406_, p_216410_, blockpos$mutableblockpos, p_216411_)) {
|
||||
T t = p_216404_.m_20655_(p_216406_, (CompoundTag)null, (Component)null, (Player)null, blockpos$mutableblockpos, p_216405_, false, false);
|
||||
if (t != null) {
|
||||
- if (t.m_5545_(p_216406_, p_216405_) && t.m_6914_(p_216406_)) {
|
||||
+ int res = net.minecraftforge.common.ForgeHooks.canEntitySpawn(t, p_216406_, t.m_20185_(), t.m_20186_(), t.m_20189_(), null, p_216405_);
|
||||
+ if (res == 1 || (res == 0 && t.m_5545_(p_216406_, p_216405_) && t.m_6914_(p_216406_))) {
|
||||
p_216406_.m_47205_(t);
|
||||
return Optional.of(t);
|
||||
}
|
||||
@@ -33,14 +33,14 @@
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -326,6 +_,7 @@
|
||||
public T m_20600_(ServerLevel p_20601_, @Nullable CompoundTag p_20602_, @Nullable Component p_20603_, @Nullable Player p_20604_, BlockPos p_20605_, MobSpawnType p_20606_, boolean p_20607_, boolean p_20608_) {
|
||||
T t = this.m_20655_(p_20601_, p_20602_, p_20603_, p_20604_, p_20605_, p_20606_, p_20607_, p_20608_);
|
||||
if (t != null) {
|
||||
+ if (t instanceof net.minecraft.world.entity.Mob && net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn((net.minecraft.world.entity.Mob) t, p_20601_, p_20605_.m_123341_(), p_20605_.m_123342_(), p_20605_.m_123343_(), null, p_20606_)) return null;
|
||||
p_20601_.m_47205_(t);
|
||||
}
|
||||
|
||||
@@ -351,6 +_,7 @@
|
||||
Mob mob = (Mob)t;
|
||||
mob.f_20885_ = mob.m_146908_();
|
||||
mob.f_20883_ = mob.m_146908_();
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, p_20656_, (float) mob.m_20185_(), (float) mob.m_20186_(), (float) mob.m_20189_(), null, p_20661_))
|
||||
mob.m_6518_(p_20656_, p_20656_.m_6436_(mob.m_20183_()), p_20661_, (SpawnGroupData)null, p_20657_);
|
||||
mob.m_8032_();
|
||||
}
|
||||
@@ -543,14 +_,23 @@
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/Mob.java
|
||||
+++ b/net/minecraft/world/entity/Mob.java
|
||||
@@ -116,6 +_,8 @@
|
||||
private CompoundTag f_21359_;
|
||||
private BlockPos f_21360_ = BlockPos.f_121853_;
|
||||
private float f_21341_ = -1.0F;
|
||||
+ @Nullable
|
||||
+ private MobSpawnType spawnType;
|
||||
|
||||
protected Mob(EntityType<? extends Mob> p_21368_, Level p_21369_) {
|
||||
super(p_21368_, p_21369_);
|
||||
@@ -210,7 +_,11 @@
|
||||
}
|
||||
|
||||
@@ -13,6 +22,31 @@
|
||||
}
|
||||
|
||||
public boolean m_6549_(EntityType<?> p_21399_) {
|
||||
@@ -408,6 +_,9 @@
|
||||
p_21484_.m_128379_("NoAI", this.m_21525_());
|
||||
}
|
||||
|
||||
+ if (this.spawnType != null) {
|
||||
+ p_21484_.m_128359_("forge:spawn_type", this.spawnType.name());
|
||||
+ }
|
||||
}
|
||||
|
||||
public void m_7378_(CompoundTag p_21450_) {
|
||||
@@ -460,6 +_,14 @@
|
||||
}
|
||||
|
||||
this.m_21557_(p_21450_.m_128471_("NoAI"));
|
||||
+
|
||||
+ if (p_21450_.m_128441_("forge:spawn_type")) {
|
||||
+ try {
|
||||
+ this.spawnType = MobSpawnType.valueOf(p_21450_.m_128461_("forge:spawn_type"));
|
||||
+ } catch (Exception ex) {
|
||||
+ p_21450_.m_128473_("forge:spawn_type");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
protected void m_7625_(DamageSource p_21389_, boolean p_21390_) {
|
||||
@@ -499,9 +_,9 @@
|
||||
public void m_8107_() {
|
||||
super.m_8107_();
|
||||
@@ -39,7 +73,26 @@
|
||||
if (entity != null) {
|
||||
double d0 = entity.m_20280_(this);
|
||||
int i = this.m_6095_().m_20674_().m_21611_();
|
||||
@@ -1374,13 +_,23 @@
|
||||
@@ -990,6 +_,10 @@
|
||||
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * <p>Calls to this method should be accompanied by firing the {@link net.minecraftforge.event.entity.living.LivingSpawnEvent.SpecialSpawn SpecialSpawn} event via {@link net.minecraftforge.event.ForgeEventFactory#doSpecialSpawn}.</p>
|
||||
+ * Additionally, if you override this method, you should ensure you either call super, or manually set {@link #spawnType} from your override.
|
||||
+ */
|
||||
@Nullable
|
||||
public SpawnGroupData m_6518_(ServerLevelAccessor p_21434_, DifficultyInstance p_21435_, MobSpawnType p_21436_, @Nullable SpawnGroupData p_21437_, @Nullable CompoundTag p_21438_) {
|
||||
RandomSource randomsource = p_21434_.m_213780_();
|
||||
@@ -1000,6 +_,7 @@
|
||||
this.m_21559_(false);
|
||||
}
|
||||
|
||||
+ this.spawnType = p_21436_;
|
||||
return p_21437_;
|
||||
}
|
||||
|
||||
@@ -1374,15 +_,25 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -56,11 +109,30 @@
|
||||
this.m_20256_(this.m_20184_().m_82520_(0.0D, 0.3D, 0.0D));
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public void jumpInFluid(net.minecraftforge.fluids.FluidType type) {
|
||||
+ this.jumpInLiquidInternal(() -> super.jumpInFluid(type));
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
public void m_147272_() {
|
||||
this.f_21345_.m_148096_();
|
||||
this.m_6274_().m_147343_();
|
||||
@@ -1404,5 +_,16 @@
|
||||
|
||||
public Iterable<BlockPos> m_238383_() {
|
||||
return ImmutableSet.of(new BlockPos(this.m_20191_().f_82288_, (double)this.m_146904_(), this.m_20191_().f_82290_), new BlockPos(this.m_20191_().f_82288_, (double)this.m_146904_(), this.m_20191_().f_82293_), new BlockPos(this.m_20191_().f_82291_, (double)this.m_146904_(), this.m_20191_().f_82290_), new BlockPos(this.m_20191_().f_82291_, (double)this.m_146904_(), this.m_20191_().f_82293_));
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * {@return the type of spawn that created this mob, if applicable}
|
||||
+ * If it could not be determined, this will return null.
|
||||
+ * <p>
|
||||
+ * This is set via {@link Mob#finalizeSpawn}, so you should not call this from within that method, and instead use the parameter.
|
||||
+ */
|
||||
+ @Nullable
|
||||
+ public final MobSpawnType getSpawnType() {
|
||||
+ return this.spawnType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/entity/monster/Strider.java
|
||||
+++ b/net/minecraft/world/entity/monster/Strider.java
|
||||
@@ -418,6 +_,7 @@
|
||||
|
||||
private SpawnGroupData m_33881_(ServerLevelAccessor p_33882_, DifficultyInstance p_33883_, Mob p_33884_, @Nullable SpawnGroupData p_33885_) {
|
||||
p_33884_.m_7678_(this.m_20185_(), this.m_20186_(), this.m_20189_(), this.m_146908_(), 0.0F);
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(p_33884_, p_33882_, (float)p_33884_.m_20185_(), (float)p_33884_.m_20186_(), (float)p_33884_.m_20189_(), null, MobSpawnType.JOCKEY))
|
||||
p_33884_.m_6518_(p_33882_, p_33883_, MobSpawnType.JOCKEY, p_33885_, (CompoundTag)null);
|
||||
p_33884_.m_7998_(this, true);
|
||||
return new AgeableMob.AgeableMobGroupData(0.0F);
|
||||
@@ -1,11 +1,13 @@
|
||||
--- a/net/minecraft/world/entity/npc/CatSpawner.java
|
||||
+++ b/net/minecraft/world/entity/npc/CatSpawner.java
|
||||
@@ -86,8 +_,9 @@
|
||||
@@ -86,8 +_,11 @@
|
||||
if (cat == null) {
|
||||
return 0;
|
||||
} else {
|
||||
+ cat.m_20035_(p_35334_, 0.0F, 0.0F); // Fix MC-147659: Some witch huts spawn the incorrect cat
|
||||
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(cat, p_35335_, p_35334_.m_123341_(), p_35334_.m_123342_(), p_35334_.m_123343_(), null, MobSpawnType.NATURAL) == -1) return 0;
|
||||
+ // Note: This call to canEntitySpawn is erroneous, it is only provided for backwards compatibility.
|
||||
+ if (net.minecraftforge.common.ForgeHooks.canEntitySpawn(cat, p_35335_, p_35334_.m_123341_(), p_35334_.m_123342_(), p_35334_.m_123343_(), null, MobSpawnType.NATURAL) == -1) return 0;
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(cat, p_35335_, p_35334_.m_123341_(), p_35334_.m_123342_(), p_35334_.m_123343_(), null, MobSpawnType.NATURAL))
|
||||
cat.m_6518_(p_35335_, p_35335_.m_6436_(p_35334_), MobSpawnType.NATURAL, (SpawnGroupData)null, (CompoundTag)null);
|
||||
- cat.m_20035_(p_35334_, 0.0F, 0.0F);
|
||||
p_35335_.m_47205_(cat);
|
||||
|
||||
@@ -67,6 +67,17 @@
|
||||
if (!ItemStack.m_41728_(itemstack, itemstack1)) {
|
||||
this.f_39559_.m_6836_(0, ItemStack.f_41583_);
|
||||
this.m_38946_();
|
||||
@@ -163,6 +_,10 @@
|
||||
itemstack2 = flag3 ? itemstack : itemstack1;
|
||||
}
|
||||
|
||||
+ // Forge: Skip the repair if the result would give an item stack with a count not normally obtainable
|
||||
+ if (j > itemstack2.m_41741_())
|
||||
+ this.f_39559_.m_6836_(0, ItemStack.f_41583_);
|
||||
+ else
|
||||
this.f_39559_.m_6836_(0, this.m_39579_(itemstack2, i, j));
|
||||
}
|
||||
|
||||
@@ -175,7 +_,7 @@
|
||||
|
||||
for(Map.Entry<Enchantment, Integer> entry : map.entrySet()) {
|
||||
|
||||
@@ -38,15 +38,44 @@
|
||||
p_40704_.m_5496_(p_150709_, 1.0F, 1.0F);
|
||||
});
|
||||
p_40703_.m_142346_(p_40704_, GameEvent.f_157816_, blockpos);
|
||||
@@ -72,7 +_,7 @@
|
||||
@@ -72,8 +_,8 @@
|
||||
return InteractionResultHolder.m_19100_(itemstack);
|
||||
} else {
|
||||
BlockState blockstate = p_40703_.m_8055_(blockpos);
|
||||
- BlockPos blockpos2 = blockstate.m_60734_() instanceof LiquidBlockContainer && this.f_40687_ == Fluids.f_76193_ ? blockpos : blockpos1;
|
||||
- if (this.m_142073_(p_40704_, p_40703_, blockpos2, blockhitresult)) {
|
||||
+ BlockPos blockpos2 = canBlockContainFluid(p_40703_, blockpos, blockstate) ? blockpos : blockpos1;
|
||||
if (this.m_142073_(p_40704_, p_40703_, blockpos2, blockhitresult)) {
|
||||
+ if (this.emptyContents(p_40704_, p_40703_, blockpos2, blockhitresult, itemstack)) {
|
||||
this.m_142131_(p_40704_, p_40703_, itemstack, blockpos2);
|
||||
if (p_40704_ instanceof ServerPlayer) {
|
||||
CriteriaTriggers.f_10591_.m_59469_((ServerPlayer)p_40704_, blockpos2, itemstack);
|
||||
@@ -98,7 +_,12 @@
|
||||
public void m_142131_(@Nullable Player p_150711_, Level p_150712_, ItemStack p_150713_, BlockPos p_150714_) {
|
||||
}
|
||||
|
||||
+ @Deprecated //Forge: use the ItemStack sensitive version
|
||||
public boolean m_142073_(@Nullable Player p_150716_, Level p_150717_, BlockPos p_150718_, @Nullable BlockHitResult p_150719_) {
|
||||
+ return this.emptyContents(p_150716_, p_150717_, p_150718_, p_150719_, null);
|
||||
+ }
|
||||
+
|
||||
+ public boolean emptyContents(@Nullable Player p_150716_, Level p_150717_, BlockPos p_150718_, @Nullable BlockHitResult p_150719_, @Nullable ItemStack container) {
|
||||
if (!(this.f_40687_ instanceof FlowingFluid)) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -107,8 +_,12 @@
|
||||
Material material = blockstate.m_60767_();
|
||||
boolean flag = blockstate.m_60722_(this.f_40687_);
|
||||
boolean flag1 = blockstate.m_60795_() || flag || block instanceof LiquidBlockContainer && ((LiquidBlockContainer)block).m_6044_(p_150717_, p_150718_, blockstate, this.f_40687_);
|
||||
+ java.util.Optional<net.minecraftforge.fluids.FluidStack> containedFluidStack = java.util.Optional.ofNullable(container).flatMap(net.minecraftforge.fluids.FluidUtil::getFluidContained);
|
||||
if (!flag1) {
|
||||
- return p_150719_ != null && this.m_142073_(p_150716_, p_150717_, p_150719_.m_82425_().m_121945_(p_150719_.m_82434_()), (BlockHitResult)null);
|
||||
+ return p_150719_ != null && this.emptyContents(p_150716_, p_150717_, p_150719_.m_82425_().m_121945_(p_150719_.m_82434_()), (BlockHitResult)null, container);
|
||||
+ } else if (containedFluidStack.isPresent() && this.f_40687_.getFluidType().isVaporizedOnPlacement(p_150717_, p_150718_, containedFluidStack.get())) {
|
||||
+ this.f_40687_.getFluidType().onVaporize(p_150716_, p_150717_, p_150718_, containedFluidStack.get());
|
||||
+ return true;
|
||||
} else if (p_150717_.m_6042_().f_63857_() && this.f_40687_.m_205067_(FluidTags.f_13131_)) {
|
||||
int i = p_150718_.m_123341_();
|
||||
int j = p_150718_.m_123342_();
|
||||
@@ -120,7 +_,7 @@
|
||||
}
|
||||
|
||||
@@ -78,7 +107,7 @@
|
||||
+ private final java.util.function.Supplier<? extends Fluid> fluidSupplier;
|
||||
+ public Fluid getFluid() { return fluidSupplier.get(); }
|
||||
+
|
||||
+ private boolean canBlockContainFluid(Level worldIn, BlockPos posIn, BlockState blockstate)
|
||||
+ protected boolean canBlockContainFluid(Level worldIn, BlockPos posIn, BlockState blockstate)
|
||||
+ {
|
||||
+ return blockstate.m_60734_() instanceof LiquidBlockContainer && ((LiquidBlockContainer)blockstate.m_60734_()).m_6044_(worldIn, posIn, blockstate, this.f_40687_);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
--- a/net/minecraft/world/item/BundleItem.java
|
||||
+++ b/net/minecraft/world/item/BundleItem.java
|
||||
@@ -40,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean m_142207_(ItemStack p_150733_, Slot p_150734_, ClickAction p_150735_, Player p_150736_) {
|
||||
- if (p_150735_ != ClickAction.SECONDARY) {
|
||||
+ if (p_150733_.m_41613_() != 1 || p_150735_ != ClickAction.SECONDARY) {
|
||||
return false;
|
||||
} else {
|
||||
ItemStack itemstack = p_150734_.m_7993_();
|
||||
@@ -62,6 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean m_142305_(ItemStack p_150742_, ItemStack p_150743_, Slot p_150744_, ClickAction p_150745_, Player p_150746_, SlotAccess p_150747_) {
|
||||
+ if (p_150742_.m_41613_() != 1) return false;
|
||||
if (p_150745_ == ClickAction.SECONDARY && p_150744_.m_150651_(p_150746_)) {
|
||||
if (p_150743_.m_41619_()) {
|
||||
m_150780_(p_150742_).ifPresent((p_186347_) -> {
|
||||
@@ -0,0 +1,14 @@
|
||||
--- a/net/minecraft/world/item/DispensibleContainerItem.java
|
||||
+++ b/net/minecraft/world/item/DispensibleContainerItem.java
|
||||
@@ -6,9 +_,10 @@
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
|
||||
-public interface DispensibleContainerItem {
|
||||
+public interface DispensibleContainerItem extends net.minecraftforge.common.extensions.IForgeDispensibleContainerItem {
|
||||
default void m_142131_(@Nullable Player p_150817_, Level p_150818_, ItemStack p_150819_, BlockPos p_150820_) {
|
||||
}
|
||||
|
||||
+ @Deprecated //Forge: use the ItemStack sensitive version
|
||||
boolean m_142073_(@Nullable Player p_150821_, Level p_150822_, BlockPos p_150823_, @Nullable BlockHitResult p_150824_);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/level/BaseSpawner.java
|
||||
+++ b/net/minecraft/world/level/BaseSpawner.java
|
||||
@@ -127,11 +_,15 @@
|
||||
@@ -127,10 +_,15 @@
|
||||
entity.m_7678_(entity.m_20185_(), entity.m_20186_(), entity.m_20189_(), randomsource.m_188501_() * 360.0F, 0.0F);
|
||||
if (entity instanceof Mob) {
|
||||
Mob mob = (Mob)entity;
|
||||
@@ -11,11 +11,11 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
+ // Fire this early so mods can react to mobs that vanilla normally ignores.
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, p_151312_, (float)entity.m_20185_(), (float)entity.m_20186_(), (float)entity.m_20189_(), this, MobSpawnType.SPAWNER))
|
||||
if (this.f_45444_.m_186567_().m_128440_() == 1 && this.f_45444_.m_186567_().m_128425_("id", 8)) {
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, (LevelAccessor)p_151312_, (float)entity.m_20185_(), (float)entity.m_20186_(), (float)entity.m_20189_(), this, MobSpawnType.SPAWNER))
|
||||
((Mob)entity).m_6518_(p_151312_, p_151312_.m_6436_(entity.m_20183_()), MobSpawnType.SPAWNER, (SpawnGroupData)null, (CompoundTag)null);
|
||||
}
|
||||
}
|
||||
@@ -275,4 +_,12 @@
|
||||
public double m_45474_() {
|
||||
return this.f_45446_;
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
mob.m_7678_(d0, (double)i, d1, p_47040_.f_46441_.m_188501_() * 360.0F, 0.0F);
|
||||
- if (m_46991_(p_47040_, mob, d2)) {
|
||||
+ int canSpawn = net.minecraftforge.common.ForgeHooks.canEntitySpawn(mob, p_47040_, d0, i, d1, null, MobSpawnType.NATURAL);
|
||||
+ if (canSpawn != -1 && (canSpawn == 1 || m_46991_(p_47040_, mob, d2))) {
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, (LevelAccessor) p_47040_, (float)d0, (float)i, (float)d1, null, MobSpawnType.NATURAL))
|
||||
+ if (canSpawn == 1 || (canSpawn == 0 && m_46991_(p_47040_, mob, d2))) {
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, p_47040_, (float)d0, (float)i, (float)d1, null, MobSpawnType.NATURAL))
|
||||
spawngroupdata = mob.m_6518_(p_47040_, p_47040_.m_6436_(mob.m_20183_()), MobSpawnType.NATURAL, spawngroupdata, (CompoundTag)null);
|
||||
++j;
|
||||
++l1;
|
||||
@@ -75,11 +75,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,6 +_,7 @@
|
||||
@@ -370,7 +_,9 @@
|
||||
entity.m_7678_(d0, (double)blockpos.m_123342_(), d1, p_220454_.m_188501_() * 360.0F, 0.0F);
|
||||
if (entity instanceof Mob) {
|
||||
Mob mob = (Mob)entity;
|
||||
+ if (net.minecraftforge.common.ForgeHooks.canEntitySpawn(mob, p_220451_, d0, blockpos.m_123342_(), d1, null, MobSpawnType.CHUNK_GENERATION) == -1) continue;
|
||||
if (mob.m_5545_(p_220451_, MobSpawnType.CHUNK_GENERATION) && mob.m_6914_(p_220451_)) {
|
||||
- if (mob.m_5545_(p_220451_, MobSpawnType.CHUNK_GENERATION) && mob.m_6914_(p_220451_)) {
|
||||
+ int res = net.minecraftforge.common.ForgeHooks.canEntitySpawn(mob, p_220451_, d0, blockpos.m_123342_(), d1, null, MobSpawnType.CHUNK_GENERATION);
|
||||
+ if (res == 1 || (res == 0 && mob.m_5545_(p_220451_, MobSpawnType.CHUNK_GENERATION) && mob.m_6914_(p_220451_))) {
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, p_220451_, (float) d0, blockpos.m_123342_(), (float) d1, null, MobSpawnType.CHUNK_GENERATION))
|
||||
spawngroupdata = mob.m_6518_(p_220451_, p_220451_.m_6436_(mob.m_20183_()), MobSpawnType.CHUNK_GENERATION, spawngroupdata, (CompoundTag)null);
|
||||
p_220451_.m_47205_(mob);
|
||||
flag = true;
|
||||
@@ -4,8 +4,9 @@
|
||||
}
|
||||
|
||||
public void m_214148_(ServerLevel p_221243_, RandomSource p_221244_, BlockPos p_221245_, BlockState p_221246_) {
|
||||
- this.f_53597_.get().m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
|
||||
+ net.minecraftforge.event.level.SaplingGrowTreeEvent event = net.minecraftforge.event.ForgeEventFactory.blockGrowFeature(p_221243_, p_221244_, p_221245_, this.f_53597_.get());
|
||||
+ if (event.getResult().equals(net.minecraftforge.eventbus.api.Event.Result.DENY)) return;
|
||||
this.f_53597_.get().m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
|
||||
+ event.getFeature().m_203334_().m_224953_(p_221243_, p_221243_.m_7726_().m_8481_(), p_221244_, p_221245_);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/level/block/StemBlock.java
|
||||
+++ b/net/minecraft/world/level/block/StemBlock.java
|
||||
@@ -43,22 +_,24 @@
|
||||
@@ -43,22 +_,23 @@
|
||||
}
|
||||
|
||||
public void m_213898_(BlockState p_222538_, ServerLevel p_222539_, BlockPos p_222540_, RandomSource p_222541_) {
|
||||
@@ -19,8 +19,7 @@
|
||||
BlockPos blockpos = p_222540_.m_121945_(direction);
|
||||
BlockState blockstate = p_222539_.m_8055_(blockpos.m_7495_());
|
||||
- if (p_222539_.m_8055_(blockpos).m_60795_() && (blockstate.m_60713_(Blocks.f_50093_) || blockstate.m_204336_(BlockTags.f_144274_))) {
|
||||
+ Block block = blockstate.m_60734_();
|
||||
+ if (p_222539_.m_46859_(blockpos) && (blockstate.canSustainPlant(p_222539_, blockpos.m_7495_(), Direction.UP, this) || block == Blocks.f_50093_ || block == Blocks.f_50493_ || block == Blocks.f_50546_ || block == Blocks.f_50599_ || block == Blocks.f_50440_)) {
|
||||
+ if (p_222539_.m_46859_(blockpos) && (blockstate.canSustainPlant(p_222539_, blockpos.m_7495_(), Direction.UP, this.f_57015_) || blockstate.m_60713_(Blocks.f_50093_) || blockstate.m_204336_(BlockTags.f_144274_))) {
|
||||
p_222539_.m_46597_(blockpos, this.f_57015_.m_49966_());
|
||||
p_222539_.m_46597_(p_222540_, this.f_57015_.m_7810_().m_49966_().m_61124_(HorizontalDirectionalBlock.f_54117_, direction));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
--- a/net/minecraft/world/level/block/StemGrownBlock.java
|
||||
+++ b/net/minecraft/world/level/block/StemGrownBlock.java
|
||||
@@ -2,7 +_,7 @@
|
||||
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
|
||||
-public abstract class StemGrownBlock extends Block {
|
||||
+public abstract class StemGrownBlock extends Block implements net.minecraftforge.common.IPlantable {
|
||||
public StemGrownBlock(BlockBehaviour.Properties p_57058_) {
|
||||
super(p_57058_);
|
||||
}
|
||||
@@ -10,4 +_,11 @@
|
||||
public abstract StemBlock m_7161_();
|
||||
|
||||
public abstract AttachedStemBlock m_7810_();
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.world.level.block.state.BlockState getPlant(net.minecraft.world.level.BlockGetter world, net.minecraft.core.BlockPos pos) {
|
||||
+ net.minecraft.world.level.block.state.BlockState state = world.m_8055_(pos);
|
||||
+ if (state.m_60734_() != this) return m_49966_();
|
||||
+ return state;
|
||||
+ }
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
--- a/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
+++ b/net/minecraft/world/level/levelgen/PatrolSpawner.java
|
||||
@@ -104,6 +_,7 @@
|
||||
@@ -104,6 +_,9 @@
|
||||
}
|
||||
|
||||
patrollingmonster.m_6034_((double)p_224534_.m_123341_(), (double)p_224534_.m_123342_(), (double)p_224534_.m_123343_());
|
||||
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(patrollingmonster, p_224533_, p_224534_.m_123341_(), p_224534_.m_123342_(), p_224534_.m_123343_(), null, MobSpawnType.PATROL) == -1) return false;
|
||||
+ // Note: This call to canEntitySpawn is erroneous, it is only provided for backwards compatibility.
|
||||
+ if (net.minecraftforge.common.ForgeHooks.canEntitySpawn(patrollingmonster, p_224533_, p_224534_.m_123341_(), p_224534_.m_123342_(), p_224534_.m_123343_(), null, MobSpawnType.PATROL) == -1) return false;
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(patrollingmonster, p_224533_, p_224534_.m_123341_(), p_224534_.m_123342_(), p_224534_.m_123343_(), null, MobSpawnType.PATROL))
|
||||
patrollingmonster.m_6518_(p_224533_, p_224533_.m_6436_(p_224534_), MobSpawnType.PATROL, (SpawnGroupData)null, (CompoundTag)null);
|
||||
p_224533_.m_47205_(patrollingmonster);
|
||||
return true;
|
||||
@@ -1,10 +1,12 @@
|
||||
--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java
|
||||
@@ -60,6 +_,7 @@
|
||||
@@ -60,6 +_,9 @@
|
||||
for(int i1 = 0; i1 < l; ++i1) {
|
||||
Phantom phantom = EntityType.f_20509_.m_20615_(p_64576_);
|
||||
phantom.m_20035_(blockpos1, 0.0F, 0.0F);
|
||||
+ if(net.minecraftforge.common.ForgeHooks.canEntitySpawn(phantom, p_64576_, blockpos1.m_123341_(), blockpos1.m_123342_(), blockpos1.m_123343_(), null, MobSpawnType.NATURAL) == -1) { i--; continue; }
|
||||
+ // Note: This call to canEntitySpawn is erroneous, it is only provided for backwards compatibility.
|
||||
+ if (net.minecraftforge.common.ForgeHooks.canEntitySpawn(phantom, p_64576_, blockpos1.m_123341_(), blockpos1.m_123342_(), blockpos1.m_123343_(), null, MobSpawnType.NATURAL) == -1) { i--; continue; }
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(phantom, p_64576_, blockpos1.m_123341_(), blockpos1.m_123342_(), blockpos1.m_123343_(), null, MobSpawnType.NATURAL))
|
||||
spawngroupdata = phantom.m_6518_(p_64576_, difficultyinstance, MobSpawnType.NATURAL, spawngroupdata, (CompoundTag)null);
|
||||
p_64576_.m_47205_(phantom);
|
||||
}
|
||||
+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;
|
||||
}
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/level/levelgen/structure/structures/OceanMonumentPieces.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/structures/OceanMonumentPieces.java
|
||||
@@ -1442,6 +_,7 @@
|
||||
ElderGuardian elderguardian = EntityType.f_20563_.m_20615_(p_228844_.m_6018_());
|
||||
elderguardian.m_5634_(elderguardian.m_21233_());
|
||||
elderguardian.m_7678_((double)blockpos.m_123341_() + 0.5D, (double)blockpos.m_123342_(), (double)blockpos.m_123343_() + 0.5D, 0.0F, 0.0F);
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(elderguardian, p_228844_, (float)elderguardian.m_20185_(), (float)elderguardian.m_20186_(), (float)elderguardian.m_20189_(), null, MobSpawnType.STRUCTURE))
|
||||
elderguardian.m_6518_(p_228844_, p_228844_.m_6436_(elderguardian.m_20183_()), MobSpawnType.STRUCTURE, (SpawnGroupData)null, (CompoundTag)null);
|
||||
p_228844_.m_47205_(elderguardian);
|
||||
return true;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
--- a/net/minecraft/world/level/levelgen/structure/structures/WoodlandMansionPieces.java
|
||||
+++ b/net/minecraft/world/level/levelgen/structure/structures/WoodlandMansionPieces.java
|
||||
@@ -1052,6 +_,7 @@
|
||||
for(Mob mob : list) {
|
||||
mob.m_21530_();
|
||||
mob.m_20035_(p_230214_, 0.0F, 0.0F);
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn(mob, p_230215_, (float)mob.m_20185_(), (float)mob.m_20186_(), (float)mob.m_20189_(), null, MobSpawnType.STRUCTURE))
|
||||
mob.m_6518_(p_230215_, p_230215_.m_6436_(mob.m_20183_()), MobSpawnType.STRUCTURE, (SpawnGroupData)null, (CompoundTag)null);
|
||||
p_230215_.m_47205_(mob);
|
||||
p_230215_.m_7731_(p_230214_, Blocks.f_50016_.m_49966_(), 2);
|
||||
+2
-1
@@ -86,7 +86,7 @@
|
||||
ListTag listtag = new ListTag();
|
||||
listtag.add(DoubleTag.m_128500_(vec31.f_82479_));
|
||||
listtag.add(DoubleTag.m_128500_(vec31.f_82480_));
|
||||
@@ -391,10 +_,10 @@
|
||||
@@ -391,10 +_,11 @@
|
||||
compoundtag.m_128365_("Pos", listtag);
|
||||
compoundtag.m_128473_("UUID");
|
||||
m_74543_(p_74524_, compoundtag).ifPresent((p_205061_) -> {
|
||||
@@ -97,6 +97,7 @@
|
||||
p_205061_.m_7678_(vec31.f_82479_, vec31.f_82480_, vec31.f_82481_, f, p_205061_.m_146909_());
|
||||
- if (p_74530_ && p_205061_ instanceof Mob) {
|
||||
+ if (placementIn.m_74414_() && p_205061_ instanceof Mob) {
|
||||
+ if (!net.minecraftforge.event.ForgeEventFactory.doSpecialSpawn((Mob)p_205061_, p_74524_, (float)p_205061_.m_20185_(), (float)p_205061_.m_20186_(), (float)p_205061_.m_20189_(), null, MobSpawnType.STRUCTURE))
|
||||
((Mob)p_205061_).m_6518_(p_74524_, p_74524_.m_6436_(new BlockPos(vec31)), MobSpawnType.STRUCTURE, (SpawnGroupData)null, compoundtag);
|
||||
}
|
||||
|
||||
@@ -71,13 +71,14 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.locale.Language;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.chat.ChatSender;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.ChatTypeDecoration;
|
||||
import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.network.chat.MessageSigner;
|
||||
import net.minecraft.network.chat.PlayerChatMessage;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.network.protocol.status.ServerStatus;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
@@ -963,6 +964,17 @@ public class ForgeHooksClient
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getMessage();
|
||||
}
|
||||
|
||||
private static final ChatTypeDecoration SYSTEM_CHAT_TYPE_DECORATION = new ChatTypeDecoration("forge.chatType.system", List.of(ChatTypeDecoration.Parameter.CONTENT), Style.EMPTY);
|
||||
private static final ChatType SYSTEM_CHAT_TYPE = new ChatType(SYSTEM_CHAT_TYPE_DECORATION, SYSTEM_CHAT_TYPE_DECORATION);
|
||||
private static final ChatType.Bound SYSTEM_CHAT_TYPE_BOUND = SYSTEM_CHAT_TYPE.bind(Component.literal("System"));
|
||||
|
||||
@Nullable
|
||||
public static Component onClientSystemChat(Component message, boolean overlay)
|
||||
{
|
||||
ClientChatReceivedEvent.System event = new ClientChatReceivedEvent.System(SYSTEM_CHAT_TYPE_BOUND, message, overlay);
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getMessage();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String onClientSendMessage(String message)
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.network.chat.ChatMessageContent;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MessageSigner;
|
||||
@@ -45,6 +46,11 @@ public class ClientChatReceivedEvent extends Event
|
||||
this.messageSigner = messageSigner;
|
||||
}
|
||||
|
||||
private ClientChatReceivedEvent(ChatType.Bound boundChatType, Component message, PlayerChatMessage playerChatMessage)
|
||||
{
|
||||
this(boundChatType, message, playerChatMessage, playerChatMessage.signer());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the message that will be displayed in the chat message window, if the event is not cancelled}
|
||||
*/
|
||||
@@ -98,4 +104,33 @@ public class ClientChatReceivedEvent extends Event
|
||||
{
|
||||
return this.messageSigner.isSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a system chat message is received on the client.
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If the event is cancelled, the message is not displayed in the chat message window or in the overlay.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static class System extends ClientChatReceivedEvent
|
||||
{
|
||||
private final boolean overlay;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public System(ChatType.Bound boundChatType, Component message, boolean overlay)
|
||||
{
|
||||
super(boundChatType, message, PlayerChatMessage.system(new ChatMessageContent(message.getString(), message)));
|
||||
this.overlay = overlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return whether the message goes to the overlay}
|
||||
*/
|
||||
public boolean isOverlay()
|
||||
{
|
||||
return this.overlay;
|
||||
}
|
||||
}
|
||||
}
|
||||
+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) {}
|
||||
}
|
||||
@@ -499,6 +499,13 @@ public class ForgeGui extends Gui
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache()
|
||||
{
|
||||
super.clearCache();
|
||||
this.debugOverlay.clearChunkCache();
|
||||
}
|
||||
|
||||
protected void renderRecordOverlay(int width, int height, float partialTick, PoseStack pStack)
|
||||
{
|
||||
if (overlayMessageTime > 0)
|
||||
|
||||
@@ -37,6 +37,7 @@ import net.minecraftforge.client.model.data.ModelProperty;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryLoader;
|
||||
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
|
||||
import net.minecraftforge.common.util.ConcatenatedListView;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -91,7 +92,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
|
||||
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
|
||||
modelState = UnbakedGeometryHelper.composeRootTransformIntoModelState(modelState, rootTransform);
|
||||
|
||||
var bakedPartsBuilder = ImmutableMap.<String, BakedModel>builder();
|
||||
for (var entry : children.entrySet())
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.util.GsonHelper;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
|
||||
import net.minecraftforge.client.model.geometry.IGeometryLoader;
|
||||
import net.minecraftforge.client.model.geometry.SimpleUnbakedGeometry;
|
||||
import net.minecraftforge.client.model.geometry.UnbakedGeometryHelper;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@@ -65,8 +66,10 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
// If there is a root transform, undo the ModelState transform, apply it, then re-apply the ModelState transform.
|
||||
// This is necessary because of things like UV locking, which should only respond to the ModelState, and as such
|
||||
// that is the only transform that should be applied during face bake.
|
||||
var postTransform = context.getRootTransform().isIdentity() ? QuadTransformers.empty() :
|
||||
QuadTransformers.applying(modelState.getRotation().compose(context.getRootTransform()).compose(modelState.getRotation().inverse()));
|
||||
var postTransform = QuadTransformers.empty();
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
postTransform = UnbakedGeometryHelper.applyRootTransform(modelState, rootTransform);
|
||||
|
||||
for (BlockElement element : elements)
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel>
|
||||
);
|
||||
var rootTransform = context.getRootTransform();
|
||||
if (!rootTransform.isIdentity())
|
||||
modelState = new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
|
||||
modelState = UnbakedGeometryHelper.composeRootTransformIntoModelState(modelState, rootTransform);
|
||||
|
||||
var normalRenderTypes = new RenderTypeGroup(RenderType.translucent(), ForgeRenderTypes.ITEM_UNSORTED_TRANSLUCENT.get());
|
||||
CompositeModel.Baked.Builder builder = CompositeModel.Baked.builder(context, particle, overrides, context.getTransforms());
|
||||
|
||||
+8
-1
@@ -42,6 +42,7 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext
|
||||
private Transformation rootTransform;
|
||||
@Nullable
|
||||
private ResourceLocation renderTypeHint;
|
||||
private boolean gui3d = true;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public BlockGeometryBakingContext(BlockModel owner)
|
||||
@@ -94,7 +95,7 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext
|
||||
@Override
|
||||
public boolean isGui3d()
|
||||
{
|
||||
return true;
|
||||
return gui3d;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,12 +143,18 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext
|
||||
this.renderTypeHint = renderTypeHint;
|
||||
}
|
||||
|
||||
public void setGui3d(boolean gui3d)
|
||||
{
|
||||
this.gui3d = gui3d;
|
||||
}
|
||||
|
||||
public void copyFrom(BlockGeometryBakingContext other)
|
||||
{
|
||||
this.customGeometry = other.customGeometry;
|
||||
this.rootTransform = other.rootTransform;
|
||||
this.visibilityData.copyFrom(other.visibilityData);
|
||||
this.renderTypeHint = other.renderTypeHint;
|
||||
this.gui3d = other.gui3d;
|
||||
}
|
||||
|
||||
public Collection<Material> getTextureDependencies(Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
|
||||
@@ -27,6 +27,8 @@ import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.model.ElementsModel;
|
||||
import net.minecraftforge.client.model.IModelBuilder;
|
||||
import net.minecraftforge.client.model.IQuadTransformer;
|
||||
import net.minecraftforge.client.model.QuadTransformers;
|
||||
import net.minecraftforge.client.model.SimpleModelState;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -244,4 +246,32 @@ public class UnbakedGeometryHelper
|
||||
{
|
||||
return FACE_BAKERY.bakeQuad(element.from, element.to, face, sprite, direction, state, element.rotation, element.shade, modelLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link IQuadTransformer} to apply a {@link Transformation} that undoes the {@link ModelState}
|
||||
* transform (blockstate transform), applies the given root transform and then re-applies the
|
||||
* blockstate transform.
|
||||
*
|
||||
* @return an {@code IQuadTransformer} that applies the root transform to a baked quad that already has the
|
||||
* transformation of the given {@code ModelState} applied to it
|
||||
*/
|
||||
public static IQuadTransformer applyRootTransform(ModelState modelState, Transformation rootTransform)
|
||||
{
|
||||
// Move the origin of the ModelState transform and its inverse from the negative corner to the block center
|
||||
// to replicate the way the ModelState transform is applied in the FaceBakery by moving the vertices such that
|
||||
// the negative corner acts as the block center
|
||||
Transformation transform = modelState.getRotation().applyOrigin(new Vector3f(.5F, .5F, .5F));
|
||||
return QuadTransformers.applying(transform.compose(rootTransform).compose(transform.inverse()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a {@link ModelState} that combines the existing model state and the {@linkplain Transformation root transform}}
|
||||
*/
|
||||
public static ModelState composeRootTransformIntoModelState(ModelState modelState, Transformation rootTransform)
|
||||
{
|
||||
// Move the origin of the root transform as if the negative corner were the block center to match the way the
|
||||
// ModelState transform is applied in the FaceBakery by moving the vertices to be centered on that corner
|
||||
rootTransform = rootTransform.applyOrigin(new Vector3f(-.5F, -.5F, -.5F));
|
||||
return new SimpleModelState(modelState.getRotation().compose(rootTransform), modelState.isUvLocked());
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import net.minecraftforge.client.ClientCommandHandler;
|
||||
import net.minecraftforge.eventbus.api.BusBuilder;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.network.DualStackUtils;
|
||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -42,6 +43,7 @@ public class MinecraftForge
|
||||
UsernameCache.load();
|
||||
TierSortingRegistry.init();
|
||||
if (FMLEnvironment.dist == Dist.CLIENT) ClientCommandHandler.init();
|
||||
DualStackUtils.initialise();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.DispensibleContainerItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface IForgeDispensibleContainerItem
|
||||
{
|
||||
private DispensibleContainerItem self()
|
||||
{
|
||||
return (DispensibleContainerItem)this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the contents of the container and returns whether it was successful.
|
||||
*
|
||||
* @param player Player who empties the container. May be null for blocks like dispensers.
|
||||
* @param level Level to place the content in
|
||||
* @param pos The position in the level to empty the content
|
||||
* @param hitResult Hit result of the interaction. May be null for blocks like dispensers.
|
||||
* @param container ItemStack of the container. May be null for backwards compatibility.
|
||||
* @return true if emptying the contents of the container was successful, false otherwise
|
||||
*/
|
||||
default boolean emptyContents(@Nullable Player player, Level level, BlockPos pos, @Nullable BlockHitResult hitResult, @Nullable ItemStack container)
|
||||
{
|
||||
return self().emptyContents(player, level, pos, hitResult);
|
||||
}
|
||||
}
|
||||
@@ -201,16 +201,9 @@ public final class TransformationHelper
|
||||
elements.remove("origin");
|
||||
}
|
||||
if (!elements.isEmpty()) throw new JsonParseException("TRSR: can either have single 'matrix' key, or a combination of 'translation', 'rotation' OR 'left_rotation', 'scale', 'post-rotation' (legacy) OR 'right_rotation', 'origin'. Found: " + String.join(", ", elements));
|
||||
Transformation matrix = new Transformation(translation, leftRot, scale, rightRot);
|
||||
|
||||
// Use a different origin if needed.
|
||||
if (!TransformOrigin.CENTER.getVector().equals(origin))
|
||||
{
|
||||
Vector3f originFromCenter = origin.copy();
|
||||
originFromCenter.sub(TransformOrigin.CENTER.getVector());
|
||||
matrix = matrix.applyOrigin(originFromCenter);
|
||||
}
|
||||
return matrix;
|
||||
Transformation matrix = new Transformation(translation, leftRot, scale, rightRot);
|
||||
return matrix.applyOrigin(origin.copy());
|
||||
}
|
||||
|
||||
private static Vector3f parseOrigin(JsonObject obj) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.MobCategory;
|
||||
import net.minecraft.world.entity.projectile.Projectile;
|
||||
import net.minecraft.world.entity.projectile.ThrownEnderpearl;
|
||||
import net.minecraft.world.level.LevelSimulatedReader;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
@@ -121,6 +122,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;
|
||||
@@ -185,7 +187,7 @@ public class ForgeEventFactory
|
||||
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(player, stack, hand));
|
||||
}
|
||||
|
||||
public static Result canEntitySpawn(Mob entity, LevelAccessor level, double x, double y, double z, BaseSpawner spawner, MobSpawnType spawnReason)
|
||||
public static Result canEntitySpawn(Mob entity, LevelAccessor level, double x, double y, double z, @Nullable BaseSpawner spawner, MobSpawnType spawnReason)
|
||||
{
|
||||
if (entity == null)
|
||||
return Result.DEFAULT;
|
||||
@@ -194,7 +196,7 @@ public class ForgeEventFactory
|
||||
return event.getResult();
|
||||
}
|
||||
|
||||
public static boolean doSpecialSpawn(Mob entity, LevelAccessor level, float x, float y, float z, BaseSpawner spawner, MobSpawnType spawnReason)
|
||||
public static boolean doSpecialSpawn(Mob entity, LevelAccessor level, float x, float y, float z, @Nullable BaseSpawner spawner, MobSpawnType spawnReason)
|
||||
{
|
||||
return MinecraftForge.EVENT_BUS.post(new LivingSpawnEvent.SpecialSpawn(entity, level, x, y, z, spawner, spawnReason));
|
||||
}
|
||||
@@ -628,6 +630,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)
|
||||
@@ -812,12 +821,12 @@ public class ForgeEventFactory
|
||||
|
||||
public static void onPreLevelTick(Level level, BooleanSupplier haveTime)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(new TickEvent.LevelTickEvent(LogicalSide.SERVER, TickEvent.Phase.START, level, haveTime));
|
||||
MinecraftForge.EVENT_BUS.post(new TickEvent.LevelTickEvent(level.isClientSide ? LogicalSide.CLIENT : LogicalSide.SERVER, TickEvent.Phase.START, level, haveTime));
|
||||
}
|
||||
|
||||
public static void onPostLevelTick(Level level, BooleanSupplier haveTime)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(new TickEvent.LevelTickEvent(LogicalSide.SERVER, TickEvent.Phase.END, level, haveTime));
|
||||
MinecraftForge.EVENT_BUS.post(new TickEvent.LevelTickEvent(level.isClientSide ? LogicalSide.CLIENT : LogicalSide.SERVER, TickEvent.Phase.END, level, haveTime));
|
||||
}
|
||||
|
||||
public static void onPreClientTick()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.event.entity;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
@@ -26,6 +27,7 @@ import net.minecraftforge.fml.LogicalSide;
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus}
|
||||
* on both logical sides.
|
||||
* @apiNote If the spawned entity is a mob, and {@linkplain Mob#finalizeSpawn the spawn was finalized}, the spawn type is available via {@link Mob#getSpawnType()}
|
||||
**/
|
||||
@Cancelable
|
||||
public class EntityJoinLevelEvent extends EntityEvent
|
||||
|
||||
@@ -5,23 +5,24 @@
|
||||
|
||||
package net.minecraftforge.event.entity.living;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.level.BaseSpawner;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* This event is fired whenever a {@link Mob} should do something spawn-related.
|
||||
* <p>
|
||||
* This event is not {@linkplain Cancelable cancellable} and does not {@linkplain HasResult have a result}.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus}
|
||||
* only on the {@linkplain LogicalSide#SERVER logical server}.
|
||||
* Base class for mob spawn events.
|
||||
* Will not be fired directly.
|
||||
* @see CheckSpawn
|
||||
* @see SpecialSpawn
|
||||
* @see AllowDespawn
|
||||
*/
|
||||
public class LivingSpawnEvent extends LivingEvent
|
||||
{
|
||||
@@ -83,7 +84,7 @@ public class LivingSpawnEvent extends LivingEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired before a {@link Mob} spawns.
|
||||
* This event is fired when {@link Mob#checkSpawnRules} would be called.
|
||||
* <p>
|
||||
* This event is not {@linkplain Cancelable cancellable}, but does {@linkplain HasResult have a result}.
|
||||
* {@linkplain Result#DEFAULT DEFAULT} indicates that default spawn rules should be used.
|
||||
@@ -125,13 +126,14 @@ public class LivingSpawnEvent extends LivingEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired whenever a {@link Mob} is set to be spawned, to allow for mod-specific initializers.
|
||||
* This event is fired whenever {@link Mob#finalizeSpawn} would be called.
|
||||
* <p>
|
||||
* This event is {@linkplain Cancelable cancellable} and does not {@linkplain HasResult have a result}.
|
||||
* If the event is canceled, the mob will not spawn.
|
||||
* If the event is canceled, then {@link Mob#finalizeSpawn} will not be called.<br>
|
||||
* The mob will still be spawned. Preventing the spawn requires usage of {@link EntityJoinLevelEvent}.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#SERVER logical server}.
|
||||
* and only on the {@linkplain LogicalSide#SERVER logical server}.
|
||||
*/
|
||||
@Cancelable
|
||||
public static class SpecialSpawn extends LivingSpawnEvent
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.event.level;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.LevelSimulatedReader;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecorator;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* This event is fired when {@link net.minecraft.world.level.levelgen.feature.treedecorators.AlterGroundDecorator#placeBlockAt(TreeDecorator.Context, BlockPos)}
|
||||
* attempts to alter a ground block when generating a feature. An example of this would be large spruce trees converting grass blocks into podzol.
|
||||
* <p>
|
||||
* This event is not {@linkplain Cancelable cancellable}.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus}
|
||||
* only on the {@linkplain net.minecraftforge.fml.LogicalSide#SERVER logical server}.
|
||||
*/
|
||||
public class AlterGroundEvent extends Event {
|
||||
private final LevelSimulatedReader level;
|
||||
private final RandomSource random;
|
||||
private final BlockPos pos;
|
||||
private final BlockState originalAltered;
|
||||
private BlockState newAltered;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public AlterGroundEvent(LevelSimulatedReader level, RandomSource random, BlockPos pos, BlockState altered) {
|
||||
super();
|
||||
this.level = level;
|
||||
this.random = random;
|
||||
this.pos = pos;
|
||||
this.originalAltered = altered;
|
||||
this.newAltered = altered;
|
||||
}
|
||||
|
||||
public LevelSimulatedReader getLevel() {
|
||||
return this.level;
|
||||
}
|
||||
|
||||
public RandomSource getRandom() {
|
||||
return this.random;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the position of the block that will be altered}
|
||||
*/
|
||||
public BlockPos getPos() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the original block state that would be placed by the ground decorator}
|
||||
*/
|
||||
public BlockState getOriginalAlteredState() {
|
||||
return this.originalAltered;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the new block state to be placed by the ground decorator}
|
||||
*/
|
||||
public BlockState getNewAlteredState() {
|
||||
return this.newAltered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param newAltered the new block state to be placed by the ground decorator
|
||||
*/
|
||||
public void setNewAlteredState(BlockState newAltered) {
|
||||
this.newAltered = newAltered;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,9 @@ public class FluidUtil
|
||||
}
|
||||
else
|
||||
{
|
||||
containerFluidHandler.fill(simulatedTransfer, IFluidHandler.FluidAction.SIMULATE);
|
||||
// We are acting on a COPY of the stack, so performing changes on the source is acceptable even if we are simulating.
|
||||
// We need to perform the change otherwise the call to getContainer() will be incorrect.
|
||||
containerFluidHandler.fill(simulatedTransfer, IFluidHandler.FluidAction.EXECUTE);
|
||||
}
|
||||
|
||||
ItemStack resultContainer = containerFluidHandler.getContainer();
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
|
||||
package net.minecraftforge.network;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.minecraft.client.multiplayer.resolver.ResolvedServerAddress;
|
||||
import net.minecraft.client.multiplayer.resolver.ServerAddress;
|
||||
import net.minecraft.client.multiplayer.resolver.ServerNameResolver;
|
||||
import net.minecraft.util.HttpUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
@@ -19,6 +23,19 @@ import java.util.Optional;
|
||||
|
||||
public class DualStackUtils
|
||||
{
|
||||
private static final String INITIAL_PREFER_IPv4_STACK = System.getProperty("java.net.preferIPv4Stack") == null ? "false" : System.getProperty("java.net.preferIPv4Stack");
|
||||
private static final String INITIAL_PREFER_IPv6_ADDRESSES = System.getProperty("java.net.preferIPv6Addresses") == null ? "false" : System.getProperty("java.net.preferIPv6Addresses");
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
/**
|
||||
* Called by {@link net.minecraftforge.common.MinecraftForge} to load this class so that the initial network
|
||||
* property constants are set before any of the other methods in this class are called. This is so we can
|
||||
* distinguish what Java's read once on JVM start vs what we've set for Netty.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void initialise() {}
|
||||
|
||||
/**
|
||||
* Resolve the address and see if Java and the OS return an IPv6 or IPv4 one, then let Netty know
|
||||
* accordingly (it doesn't understand the {@code java.net.preferIPv6Addresses=system} property).
|
||||
@@ -45,14 +62,49 @@ public class DualStackUtils
|
||||
*/
|
||||
public static boolean checkIPv6(final InetAddress inetAddress)
|
||||
{
|
||||
if (inetAddress instanceof Inet6Address)
|
||||
// only log debug messages if we're not in the server pinger thread, as otherwise it's unclear which IP
|
||||
// corresponds to which server as soon as you have more than one server in the multiplayer server list
|
||||
final String currentThreadName = Thread.currentThread().getName();
|
||||
final boolean shouldLogDebug = !currentThreadName.contains("Server Pinger #");
|
||||
|
||||
if (inetAddress instanceof Inet6Address addr)
|
||||
{
|
||||
if (shouldLogDebug)
|
||||
LOGGER.debug("Detected IPv6 address: \"" + addr.getHostAddress() + "\"");
|
||||
|
||||
System.setProperty("java.net.preferIPv4Stack", "false");
|
||||
System.setProperty("java.net.preferIPv6Addresses", "true");
|
||||
return true;
|
||||
}
|
||||
else if (inetAddress instanceof Inet4Address addr)
|
||||
{
|
||||
if (shouldLogDebug)
|
||||
LOGGER.debug("Detected IPv4 address: \"" + addr.getHostAddress() + "\"");
|
||||
|
||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
System.setProperty("java.net.preferIPv6Addresses", "false");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shouldLogDebug) {
|
||||
final String addr = inetAddress == null ? "null" : "\"" + inetAddress.getHostAddress() + "\"";
|
||||
LOGGER.debug("Unable to determine IP version of address: " + addr);
|
||||
}
|
||||
|
||||
if (INITIAL_PREFER_IPv4_STACK.equalsIgnoreCase("false") && INITIAL_PREFER_IPv6_ADDRESSES.equalsIgnoreCase("true"))
|
||||
{
|
||||
if (shouldLogDebug)
|
||||
LOGGER.debug("Assuming IPv6 as Java was explicitly told to prefer it...");
|
||||
|
||||
System.setProperty("java.net.preferIPv4Stack", "false");
|
||||
System.setProperty("java.net.preferIPv6Addresses", "true");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (shouldLogDebug)
|
||||
LOGGER.debug("Assuming IPv4...");
|
||||
|
||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
System.setProperty("java.net.preferIPv6Addresses", "false");
|
||||
return false;
|
||||
@@ -81,8 +133,21 @@ public class DualStackUtils
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for the "Open to LAN" feature.
|
||||
* @return The multicast group to use for LAN discovery - IPv6 if available, IPv4 otherwise.
|
||||
*/
|
||||
public static String getMulticastGroup() {
|
||||
if (checkIPv6(getLocalAddress())) return "FF75:230::60";
|
||||
else return "224.0.2.60";
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the initial values of the {@code java.net.preferIPv4Stack} and {@code java.net.preferIPv6Addresses} system
|
||||
* properties that Java has read on JVM start. Useful for debugging hostname lookup failures.
|
||||
*/
|
||||
public static void logInitialPreferences() {
|
||||
LOGGER.debug("Initial IPv4 stack preference: " + INITIAL_PREFER_IPv4_STACK);
|
||||
LOGGER.debug("Initial IPv6 addresses preference: " + INITIAL_PREFER_IPv6_ADDRESSES);
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class ResourceCacheManager
|
||||
*/
|
||||
public static boolean shouldUseCache()
|
||||
{
|
||||
return ResourceManagerBootCacheConfigurationHandler.getInstance().getConfigValue("cachePackAccess", true);
|
||||
return ResourceManagerBootCacheConfigurationHandler.getInstance().getConfigValue("cacheResources", true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -217,6 +217,8 @@
|
||||
"fluid_type.minecraft.milk": "Milk",
|
||||
"fluid_type.minecraft.flowing_milk": "Milk",
|
||||
|
||||
"forge.chatType.system": "{0}",
|
||||
|
||||
"forge.experimentalsettings.tooltip": "This world uses experimental settings, which could stop working at any time.",
|
||||
"forge.selectWorld.backupWarning.experimental.additional" : "This message will not show again for this world."
|
||||
}
|
||||
@@ -65,6 +65,7 @@ net/minecraft/world/entity/player/Player.getDigSpeed(Lnet/minecraft/world/level/
|
||||
net/minecraft/world/entity/projectile/ThrownEnderpearl.changeDimension(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraftforge/common/util/ITeleporter;)Lnet/minecraft/world/entity/Entity;=|p_37506_,teleporter
|
||||
net/minecraft/world/food/FoodData.eat(Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)V=|p_38713_,p_38714_,entity
|
||||
net/minecraft/world/item/BoneMealItem.applyBonemeal(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;)Z=|p_40628_,p_40629_,p_40630_,player
|
||||
net/minecraft/world/item/BucketItem.emptyContents(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/phys/BlockHitResult;Lnet/minecraft/world/item/ItemStack;)Z=|p_150716_,p_150717_,p_150718_,p_150719_,container
|
||||
net/minecraft/world/item/DyeableHorseArmorItem.<init>(ILnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/item/Item$Properties;)V=|p_41110_,p_41111_,p_41112_
|
||||
net/minecraft/world/item/HorseArmorItem.<init>(ILnet/minecraft/resources/ResourceLocation;Lnet/minecraft/world/item/Item$Properties;)V=|p_41364_,p_41365_,p_41366_
|
||||
net/minecraft/world/item/ItemStack.<init>(Lnet/minecraft/world/level/ItemLike;ILnet/minecraft/nbt/CompoundTag;)V=|p_41604_,p_41605_,p_41606_
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.debug;
|
||||
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.event.level.AlterGroundEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod("alter_ground_event_test")
|
||||
@Mod.EventBusSubscriber
|
||||
public class AlterGroundEventTest {
|
||||
public static final boolean ENABLE = true;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onAlterGround(AlterGroundEvent event)
|
||||
{
|
||||
if (ENABLE) {
|
||||
if (event.getOriginalAlteredState().is(Blocks.PODZOL)) {
|
||||
event.setNewAlteredState(Blocks.REDSTONE_BLOCK.defaultBlockState());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ public class FluidUtilTest
|
||||
private static void runTests(FMLCommonSetupEvent commonSetupEvent)
|
||||
{
|
||||
test_tryEmptyContainer();
|
||||
test_tryFillContainer();
|
||||
test_tryEmptyContainerAndStow_stackable();
|
||||
|
||||
LogManager.getLogger().info("FluidUtilTest ok!");
|
||||
@@ -70,6 +71,35 @@ public class FluidUtilTest
|
||||
checkItemStack(sourceStack, Items.WATER_BUCKET, 2); // Apparently the stack is not supposed to be modified
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that tryFillContainer doesn't change the target fluid handler when simulating.
|
||||
* Ant that the result of the simulated transfver is valid.
|
||||
* Regression test for the root cause of <a href="https://github.com/MinecraftForge/MinecraftForge/issues/6796">issue #6796</a>.
|
||||
*/
|
||||
private static void test_tryFillContainer()
|
||||
{
|
||||
var targetStack = new ItemStack(Items.BUCKET, 2);
|
||||
var sourceTank = new FluidTank(10000);
|
||||
sourceTank.setFluid(new FluidStack(Fluids.WATER, 5000));
|
||||
|
||||
// Simulate is not supposed to modify anything
|
||||
var simulateResult = FluidUtil.tryFillContainer(targetStack, sourceTank, 1000, null, false);
|
||||
if (!simulateResult.isSuccess())
|
||||
throw new AssertionError("Failed to transfer.");
|
||||
checkItemStack(simulateResult.getResult(), Items.WATER_BUCKET, 1);
|
||||
// Tank and stack shouldn't be modified
|
||||
checkItemStack(targetStack, Items.BUCKET, 2);
|
||||
checkFluidStack(sourceTank.getFluid(), Fluids.WATER, 5000);
|
||||
|
||||
// Execute should modify
|
||||
var executeResult = FluidUtil.tryFillContainer(targetStack, sourceTank, 1000, null, true);
|
||||
if (!executeResult.isSuccess())
|
||||
throw new AssertionError("Failed to transfer.");
|
||||
checkItemStack(executeResult.getResult(), Items.WATER_BUCKET, 1);
|
||||
checkFluidStack(sourceTank.getFluid(), Fluids.WATER, 4000);
|
||||
checkItemStack(targetStack, Items.BUCKET, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that tryEmptyContainerAndStow doesn't duplicate fluids in the target when the container is stackable.
|
||||
* Regression test for <a href="https://github.com/MinecraftForge/MinecraftForge/issues/6796">issue #6796</a>.
|
||||
|
||||
@@ -270,6 +270,7 @@ modId="item_stacked_on_other_test"
|
||||
modId="ambient_occlusion_elements_test"
|
||||
[[mods]]
|
||||
modId="grindstone_event_test"
|
||||
|
||||
[[mods]]
|
||||
modId="alter_ground_event_test"
|
||||
|
||||
# ADD ABOVE THIS LINE
|
||||
Reference in new issue
Block a user