Compare commits

...
38 Commits
Author SHA1 Message Date
LexManos f173bde812 1.16.5 Initial Update. 2021-01-15 11:33:11 -08:00
LexManos dd10933ab0 Update Coremods, ASM, and include standalone Nashorn to load on J15. 2021-01-14 15:48:53 -08:00
Ian Rehwinkel c3e84646db Added IWeatherParticleRenderHandler to allow a mod to take control over weather particles and sounds. (#7522) 2021-01-07 12:24:40 -08:00
covers1624 2094f99640 Allow Chunk loading Tickets to opt-into forcing chunk ticks. (#7525) 2021-01-07 12:13:47 -08:00
malte0811 94f3bdaa69 Fix crash when mods add goals to skeleton horses (MC-206338) (#7509) 2021-01-07 12:04:50 -08:00
Take Weiland 7220e9d0b0 Set WM_CLASS and WM_INSTANCE_NAME for early progress window (#7534) 2021-01-07 12:03:46 -08:00
Alex O'Neill 020102d87f Make UnboundedMapCodec more lenient in decoding dimensions. Fixes MC-197860 (#7527) 2021-01-05 19:17:24 -08:00
LexManos f101700969 Fix FML's Config Sync packet not allowing same length filenames in encoder and decoder. Closes #7584 2021-01-05 11:50:05 -08:00
LexManos c4b148b84b Prevent NPE and deprecated MissingMappings.getMappings function. Closes #6252 2021-01-05 11:47:00 -08:00
LexManos b6a9274870 Fix entities not correctly being able to be ridden under water. 2021-01-03 03:02:32 -08:00
Jonathan Coates 830d9699e3 Fix crash when beehive is broken by fake player (#7566) 2020-12-28 13:56:44 -08:00
Alex O'Neill fc68b81b21 Add supplier variant to AbstractBlock.Properties#lootFrom (#7563) 2020-12-28 13:42:15 -08:00
Take Weiland 2904772b16 Fix ModFileResourcePack.getAllResourceLocations ignoring resourceNamespace. (#7562)
Fixes #7405
2020-12-28 13:39:44 -08:00
Take Weiland e120b57032 Fix missing serializers when deserializing global loot modifiers (#7561) 2020-12-28 13:37:32 -08:00
Take Weiland b86b56260d Fix VanillaConnectionNetworkFilter sending out invalid entity properties packets without an entity ID (#7560) 2020-12-28 13:34:31 -08:00
Richard Freimer b222b23557 Make shear interactions extend to subclasses (#7544) 2020-12-28 13:10:35 -08:00
sciwhiz12 8ec4253068 Add a SoundType subclass that uses suppliers (#7538) 2020-12-28 13:09:03 -08:00
sciwhiz12 74ca88b7be Fix compound ingredient in shapeless recipes (#7537) Fixes #7530 2020-12-28 13:03:48 -08:00
Alex O'Neill a1119cd77a Fix potential NPE in ForgeHooks.onItemPlaceIntoWorld when passing in null player. (#7505) 2020-12-28 12:18:52 -08:00
mrp-v2 545723dc8c Fix modded PointOfInterestType's not populating blockstate map when registered (#7503) 2020-12-28 12:17:51 -08:00
poopoodice b64f4780c5 Add new LivingConversionEvent to control mobs turning into other mobs. (#7386) 2020-12-28 12:03:11 -08:00
KnightMiner 1c98b29087 Add ItemAttributeModifierEvent (#7484) 2020-12-28 11:59:09 -08:00
Brennan Ward 33880331d2 Fix RightClickBlock ALLOW not being implemented (#7426) 2020-12-28 11:54:30 -08:00
LexManos 74a43877e4 Quiet down errors related to modders not changing their update urls from the default. 2020-12-26 11:39:14 -08:00
LexManos 7542fbea48 Make mod data packs able to be disabled. It'll break things, but that's on you. Closes #6776 2020-12-26 11:38:45 -08:00
tterrag 2d9a1bc6f9 Add generated resource tracking to ExistingFileHelper 2020-12-12 12:33:56 -05:00
tterrag a57a240c13 Fix BlockStateProvider item models not knowing about block models
Add tests for this case
2020-12-10 21:37:13 -05:00
Richard Freimer b7fb6484d7 Override invalidateCaps instead of remove for vanilla TE capability invalidation (#7536)
Properly invalidate patched in vanilla TE caps in invalidateCaps instead of remove so that they get invalidated on chunk unload
2020-12-08 11:54:29 -08:00
Richard Freimer 1a539ffebc Make TEs invalidate capabilities when the chunk they are in unloads (#7529)
Fixed LazyOptional potentially notifying invalidation listeners multiple times.
2020-12-05 12:05:32 -08:00
Kevin G 27220a5ad8 Fixed entity navigation to stop entities spinning - MC-94054 (#7520) 2020-12-05 11:54:03 -08:00
Unbekannt1998 e975fc8252 Fix wrong function call in BlockStateProvider::horizontalFaceBlock (#7514) 2020-12-05 11:52:44 -08:00
tterrag d85ea5a3b0 Fix datagen order of multipart conditions being unstable 2020-11-28 21:10:49 -05:00
Alex O'Neill ccb7345084 Fix forge config option for default world type not applying unless you change the default world type (#7521) 2020-11-28 03:56:44 +01:00
David Quintana 93c00b67d9 Implement feature for mods to define new world types (#7448)
* Mods can now register world types via a new forge registry, and optionally register a settings screen to tweak them.
  * The default world type for dedicated servers and singleplayer world creation is configurable via forge's common config.
2020-11-28 00:57:15 +01:00
IzzelAliz cd393bbfdc Fix dimType not encode to registries (#7513) 2020-11-24 09:14:10 -08:00
Richard Freimer fd045d4628 Add support for referencing forge's resources and specifying existing mods to data generators (#7456) 2020-11-22 22:45:13 -05:00
cpw 47e076071b Fix #6692
Thanks @AterAnimAvis for help and suggestions

Signed-off-by: cpw <[email protected]>
2020-11-22 17:00:48 -05:00
Cyborgmas a73e003dd3 Fix translucent blocks not rendering properly when moved by pistons on fabulous (#7441) 2020-11-21 11:57:33 -08:00
100 changed files with 2247 additions and 306 deletions

No files matched your search

+54 -48
View File
@@ -11,8 +11,8 @@ buildscript {
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.187'
classpath 'org.ow2.asm:asm:7.2'
classpath 'org.ow2.asm:asm-tree:7.2'
classpath 'org.ow2.asm:asm:9.0'
classpath 'org.ow2.asm:asm-tree:9.0'
}
}
@@ -54,8 +54,8 @@ ext {
}
MAPPING_CHANNEL = 'snapshot'
MAPPING_VERSION = '20201028-1.16.3'
MC_VERSION = '1.16.4'
MCP_VERSION = '20201102.104115'
MC_VERSION = '1.16.5'
MCP_VERSION = '20210115.111550'
}
project(':mcp') {
@@ -197,7 +197,7 @@ project(':forge') {
}
ext {
SPEC_VERSION = '35.1' // This is overwritten by git tag, but here so dev time doesnt explode
SPEC_VERSION = '36.0' // This is overwritten by git tag, but here so dev time doesnt explode
// The new versioning sceme is <MCVersion>-<ForgeMC>.<RB>.<CommitsSinceRB>
// ForgeMC is a unique identifier for every MC version we have supported.
// Essentially, the same as the old, except dropping the first number, and the builds are no longer unique.
@@ -432,17 +432,18 @@ project(':forge') {
fmllauncherImplementation.extendsFrom(installer)
}
dependencies {
installer 'org.ow2.asm:asm:7.2'
installer 'org.ow2.asm:asm-commons:7.2'
installer 'org.ow2.asm:asm-tree:7.2'
installer 'org.ow2.asm:asm-util:7.2'
installer 'org.ow2.asm:asm-analysis:7.2'
installer 'cpw.mods:modlauncher:8.0.6'
installer 'org.ow2.asm:asm:9.0'
installer 'org.ow2.asm:asm-commons:9.0'
installer 'org.ow2.asm:asm-tree:9.0'
installer 'org.ow2.asm:asm-util:9.0'
installer 'org.ow2.asm:asm-analysis:9.0'
installer 'cpw.mods:modlauncher:8.0.+'
installer 'cpw.mods:grossjava9hacks:1.3.+'
installer 'net.minecraftforge:accesstransformers:2.2.+:shadowed'
installer 'net.minecraftforge:eventbus:3.0.+:service'
installer 'net.minecraftforge:accesstransformers:3.0.+'
installer 'org.antlr:antlr4-runtime:4.9.1' //Dep of AccessTransformer
installer 'net.minecraftforge:eventbus:4.0.+'
installer 'net.minecraftforge:forgespi:3.2.+'
installer 'net.minecraftforge:coremods:3.0.+'
installer 'net.minecraftforge:coremods:4.0.+'
installer 'net.minecraftforge:unsafe:0.2.+'
installer 'com.electronwill.night-config:core:3.6.2'
installer 'com.electronwill.night-config:toml:3.6.2'
@@ -454,6 +455,9 @@ project(':forge') {
installer 'net.minecrell:terminalconsoleappender:1.2.+'
installer 'net.sf.jopt-simple:jopt-simple:5.0.4'
installer 'org.spongepowered:mixin:0.8.2'
// This is org.openjdk.nashorn:nashorn-core:15.1.1 repackaged so it doesn't crash on JREs < 15.
// See: https://github.com/LexManos/NashornLegacyPackager
installer 'net.minecraftforge:nashorn-core-compat:15.1.1'
fmllauncherImplementation 'com.google.guava:guava:21.0'
fmllauncherImplementation 'com.google.code.gson:gson:2.8.0'
fmllauncherImplementation 'org.lwjgl:lwjgl:3.2.2'
@@ -475,35 +479,35 @@ project(':forge') {
if (changelog.exists())
extraTxts += changelog
task crowdin(type: CrowdinTask) {
key = project.hasProperty('crowdinKey') ? project.crowdinKey : null
//TODO: Merge our english.json?
}
task crowdin(type: CrowdinTask) {
key = project.hasProperty('crowdinKey') ? project.crowdinKey : null
//TODO: Merge our english.json?
}
// We apply the bin patches we just created to make a jar that is JUST our changes
['Client', 'Server', 'Joined'].each { side ->
def gen = tasks.getByName("gen${side}BinPatches")
gen.tool = BINPATCH_TOOL
task "apply${side}BinPatches"(type: ApplyBinPatches, dependsOn: gen) {
clean = { gen.cleanJar }
input = gen.output
tool = BINPATCH_TOOL
}
if (side != 'Joined') {
// Create SRG named Vanilla jars, using the SpecialSource we have in the installer
task "create${side}SRG"(type: RenameJar, dependsOn: gen) {
tool = SPECIAL_SOURCE + ':shaded'
args = ['--stable', '--in-jar', '{input}', '--out-jar', '{output}', '--srg-in', '{mappings}']
mappings = { gen.srg }
input = { gen.cleanJar }
output = file("build/create${name}SRG/output.jar")
}
}
}
['Client', 'Server', 'Joined'].each { side ->
def gen = tasks.getByName("gen${side}BinPatches")
gen.tool = BINPATCH_TOOL
task "apply${side}BinPatches"(type: ApplyBinPatches, dependsOn: gen) {
clean = { gen.cleanJar }
input = gen.output
tool = BINPATCH_TOOL
}
if (side != 'Joined') {
// Create SRG named Vanilla jars, using the SpecialSource we have in the installer
task "create${side}SRG"(type: RenameJar, dependsOn: gen) {
tool = SPECIAL_SOURCE + ':shaded'
args = ['--stable', '--in-jar', '{input}', '--out-jar', '{output}', '--srg-in', '{mappings}']
mappings = { gen.srg }
input = { gen.cleanJar }
output = file("build/create${name}SRG/output.jar")
}
}
}
task downloadLibraries(type: DownloadLibrariesTask, dependsOn: ':mcp:setupMCP') {
input = VERSION_JSON
output = rootProject.file('build/libraries/')
input = VERSION_JSON
output = rootProject.file('build/libraries/')
}
task extractInheritance(type: ExtractInheritance, dependsOn: [genJoinedBinPatches, downloadLibraries]) {
@@ -511,23 +515,23 @@ project(':forge') {
input { genJoinedBinPatches.cleanJar }
doFirst { downloadLibraries.libraries.each{ addLibrary(it) } }
}
task checkATs(type: CheckATs, dependsOn: extractInheritance) {
inheritance = extractInheritance.output
ats = patcher.accessTransformers
ats = patcher.accessTransformers
}
task checkSAS(type: CheckSAS, dependsOn: extractInheritance) {
inheritance = extractInheritance.output
sass = patcher.sideAnnotationStrippers
sass = patcher.sideAnnotationStrippers
}
task checkExcs(type: CheckExcs, dependsOn: jar) {
binary = jar.archivePath
excs = patcher.excs
excs = patcher.excs
}
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs]){}
task checkAll(dependsOn: [checkATs, checkSAS, checkExcs]){}
task checkPatchesAndFix(type: CheckPatches) {
patchDir = file("$rootDir/patches")
@@ -638,6 +642,7 @@ project(':forge') {
logo: '/big_logo.png',
minecraft: MC_VERSION,
welcome: "Welcome to the simple ${project.name.capitalize()} installer.",
mirrorList: "https://files.minecraftforge.net/mirrors-2.0.json",
data: [
MAPPINGS: [
client: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings@txt]",
@@ -758,7 +763,7 @@ project(':forge') {
// add crowdin locales
from { crowdin.output.exists() ? zipTree(crowdin.output) : null}
dependsOn crowdin
duplicatesStrategy = 'exclude'
duplicatesStrategy = 'exclude'
doFirst {
MANIFESTS.each{ pkg, values ->
@@ -949,6 +954,7 @@ project(':forge') {
exclude 'net/minecraftforge/fml/common/versioning/InvalidVersionSpecificationException.java'
exclude 'net/minecraftforge/fml/common/versioning/Restriction.java'
exclude 'net/minecraftforge/fml/common/versioning/VersionRange.java'
exclude 'net/minecraftforge/common/LenientUnboundedMapCodec.java'
tasks {
main {
@@ -59,11 +59,12 @@ public class Util {
url = "https://files.minecraftforge.net/maven/${path}"
}
//TODO remove when Mojang launcher is updated
if (!classifiers && art.classifier != null) { //Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
if (!classifiers && art.classifier != null) {
//Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
// However, keep the path normal so that our mirror system works.
art.version = "${art.version}-${art.classifier}"
art.classifier = null
art.extension = 'jar'
path = "${art.group.replace('.', '/')}/${art.name}/${art.version}/${art.name}-${art.version}.jar"
}
ret[key] = [
name: "${art.group}:${art.name}:${art.version}" + (art.classifier == null ? '' : ":${art.classifier}") + (art.extension == 'jar' ? '' : "@${art.extension}"),
+4 -4
View File
@@ -11,7 +11,7 @@ loaderVersion="[@FORGE_SPEC_VERSION@,)" #mandatory This is typically bumped ever
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license="All rights reserved"
# A URL to refer people to when problems occur with this mod
issueTrackerURL="http://my.issue.tracker/" #optional
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
@@ -22,10 +22,10 @@ modId="examplemod" #mandatory
version="${file.jarVersion}" #mandatory
# A display name for the mod
displayName="Example Mod" #mandatory
# A URL to query for updates for this mod. See the JSON update specification <here>
updateJSONURL="http://myurl.me/" #optional
# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
displayURL="http://example.com/" #optional
#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
logoFile="examplemod.png" #optional
# A text field displayed in the mod UI
@@ -144,12 +144,22 @@
public AbstractBlock.Properties func_200941_a(float p_200941_1_) {
this.field_200961_i = p_200941_1_;
return this;
@@ -933,7 +971,7 @@
@@ -932,11 +970,17 @@
return this;
}
+ @Deprecated // FORGE: Use the variant that takes a Supplier below
public AbstractBlock.Properties func_222379_b(Block p_222379_1_) {
- this.field_222381_j = p_222379_1_.func_220068_i();
+ this.lootTableSupplier = () -> p_222379_1_.delegate.get().func_220068_i();
return this;
}
+ public AbstractBlock.Properties lootFrom(java.util.function.Supplier<? extends Block> blockIn) {
+ this.lootTableSupplier = () -> blockIn.get().func_220068_i();
+ return this;
+ }
+
public AbstractBlock.Properties func_235859_g_() {
this.field_235813_o_ = true;
return this;
@@ -0,0 +1,19 @@
--- a/net/minecraft/block/BeehiveBlock.java
+++ b/net/minecraft/block/BeehiveBlock.java
@@ -85,6 +85,7 @@
List<BeeEntity> list = p_226881_1_.func_217357_a(BeeEntity.class, (new AxisAlignedBB(p_226881_2_)).func_72314_b(8.0D, 6.0D, 8.0D));
if (!list.isEmpty()) {
List<PlayerEntity> list1 = p_226881_1_.func_217357_a(PlayerEntity.class, (new AxisAlignedBB(p_226881_2_)).func_72314_b(8.0D, 6.0D, 8.0D));
+ if (list1.isEmpty()) return; //Forge: Prevent Error when no players are around.
int i = list1.size();
for(BeeEntity beeentity : list) {
@@ -105,7 +106,7 @@
int i = p_225533_1_.func_177229_b(field_226873_c_);
boolean flag = false;
if (i >= 5) {
- if (itemstack.func_77973_b() == Items.field_151097_aZ) {
+ if (itemstack.func_77973_b() instanceof net.minecraft.item.ShearsItem) {
p_225533_2_.func_184148_a(p_225533_4_, p_225533_4_.func_226277_ct_(), p_225533_4_.func_226278_cu_(), p_225533_4_.func_226281_cx_(), SoundEvents.field_226133_ah_, SoundCategory.NEUTRAL, 1.0F, 1.0F);
func_226878_a_(p_225533_2_, p_225533_3_);
itemstack.func_222118_a(1, p_225533_4_, (p_226874_1_) -> {
@@ -0,0 +1,11 @@
--- a/net/minecraft/block/PumpkinBlock.java
+++ b/net/minecraft/block/PumpkinBlock.java
@@ -20,7 +20,7 @@
public ActionResultType func_225533_a_(BlockState p_225533_1_, World p_225533_2_, BlockPos p_225533_3_, PlayerEntity p_225533_4_, Hand p_225533_5_, BlockRayTraceResult p_225533_6_) {
ItemStack itemstack = p_225533_4_.func_184586_b(p_225533_5_);
- if (itemstack.func_77973_b() == Items.field_151097_aZ) {
+ if (itemstack.func_77973_b() instanceof net.minecraft.item.ShearsItem) {
if (!p_225533_2_.field_72995_K) {
Direction direction = p_225533_6_.func_216354_b();
Direction direction1 = direction.func_176740_k() == Direction.Axis.Y ? p_225533_4_.func_174811_aO().func_176734_d() : direction;
@@ -0,0 +1,10 @@
--- a/net/minecraft/block/SoundType.java
+++ b/net/minecraft/block/SoundType.java
@@ -59,6 +59,7 @@
private final SoundEvent field_185865_r;
private final SoundEvent field_185866_s;
+ @Deprecated // Forge: Use {@link net.minecraftforge.common.util.ForgeSoundType} instead for suppliers
public SoundType(float p_i46679_1_, float p_i46679_2_, SoundEvent p_i46679_3_, SoundEvent p_i46679_4_, SoundEvent p_i46679_5_, SoundEvent p_i46679_6_, SoundEvent p_i46679_7_) {
this.field_185860_m = p_i46679_1_;
this.field_185861_n = p_i46679_2_;
@@ -0,0 +1,11 @@
--- a/net/minecraft/block/TripWireBlock.java
+++ b/net/minecraft/block/TripWireBlock.java
@@ -67,7 +67,7 @@
}
public void func_176208_a(World p_176208_1_, BlockPos p_176208_2_, BlockState p_176208_3_, PlayerEntity p_176208_4_) {
- if (!p_176208_1_.field_72995_K && !p_176208_4_.func_184614_ca().func_190926_b() && p_176208_4_.func_184614_ca().func_77973_b() == Items.field_151097_aZ) {
+ if (!p_176208_1_.field_72995_K && !p_176208_4_.func_184614_ca().func_190926_b() && p_176208_4_.func_184614_ca().func_77973_b() instanceof net.minecraft.item.ShearsItem) {
p_176208_1_.func_180501_a(p_176208_2_, p_176208_3_.func_206870_a(field_176295_N, Boolean.valueOf(true)), 4);
}
@@ -9,3 +9,11 @@
if (monitor != null) {
VideoMode videomode = monitor.func_197992_a(this.field_198125_l ? this.field_198124_k : Optional.empty());
this.field_198120_g = this.field_198127_n = monitor.func_197989_c() + videomode.func_198064_a() / 2 - this.field_198129_p / 2;
@@ -271,6 +271,7 @@
GLFW.glfwGetFramebufferSize(this.field_198119_f, aint, aint1);
this.field_198131_r = aint[0];
this.field_198132_s = aint1[0];
+ if (this.field_198132_s == 0 || this.field_198131_r==0) net.minecraftforge.fml.loading.progress.EarlyProgressVisualization.INSTANCE.updateFBSize(w->this.field_198131_r=w, h->this.field_198132_s=h);
}
private void func_198089_c(long p_198089_1_, int p_198089_3_, int p_198089_4_) {
@@ -0,0 +1,21 @@
--- a/net/minecraft/client/gui/screen/BiomeGeneratorTypeScreens.java
+++ b/net/minecraft/client/gui/screen/BiomeGeneratorTypeScreens.java
@@ -113,6 +113,9 @@
private BiomeGeneratorTypeScreens(String p_i232324_1_) {
this.field_239076_k_ = new TranslationTextComponent("generator." + p_i232324_1_);
}
+ public BiomeGeneratorTypeScreens(ITextComponent displayName) {
+ this.field_239076_k_ = displayName;
+ }
private static DimensionGeneratorSettings func_243452_a(DynamicRegistries p_243452_0_, DimensionGeneratorSettings p_243452_1_, BiomeGeneratorTypeScreens p_243452_2_, Biome p_243452_3_) {
BiomeProvider biomeprovider = new SingleBiomeProvider(p_243452_3_);
@@ -166,4 +169,8 @@
public interface IFactory {
Screen createEditScreen(CreateWorldScreen p_createEditScreen_1_, DimensionGeneratorSettings p_createEditScreen_2_);
}
+
+ // Forge start
+ // For internal use only, automatically called for all ForgeWorldTypes. Register your ForgeWorldType in the forge registry!
+ public static void registerGenerator(BiomeGeneratorTypeScreens gen) { field_239068_c_.add(gen); }
}
@@ -1,5 +1,14 @@
--- a/net/minecraft/client/gui/screen/CreateWorldScreen.java
+++ b/net/minecraft/client/gui/screen/CreateWorldScreen.java
@@ -110,7 +110,7 @@
public static CreateWorldScreen func_243425_a(@Nullable Screen p_243425_0_) {
DynamicRegistries.Impl dynamicregistries$impl = DynamicRegistries.func_239770_b_();
- return new CreateWorldScreen(p_243425_0_, DatapackCodec.field_234880_a_, new WorldOptionsScreen(dynamicregistries$impl, DimensionGeneratorSettings.func_242751_a(dynamicregistries$impl.func_243612_b(Registry.field_239698_ad_), dynamicregistries$impl.func_243612_b(Registry.field_239720_u_), dynamicregistries$impl.func_243612_b(Registry.field_243549_ar)), Optional.of(BiomeGeneratorTypeScreens.field_239066_a_), OptionalLong.empty()));
+ return new CreateWorldScreen(p_243425_0_, DatapackCodec.field_234880_a_, new WorldOptionsScreen(dynamicregistries$impl, net.minecraftforge.client.ForgeHooksClient.getDefaultWorldType().map(type -> type.func_241220_a_(dynamicregistries$impl, new java.util.Random().nextLong(), true, false)).orElseGet(() -> DimensionGeneratorSettings.func_242751_a(dynamicregistries$impl.func_243612_b(Registry.field_239698_ad_), dynamicregistries$impl.func_243612_b(Registry.field_239720_u_), dynamicregistries$impl.func_243612_b(Registry.field_243549_ar))), net.minecraftforge.client.ForgeHooksClient.getDefaultWorldType(), OptionalLong.empty()));
}
private CreateWorldScreen(@Nullable Screen p_i242063_1_, DatapackCodec p_i242063_2_, WorldOptionsScreen p_i242063_3_) {
@@ -542,6 +542,7 @@
File file1 = path.toFile();
if (this.field_243416_G == null) {
@@ -0,0 +1,19 @@
--- a/net/minecraft/client/gui/screen/WorldOptionsScreen.java
+++ b/net/minecraft/client/gui/screen/WorldOptionsScreen.java
@@ -134,6 +134,7 @@
this.field_239035_i_.field_230693_o_ = this.field_239040_n_.isPresent();
this.field_239036_j_ = p_239048_1_.func_230480_a_(new Button(j, 120, 150, 20, new TranslationTextComponent("selectWorld.customizeType"), (p_239044_3_) -> {
BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory = BiomeGeneratorTypeScreens.field_239069_d_.get(this.field_239040_n_);
+ biomegeneratortypescreens$ifactory = net.minecraftforge.client.ForgeHooksClient.getBiomeGeneratorTypeScreenFactory(this.field_239040_n_, biomegeneratortypescreens$ifactory);
if (biomegeneratortypescreens$ifactory != null) {
p_239048_2_.func_147108_a(biomegeneratortypescreens$ifactory.createEditScreen(p_239048_1_, this.field_239039_m_));
}
@@ -292,7 +293,7 @@
} else {
this.field_239034_h_.field_230694_p_ = p_239059_1_;
this.field_239027_a_.field_230694_p_ = p_239059_1_;
- this.field_239036_j_.field_230694_p_ = p_239059_1_ && BiomeGeneratorTypeScreens.field_239069_d_.containsKey(this.field_239040_n_);
+ this.field_239036_j_.field_230694_p_ = p_239059_1_ && (BiomeGeneratorTypeScreens.field_239069_d_.containsKey(this.field_239040_n_) || net.minecraftforge.client.ForgeHooksClient.hasBiomeGeneratorSettingsOptionsScreen(this.field_239040_n_));
this.field_239037_k_.field_230694_p_ = p_239059_1_;
}
@@ -101,7 +101,7 @@
} else {
ItemStack itemstack = p_217292_1_.func_184586_b(p_217292_3_);
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks
+ .onRightClickBlock(p_217292_1_, p_217292_3_, blockpos, p_217292_4_.func_216354_b());
+ .onRightClickBlock(p_217292_1_, p_217292_3_, blockpos, p_217292_4_);
+ if (event.isCanceled()) {
+ this.field_78774_b.func_147297_a(new CPlayerTryUseItemOnBlockPacket(p_217292_3_, p_217292_4_));
+ return event.getCancellationResult();
@@ -122,7 +122,7 @@
+ boolean flag = !p_217292_1_.func_184614_ca().doesSneakBypassUse(p_217292_2_,blockpos,p_217292_1_) || !p_217292_1_.func_184592_cb().doesSneakBypassUse(p_217292_2_,blockpos,p_217292_1_);
boolean flag1 = p_217292_1_.func_226563_dT_() && flag;
- if (!flag1) {
+ if (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1) {
+ if (event.getUseBlock() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1)) {
ActionResultType actionresulttype = p_217292_2_.func_180495_p(blockpos).func_227031_a_(p_217292_2_, p_217292_1_, p_217292_3_, p_217292_4_);
if (actionresulttype.func_226246_a_()) {
this.field_78774_b.func_147297_a(new CPlayerTryUseItemOnBlockPacket(p_217292_3_, p_217292_4_));
@@ -130,9 +130,10 @@
}
this.field_78774_b.func_147297_a(new CPlayerTryUseItemOnBlockPacket(p_217292_3_, p_217292_4_));
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return ActionResultType.PASS;
if (!itemstack.func_190926_b() && !p_217292_1_.func_184811_cZ().func_185141_a(itemstack.func_77973_b())) {
- if (!itemstack.func_190926_b() && !p_217292_1_.func_184811_cZ().func_185141_a(itemstack.func_77973_b())) {
- ItemUseContext itemusecontext = new ItemUseContext(p_217292_1_, p_217292_3_, p_217292_4_);
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return ActionResultType.PASS;
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (!itemstack.func_190926_b() && !p_217292_1_.func_184811_cZ().func_185141_a(itemstack.func_77973_b()))) {
ActionResultType actionresulttype1;
if (this.field_78779_k.func_77145_d()) {
int i = itemstack.func_190916_E();
@@ -12,7 +12,19 @@
float f = this.field_72777_q.field_71441_e.func_72867_j(p_228438_2_);
if (!(f <= 0.0F)) {
p_228438_1_.func_205109_c();
@@ -830,7 +835,7 @@
@@ -347,6 +352,11 @@
}
public void func_228436_a_(ActiveRenderInfo p_228436_1_) {
+ net.minecraftforge.client.IWeatherParticleRenderHandler renderHandler = field_72769_h.func_239132_a_().getWeatherParticleRenderHandler();
+ if (renderHandler != null) {
+ renderHandler.render(field_72773_u, field_72769_h, field_72777_q, p_228436_1_);
+ return;
+ }
float f = this.field_72777_q.field_71441_e.func_72867_j(1.0F) / (Minecraft.func_71375_t() ? 1.0F : 2.0F);
if (!(f <= 0.0F)) {
Random random = new Random((long)this.field_72773_u * 312987231L);
@@ -830,7 +840,7 @@
this.field_147595_R = true;
BlockPos blockpos2 = chunkrenderdispatcher$chunkrender4.func_178568_j().func_177982_a(8, 8, 8);
boolean flag1 = blockpos2.func_177951_i(blockpos) < 768.0D;
@@ -21,7 +33,7 @@
this.field_175009_l.add(chunkrenderdispatcher$chunkrender4);
} else {
this.field_72777_q.func_213239_aq().func_76320_a("build near");
@@ -915,13 +920,13 @@
@@ -915,13 +925,13 @@
float f = p_228426_7_.func_205001_m();
boolean flag1 = this.field_72777_q.field_71441_e.func_239132_a_().func_230493_a_(MathHelper.func_76128_c(d0), MathHelper.func_76128_c(d1)) || this.field_72777_q.field_71456_v.func_184046_j().func_184056_f();
if (this.field_72777_q.field_71474_y.field_151451_c >= 4) {
@@ -37,7 +49,7 @@
iprofiler.func_219895_b("terrain_setup");
this.func_228437_a_(p_228426_6_, clippinghelper, flag, this.field_228409_ai_++, this.field_72777_q.field_71439_g.func_175149_v());
iprofiler.func_219895_b("updatechunks");
@@ -942,7 +947,9 @@
@@ -942,7 +952,9 @@
this.func_174967_a(p_228426_3_ + l1);
iprofiler.func_219895_b("terrain");
this.func_228441_a_(RenderType.func_228639_c_(), p_228426_1_, d0, d1, d2);
@@ -47,7 +59,7 @@
this.func_228441_a_(RenderType.func_228643_e_(), p_228426_1_, d0, d1, d2);
if (this.field_72769_h.func_239132_a_().func_239217_c_()) {
RenderHelper.func_237533_a_(p_228426_1_.func_227866_c_().func_227870_a_());
@@ -972,7 +979,7 @@
@@ -972,7 +984,7 @@
IRenderTypeBuffer.Impl irendertypebuffer$impl = this.field_228415_m_.func_228487_b_();
for(Entity entity : this.field_72769_h.func_217416_b()) {
@@ -56,7 +68,7 @@
++this.field_72749_I;
if (entity.field_70173_aa == 0) {
entity.field_70142_S = entity.func_226277_ct_();
@@ -1010,6 +1017,7 @@
@@ -1010,6 +1022,7 @@
List<TileEntity> list = worldrenderer$localrenderinformationcontainer.field_178036_a.func_178571_g().func_178485_b();
if (!list.isEmpty()) {
for(TileEntity tileentity1 : list) {
@@ -64,7 +76,7 @@
BlockPos blockpos3 = tileentity1.func_174877_v();
IRenderTypeBuffer irendertypebuffer1 = irendertypebuffer$impl;
p_228426_1_.func_227860_a_();
@@ -1035,6 +1043,7 @@
@@ -1035,6 +1048,7 @@
synchronized(this.field_181024_n) {
for(TileEntity tileentity : this.field_181024_n) {
@@ -72,7 +84,7 @@
BlockPos blockpos2 = tileentity.func_174877_v();
p_228426_1_.func_227860_a_();
p_228426_1_.func_227861_a_((double)blockpos2.func_177958_n() - d0, (double)blockpos2.func_177956_o() - d1, (double)blockpos2.func_177952_p() - d2);
@@ -1084,10 +1093,13 @@
@@ -1084,10 +1098,13 @@
iprofiler.func_219895_b("outline");
BlockPos blockpos = ((BlockRayTraceResult)raytraceresult).func_216350_a();
BlockState blockstate = this.field_72769_h.func_180495_p(blockpos);
@@ -87,7 +99,7 @@
}
RenderSystem.pushMatrix();
@@ -1119,7 +1131,7 @@
@@ -1119,7 +1136,7 @@
this.field_239224_H_.func_237506_a_(this.field_72777_q.func_147110_a());
RenderState.field_239237_T_.func_228547_a_();
iprofiler.func_219895_b("particles");
@@ -96,7 +108,7 @@
RenderState.field_239237_T_.func_228549_b_();
} else {
iprofiler.func_219895_b("translucent");
@@ -1129,7 +1141,7 @@
@@ -1129,7 +1146,7 @@
iprofiler.func_219895_b("string");
this.func_228441_a_(RenderType.func_241715_r_(), p_228426_1_, d0, d1, d2);
iprofiler.func_219895_b("particles");
@@ -105,7 +117,7 @@
}
RenderSystem.pushMatrix();
@@ -1481,6 +1493,11 @@
@@ -1481,6 +1498,11 @@
}
public void func_228424_a_(MatrixStack p_228424_1_, float p_228424_2_) {
@@ -117,7 +129,7 @@
if (this.field_72777_q.field_71441_e.func_239132_a_().func_241683_c_() == DimensionRenderInfo.FogType.END) {
this.func_228444_b_(p_228424_1_);
} else if (this.field_72777_q.field_71441_e.func_239132_a_().func_241683_c_() == DimensionRenderInfo.FogType.NORMAL) {
@@ -1609,6 +1626,11 @@
@@ -1609,6 +1631,11 @@
}
public void func_228425_a_(MatrixStack p_228425_1_, float p_228425_2_, double p_228425_3_, double p_228425_5_, double p_228425_7_) {
@@ -129,7 +141,7 @@
float f = this.field_72769_h.func_239132_a_().func_239213_a_();
if (!Float.isNaN(f)) {
RenderSystem.disableCull();
@@ -1792,7 +1814,7 @@
@@ -1792,7 +1819,7 @@
while(iterator.hasNext()) {
ChunkRenderDispatcher.ChunkRender chunkrenderdispatcher$chunkrender = iterator.next();
@@ -138,7 +150,7 @@
this.field_174995_M.func_228902_a_(chunkrenderdispatcher$chunkrender);
} else {
chunkrenderdispatcher$chunkrender.func_228929_a_(this.field_174995_M);
@@ -2076,7 +2098,12 @@
@@ -2076,7 +2103,12 @@
this.field_175008_n.func_217628_a(p_215319_1_, p_215319_2_, p_215319_3_, p_215319_4_);
}
@@ -151,7 +163,7 @@
ISound isound = this.field_147593_P.get(p_184377_2_);
if (isound != null) {
this.field_72777_q.func_147118_V().func_147683_b(isound);
@@ -2084,7 +2111,7 @@
@@ -2084,7 +2116,7 @@
}
if (p_184377_1_ != null) {
@@ -160,7 +172,7 @@
if (musicdiscitem != null) {
this.field_72777_q.field_71456_v.func_238451_a_(musicdiscitem.func_234801_g_());
}
@@ -2232,7 +2259,7 @@
@@ -2232,7 +2264,7 @@
break;
case 1010:
if (Item.func_150899_d(p_180439_4_) instanceof MusicDiscItem) {
@@ -169,7 +181,7 @@
} else {
this.func_184377_a((SoundEvent)null, p_180439_3_);
}
@@ -2382,8 +2409,8 @@
@@ -2382,8 +2414,8 @@
break;
case 2001:
BlockState blockstate = Block.func_196257_b(p_180439_4_);
@@ -180,7 +192,7 @@
this.field_72769_h.func_184156_a(p_180439_3_, soundtype.func_185845_c(), SoundCategory.BLOCKS, (soundtype.func_185843_a() + 1.0F) / 2.0F, soundtype.func_185847_b() * 0.8F, false);
}
@@ -2531,7 +2558,7 @@
@@ -2531,7 +2563,7 @@
} else {
int i = p_228420_0_.func_226658_a_(LightType.SKY, p_228420_2_);
int j = p_228420_0_.func_226658_a_(LightType.BLOCK, p_228420_2_);
@@ -189,7 +201,7 @@
if (j < k) {
j = k;
}
@@ -2570,6 +2597,11 @@
@@ -2570,6 +2602,11 @@
return this.field_239226_J_;
}
@@ -1,16 +1,14 @@
--- a/net/minecraft/client/renderer/tileentity/PistonTileEntityRenderer.java
+++ b/net/minecraft/client/renderer/tileentity/PistonTileEntityRenderer.java
@@ -61,8 +61,12 @@
@@ -61,8 +61,11 @@
}
private void func_228876_a_(BlockPos p_228876_1_, BlockState p_228876_2_, MatrixStack p_228876_3_, IRenderTypeBuffer p_228876_4_, World p_228876_5_, boolean p_228876_6_, int p_228876_7_) {
- RenderType rendertype = RenderTypeLookup.func_239221_b_(p_228876_2_);
+ net.minecraft.client.renderer.RenderType.func_228661_n_().stream().filter(t -> RenderTypeLookup.canRenderInLayer(p_228876_2_, t)).forEach(rendertype -> {
+ net.minecraftforge.client.ForgeHooksClient.setRenderLayer(rendertype);
+ net.minecraftforge.client.ForgeHooksClient.renderPistonMovedBlocks(p_228876_1_, p_228876_2_, p_228876_3_, p_228876_4_, p_228876_5_, p_228876_6_, p_228876_7_, field_178462_c == null ? field_178462_c = Minecraft.func_71410_x().func_175602_ab() : field_178462_c);
+ if(false) {
RenderType rendertype = RenderTypeLookup.func_239221_b_(p_228876_2_);
IVertexBuilder ivertexbuilder = p_228876_4_.getBuffer(rendertype);
+ if (field_178462_c == null) field_178462_c = Minecraft.func_71410_x().func_175602_ab();
this.field_178462_c.func_175019_b().func_228802_a_(p_228876_5_, this.field_178462_c.func_184389_a(p_228876_2_), p_228876_2_, p_228876_1_, p_228876_3_, ivertexbuilder, p_228876_6_, new Random(), p_228876_2_.func_209533_a(p_228876_1_), p_228876_7_);
+ });
+ net.minecraftforge.client.ForgeHooksClient.setRenderLayer(null);
+ }
}
}
@@ -1,22 +1,26 @@
--- a/net/minecraft/client/world/DimensionRenderInfo.java
+++ b/net/minecraft/client/world/DimensionRenderInfo.java
@@ -26,6 +26,9 @@
@@ -26,6 +26,10 @@
private final DimensionRenderInfo.FogType field_241680_e_;
private final boolean field_241681_f_;
private final boolean field_239212_e_;
+ private net.minecraftforge.client.IWeatherRenderHandler weatherRenderHandler = null;
+ private net.minecraftforge.client.IWeatherParticleRenderHandler weatherParticleRenderHandler = null;
+ private net.minecraftforge.client.ISkyRenderHandler skyRenderHandler = null;
+ private net.minecraftforge.client.ICloudRenderHandler cloudRenderHandler = null;
public DimensionRenderInfo(float p_i241259_1_, boolean p_i241259_2_, DimensionRenderInfo.FogType p_i241259_3_, boolean p_i241259_4_, boolean p_i241259_5_) {
this.field_239210_c_ = p_i241259_1_;
@@ -82,6 +85,28 @@
@@ -82,6 +86,35 @@
return this.field_239212_e_;
}
+ public void setWeatherRenderHandler(net.minecraftforge.client.IWeatherRenderHandler weatherRenderHandler) {
+ this.weatherRenderHandler = weatherRenderHandler;
+ }
+ public void setWeatherParticleRenderHandler(net.minecraftforge.client.IWeatherParticleRenderHandler weatherParticleRenderHandler) {
+ this.weatherParticleRenderHandler = weatherParticleRenderHandler;
+ }
+ public void setSkyRenderHandler(net.minecraftforge.client.ISkyRenderHandler skyRenderHandler) {
+ this.skyRenderHandler = skyRenderHandler;
+ }
@@ -32,6 +36,10 @@
+ return weatherRenderHandler;
+ }
+ @Nullable
+ public net.minecraftforge.client.IWeatherParticleRenderHandler getWeatherParticleRenderHandler() {
+ return weatherParticleRenderHandler;
+ }
+ @Nullable
+ public net.minecraftforge.client.ISkyRenderHandler getSkyRenderHandler() {
+ return skyRenderHandler;
+ }
@@ -1,10 +1,11 @@
--- a/net/minecraft/data/Main.java
+++ b/net/minecraft/data/Main.java
@@ -21,8 +21,12 @@
@@ -21,8 +21,13 @@
OptionSpec<Void> optionspec6 = optionparser.accepts("all", "Include all generators");
OptionSpec<String> optionspec7 = optionparser.accepts("output", "Output folder").withRequiredArg().defaultsTo("generated");
OptionSpec<String> optionspec8 = optionparser.accepts("input", "Input folder").withRequiredArg();
+ OptionSpec<String> existing = optionparser.accepts("existing", "Existing resource packs that generated resources can reference").withRequiredArg();
+ OptionSpec<String> existingMod = optionparser.accepts("existing-mod", "Existing mods that generated resources can reference the resource packs of").withRequiredArg();
+ OptionSpec<java.io.File> gameDir = optionparser.accepts("gameDir").withRequiredArg().ofType(java.io.File.class).defaultsTo(new java.io.File(".")).required(); //Need by modlauncher, so lets just eat it
+ OptionSpec<String> mod = optionparser.accepts("mod", "A modid to dump").withRequiredArg().withValuesSeparatedBy(",");
+ OptionSpec<Void> flat = optionparser.accepts("flat", "Do not append modid prefix to output directory when generating for multiple mods");
@@ -14,7 +15,7 @@
Path path = Paths.get(optionspec7.value(optionset));
boolean flag = optionset.has(optionspec6);
boolean flag1 = flag || optionset.has(optionspec2);
@@ -30,10 +34,13 @@
@@ -30,10 +35,14 @@
boolean flag3 = flag || optionset.has(optionspec3);
boolean flag4 = flag || optionset.has(optionspec4);
boolean flag5 = flag || optionset.has(optionspec5);
@@ -24,9 +25,10 @@
- datagenerator.func_200392_c();
+ Collection<Path> inputs = optionset.valuesOf(optionspec8).stream().map(Paths::get).collect(Collectors.toList());
+ Collection<Path> existingPacks = optionset.valuesOf(existing).stream().map(Paths::get).collect(Collectors.toList());
+ java.util.Set<String> existingMods = new java.util.HashSet<>(optionset.valuesOf(existingMod));
+ java.util.Set<String> mods = new java.util.HashSet<>(optionset.valuesOf(mod));
+ boolean isFlat = mods.isEmpty() || optionset.has(flat);
+ net.minecraftforge.fml.DatagenModLoader.begin(mods, path, inputs, existingPacks, flag2, flag1, flag3, flag4, flag5, isFlat);
+ net.minecraftforge.fml.DatagenModLoader.begin(mods, path, inputs, existingPacks, existingMods, flag2, flag1, flag3, flag4, flag5, isFlat);
+ if (mods.contains("minecraft") || mods.isEmpty())
+ func_200264_a(isFlat ? path : path.resolve("minecraft"), inputs, flag1, flag2, flag3, flag4, flag5).func_200392_c();
} else {
@@ -1,11 +1,12 @@
--- a/net/minecraft/data/TagsProvider.java
+++ b/net/minecraft/data/TagsProvider.java
@@ -28,10 +28,18 @@
@@ -28,10 +28,20 @@
protected final DataGenerator field_200433_a;
protected final Registry<T> field_200435_c;
protected final Map<ResourceLocation, ITag.Builder> field_200434_b = Maps.newLinkedHashMap();
+ protected final String modId;
+ protected final net.minecraftforge.common.data.ExistingFileHelper existingFileHelper;
+ private final net.minecraftforge.common.data.ExistingFileHelper.IResourceType resourceType;
+ @Deprecated//Forge, Use ModID version.
protected TagsProvider(DataGenerator p_i49827_1_, Registry<T> p_i49827_2_) {
@@ -16,10 +17,11 @@
this.field_200435_c = p_i49827_2_;
+ this.modId = modId;
+ this.existingFileHelper = existingFileHelper;
+ this.resourceType = new net.minecraftforge.common.data.ExistingFileHelper.ResourceType(net.minecraft.resources.ResourcePackType.SERVER_DATA, ".json", "tags/" + getTagFolder());
}
protected abstract void func_200432_c();
@@ -47,12 +55,14 @@
@@ -47,12 +57,14 @@
return this.field_200435_c.func_241873_b(p_240527_1_).orElse((T)null);
};
this.field_200434_b.forEach((p_240524_4_, p_240524_5_) -> {
@@ -35,7 +37,7 @@
try {
String s = field_200437_e.toJson((JsonElement)jsonobject);
@@ -74,11 +84,26 @@
@@ -74,20 +86,36 @@
});
}
@@ -44,7 +46,7 @@
+ // We only care about non-optional tag entries, this is the only type that can reference a resource and needs validation
+ // Optional tags should not be validated
+ if (entry instanceof ITag.TagEntry) {
+ return existingFileHelper == null || !existingFileHelper.exists(((ITag.TagEntry)entry).getId(), net.minecraft.resources.ResourcePackType.SERVER_DATA, ".json", "tags/" + getTagFolder());
+ return existingFileHelper == null || !existingFileHelper.exists(((ITag.TagEntry)entry).getId(), resourceType);
+ }
+ return false;
+ }
@@ -63,7 +65,9 @@
}
protected ITag.Builder func_240525_b_(ITag.INamedTag<T> p_240525_1_) {
@@ -87,7 +112,7 @@
return this.field_200434_b.computeIfAbsent(p_240525_1_.func_230234_a_(), (p_240526_0_) -> {
+ existingFileHelper.trackGenerated(p_240526_0_, resourceType);
return new ITag.Builder();
});
}
@@ -72,7 +76,7 @@
private final ITag.Builder field_240528_a_;
private final Registry<T> field_240529_b_;
private final String field_240530_c_;
@@ -115,5 +140,18 @@
@@ -115,5 +143,18 @@
});
return this;
}
@@ -0,0 +1,10 @@
--- a/net/minecraft/enchantment/EfficiencyEnchantment.java
+++ b/net/minecraft/enchantment/EfficiencyEnchantment.java
@@ -22,6 +22,6 @@
}
public boolean func_92089_a(ItemStack p_92089_1_) {
- return p_92089_1_.func_77973_b() == Items.field_151097_aZ ? true : super.func_92089_a(p_92089_1_);
+ return p_92089_1_.func_77973_b() instanceof net.minecraft.item.ShearsItem ? true : super.func_92089_a(p_92089_1_);
}
}
@@ -481,7 +481,7 @@
}
public boolean func_70094_T() {
@@ -3082,6 +3138,60 @@
@@ -3082,6 +3138,58 @@
this.func_213361_c(p_213334_1_ == Hand.MAIN_HAND ? EquipmentSlotType.MAINHAND : EquipmentSlotType.OFFHAND);
}
@@ -531,12 +531,10 @@
+ }
+
+ @Override
+ public void remove(boolean keepData) {
+ super.remove(keepData);
+ if (!keepData) {
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
+
@OnlyIn(Dist.CLIENT)
@@ -0,0 +1,22 @@
--- a/net/minecraft/entity/ai/goal/TriggerSkeletonTrapGoal.java
+++ b/net/minecraft/entity/ai/goal/TriggerSkeletonTrapGoal.java
@@ -28,6 +28,10 @@
public void func_75246_d() {
ServerWorld serverworld = (ServerWorld)this.field_188516_a.field_70170_p;
+ // Forge: Trigger the trap in a tick task to avoid crashes when mods add goals to skeleton horses
+ // (MC-206338/Forge PR #7509)
+ serverworld.func_73046_m().func_212871_a_(new net.minecraft.util.concurrent.TickDelayedTask(serverworld.func_73046_m().func_71259_af(), () -> {
+ if (!this.field_188516_a.func_70089_S()) return;
DifficultyInstance difficultyinstance = serverworld.func_175649_E(this.field_188516_a.func_233580_cy_());
this.field_188516_a.func_190691_p(false);
this.field_188516_a.func_110234_j(true);
@@ -47,7 +51,7 @@
abstracthorseentity.func_70024_g(this.field_188516_a.func_70681_au().nextGaussian() * 0.5D, 0.0D, this.field_188516_a.func_70681_au().nextGaussian() * 0.5D);
serverworld.func_242417_l(abstracthorseentity);
}
-
+ }));
}
private AbstractHorseEntity func_188515_a(DifficultyInstance p_188515_1_) {
@@ -1,6 +1,6 @@
--- a/net/minecraft/entity/item/minecart/ContainerMinecartEntity.java
+++ b/net/minecraft/entity/item/minecart/ContainerMinecartEntity.java
@@ -118,17 +118,19 @@
@@ -118,17 +118,18 @@
}
@Nullable
@@ -20,11 +20,10 @@
- super.func_70106_y();
+ super.remove(keepData);
+ if (!keepData) itemHandler.invalidate();
}
protected void func_213281_b(CompoundNBT p_213281_1_) {
@@ -157,6 +159,8 @@
@@ -157,6 +158,8 @@
}
public ActionResultType func_184230_a(PlayerEntity p_184230_1_, Hand p_184230_2_) {
@@ -33,7 +32,7 @@
p_184230_1_.func_213829_a(this);
if (!p_184230_1_.field_70170_p.field_72995_K) {
PiglinTasks.func_234478_a_(p_184230_1_, true);
@@ -185,6 +189,8 @@
@@ -185,6 +188,8 @@
this.field_184290_c = null;
LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld)this.field_70170_p)).func_216015_a(LootParameters.field_237457_g_, this.func_213303_ch()).func_216016_a(this.field_184291_d);
@@ -42,7 +41,7 @@
if (p_184288_1_ != null) {
lootcontext$builder.func_186469_a(p_184288_1_.func_184817_da()).func_216015_a(LootParameters.field_216281_a, p_184288_1_);
}
@@ -215,4 +221,17 @@
@@ -215,4 +220,23 @@
}
protected abstract Container func_213968_a(int p_213968_1_, PlayerInventory p_213968_2_);
@@ -56,6 +55,12 @@
+ return super.getCapability(capability, facing);
+ }
+
+ @Override
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ itemHandler.invalidate();
+ }
+
+ public void dropContentsWhenDead(boolean value) {
+ this.field_94112_b = value;
+ }
@@ -19,3 +19,20 @@
}
@OnlyIn(Dist.CLIENT)
@@ -687,7 +688,7 @@
}
public void func_241841_a(ServerWorld p_241841_1_, LightningBoltEntity p_241841_2_) {
- if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL) {
+ if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_200759_ay, (timer) -> {})) {
field_184243_a.info("Villager {} was struck by lightning {}.", this, p_241841_2_);
WitchEntity witchentity = EntityType.field_200759_ay.func_200721_a(p_241841_1_);
witchentity.func_70012_b(this.func_226277_ct_(), this.func_226278_cu_(), this.func_226281_cx_(), this.field_70177_z, this.field_70125_A);
@@ -699,6 +700,7 @@
}
witchentity.func_110163_bv();
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, witchentity);
p_241841_1_.func_242417_l(witchentity);
this.func_242369_fq();
this.func_70106_y();
@@ -0,0 +1,19 @@
--- a/net/minecraft/entity/monster/HoglinEntity.java
+++ b/net/minecraft/entity/monster/HoglinEntity.java
@@ -117,7 +117,7 @@
HoglinTasks.func_234377_a_(this);
if (this.func_234364_eK_()) {
++this.field_234358_by_;
- if (this.field_234358_by_ > 300) {
+ if (this.field_234358_by_ > 300 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_233590_aW_, (timer) -> this.field_234358_by_ = timer)) {
this.func_241412_a_(SoundEvents.field_232715_fE_);
this.func_234360_a_((ServerWorld)this.field_70170_p);
}
@@ -212,6 +212,7 @@
ZoglinEntity zoglinentity = this.func_233656_b_(EntityType.field_233590_aW_, true);
if (zoglinentity != null) {
zoglinentity.func_195064_c(new EffectInstance(Effects.field_76431_k, 200, 0));
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zoglinentity);
}
}
@@ -1,11 +0,0 @@
--- a/net/minecraft/entity/monster/PhantomEntity.java
+++ b/net/minecraft/entity/monster/PhantomEntity.java
@@ -214,7 +214,7 @@
this.field_203142_b = 60;
List<PlayerEntity> list = PhantomEntity.this.field_70170_p.func_217373_a(this.field_220842_b, PhantomEntity.this, PhantomEntity.this.func_174813_aQ().func_72314_b(16.0D, 64.0D, 16.0D));
if (!list.isEmpty()) {
- list.sort(Comparator.comparing(Entity::func_226278_cu_).reversed());
+ list.sort(Comparator.<Entity, Double>comparing(Entity::func_226278_cu_).reversed());
for(PlayerEntity playerentity : list) {
if (PhantomEntity.this.func_213344_a(playerentity, EntityPredicate.field_221016_a)) {
@@ -1,6 +1,24 @@
--- a/net/minecraft/entity/monster/ZombieEntity.java
+++ b/net/minecraft/entity/monster/ZombieEntity.java
@@ -268,12 +268,16 @@
@@ -186,7 +186,8 @@
if (!this.field_70170_p.field_72995_K && this.func_70089_S() && !this.func_175446_cd()) {
if (this.func_204706_dD()) {
--this.field_204708_bE;
- if (this.field_204708_bE < 0) {
+
+ if (this.field_204708_bE < 0 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_200725_aD, (timer) -> this.field_204708_bE = timer)) {
this.func_207302_dI();
}
} else if (this.func_204703_dA()) {
@@ -248,6 +249,7 @@
if (zombieentity != null) {
zombieentity.func_207304_a(zombieentity.field_70170_p.func_175649_E(zombieentity.func_233580_cy_()).func_180170_c());
zombieentity.func_146070_a(zombieentity.func_204900_dz() && this.func_146072_bX());
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zombieentity);
}
}
@@ -268,12 +270,16 @@
livingentity = (LivingEntity)p_70097_1_.func_76346_g();
}
@@ -19,7 +37,7 @@
for(int l = 0; l < 50; ++l) {
int i1 = i + MathHelper.func_76136_a(this.field_70146_Z, 7, 40) * MathHelper.func_76136_a(this.field_70146_Z, -1, 1);
int j1 = j + MathHelper.func_76136_a(this.field_70146_Z, 7, 40) * MathHelper.func_76136_a(this.field_70146_Z, -1, 1);
@@ -284,6 +288,7 @@
@@ -284,6 +290,7 @@
if (WorldEntitySpawner.func_209382_a(entityspawnplacementregistry$placementtype, this.field_70170_p, blockpos, entitytype) && EntitySpawnPlacementRegistry.func_223515_a(entitytype, serverworld, SpawnReason.REINFORCEMENT, blockpos, this.field_70170_p.field_73012_v)) {
zombieentity.func_70107_b((double)i1, (double)j1, (double)k1);
if (!this.field_70170_p.func_217358_a((double)i1, (double)j1, (double)k1, 7.0D) && this.field_70170_p.func_226668_i_(zombieentity) && this.field_70170_p.func_226669_j_(zombieentity) && !this.field_70170_p.func_72953_d(zombieentity.func_174813_aQ())) {
@@ -27,7 +45,24 @@
zombieentity.func_70624_b(livingentity);
zombieentity.func_213386_a(serverworld, this.field_70170_p.func_175649_E(zombieentity.func_233580_cy_()), SpawnReason.REINFORCEMENT, (ILivingEntityData)null, (CompoundNBT)null);
serverworld.func_242417_l(zombieentity);
@@ -448,7 +453,7 @@
@@ -369,7 +376,7 @@
public void func_241847_a(ServerWorld p_241847_1_, LivingEntity p_241847_2_) {
super.func_241847_a(p_241847_1_, p_241847_2_);
- if ((p_241847_1_.func_175659_aa() == Difficulty.NORMAL || p_241847_1_.func_175659_aa() == Difficulty.HARD) && p_241847_2_ instanceof VillagerEntity) {
+ if ((p_241847_1_.func_175659_aa() == Difficulty.NORMAL || p_241847_1_.func_175659_aa() == Difficulty.HARD) && p_241847_2_ instanceof VillagerEntity && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(p_241847_2_, EntityType.field_200727_aF, (timer) -> {})) {
if (p_241847_1_.func_175659_aa() != Difficulty.HARD && this.field_70146_Z.nextBoolean()) {
return;
}
@@ -381,6 +388,7 @@
zombievillagerentity.func_223727_a(villagerentity.func_223722_es().func_234058_a_(NBTDynamicOps.field_210820_a).getValue());
zombievillagerentity.func_213790_g(villagerentity.func_213706_dY().func_222199_a());
zombievillagerentity.func_213789_a(villagerentity.func_213708_dV());
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(p_241847_2_, zombievillagerentity);
if (!this.func_174814_R()) {
p_241847_1_.func_217378_a((PlayerEntity)null, 1026, this.func_233580_cy_(), 0);
}
@@ -448,7 +456,7 @@
}
public static boolean func_241399_a_(Random p_241399_0_) {
@@ -36,7 +71,7 @@
}
protected void func_207304_a(float p_207304_1_) {
@@ -468,7 +473,7 @@
@@ -468,7 +476,7 @@
}
protected void func_230291_eT_() {
@@ -0,0 +1,20 @@
--- a/net/minecraft/entity/monster/ZombieVillagerEntity.java
+++ b/net/minecraft/entity/monster/ZombieVillagerEntity.java
@@ -116,7 +116,7 @@
if (!this.field_70170_p.field_72995_K && this.func_70089_S() && this.func_82230_o()) {
int i = this.func_190735_dq();
this.field_82234_d -= i;
- if (this.field_82234_d <= 0) {
+ if (this.field_82234_d <= 0 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_200756_av, (timer) -> this.field_82234_d = timer)) {
this.func_213791_a((ServerWorld)this.field_70170_p);
}
}
@@ -218,7 +218,7 @@
if (!this.func_174814_R()) {
p_213791_1_.func_217378_a((PlayerEntity)null, 1027, this.func_233580_cy_(), 0);
}
-
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, villagerentity);
}
private int func_190735_dq() {
@@ -0,0 +1,19 @@
--- a/net/minecraft/entity/monster/piglin/AbstractPiglinEntity.java
+++ b/net/minecraft/entity/monster/piglin/AbstractPiglinEntity.java
@@ -83,7 +83,7 @@
this.field_242334_c = 0;
}
- if (this.field_242334_c > 300) {
+ if (this.field_242334_c > 300 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_233592_ba_, (timer) -> this.field_242334_c = timer)) {
this.func_241848_eP();
this.func_234416_a_((ServerWorld)this.field_70170_p);
}
@@ -98,6 +98,7 @@
ZombifiedPiglinEntity zombifiedpiglinentity = this.func_233656_b_(EntityType.field_233592_ba_, true);
if (zombifiedpiglinentity != null) {
zombifiedpiglinentity.func_195064_c(new EffectInstance(Effects.field_76431_k, 200, 0));
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zombifiedpiglinentity);
}
}
@@ -0,0 +1,19 @@
--- a/net/minecraft/entity/passive/PigEntity.java
+++ b/net/minecraft/entity/passive/PigEntity.java
@@ -203,7 +203,7 @@
}
public void func_241841_a(ServerWorld p_241841_1_, LightningBoltEntity p_241841_2_) {
- if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL) {
+ if (p_241841_1_.func_175659_aa() != Difficulty.PEACEFUL && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.field_233592_ba_, (timer) -> {})) {
ZombifiedPiglinEntity zombifiedpiglinentity = EntityType.field_233592_ba_.func_200721_a(p_241841_1_);
zombifiedpiglinentity.func_184201_a(EquipmentSlotType.MAINHAND, new ItemStack(Items.field_151010_B));
zombifiedpiglinentity.func_70012_b(this.func_226277_ct_(), this.func_226278_cu_(), this.func_226281_cx_(), this.field_70177_z, this.field_70125_A);
@@ -215,6 +215,7 @@
}
zombifiedpiglinentity.func_110163_bv();
+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, zombifiedpiglinentity);
p_241841_1_.func_217376_c(zombifiedpiglinentity);
this.func_70106_y();
} else {
@@ -43,9 +43,9 @@
+ }
+
+ @Override
+ public void remove(boolean keepData) {
+ super.remove(keepData);
+ if (!keepData && itemHandler != null) {
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ if (itemHandler != null) {
+ itemHandler.invalidate();
+ itemHandler = null;
+ }
@@ -214,7 +214,7 @@
return list;
}
@@ -817,7 +841,7 @@
@@ -817,9 +841,10 @@
}
}
} else {
@@ -222,8 +222,11 @@
+ multimap = this.func_77973_b().getAttributeModifiers(p_111283_1_, this);
}
+ multimap = net.minecraftforge.common.ForgeHooks.getAttributeModifiers(this, p_111283_1_, multimap);
return multimap;
@@ -954,6 +978,35 @@
}
@@ -954,6 +979,35 @@
return this.func_77973_b().func_219971_r();
}
@@ -0,0 +1,14 @@
--- a/net/minecraft/pathfinding/PathNavigator.java
+++ b/net/minecraft/pathfinding/PathNavigator.java
@@ -208,9 +208,9 @@
Vector3d vector3d = this.func_75502_i();
this.field_188561_o = this.field_75515_a.func_213311_cf() > 0.75F ? this.field_75515_a.func_213311_cf() / 2.0F : 0.75F - this.field_75515_a.func_213311_cf() / 2.0F;
Vector3i vector3i = this.field_75514_c.func_242948_g();
- double d0 = Math.abs(this.field_75515_a.func_226277_ct_() - ((double)vector3i.func_177958_n() + 0.5D));
+ double d0 = Math.abs(this.field_75515_a.func_226277_ct_() - ((double)vector3i.func_177958_n() + (this.field_75515_a.func_213311_cf() + 1) / 2D)); //Forge: Fix MC-94054
double d1 = Math.abs(this.field_75515_a.func_226278_cu_() - (double)vector3i.func_177956_o());
- double d2 = Math.abs(this.field_75515_a.func_226281_cx_() - ((double)vector3i.func_177952_p() + 0.5D));
+ double d2 = Math.abs(this.field_75515_a.func_226281_cx_() - ((double)vector3i.func_177952_p() + (this.field_75515_a.func_213311_cf() + 1) / 2D)); //Forge: Fix MC-94054
boolean flag = d0 < (double)this.field_188561_o && d2 < (double)this.field_188561_o && d1 < 1.0D;
if (flag || this.field_75515_a.func_233660_b_(this.field_75514_c.func_237225_h_().field_186287_m) && this.func_234112_b_(vector3d)) {
this.field_75514_c.func_75875_a();
@@ -60,7 +60,7 @@
}
+ // Forge: Deserialize the DimensionGeneratorSettings to ensure modded dims are loaded on first server load (see SimpleRegistryCodec#decode). Vanilla behaviour only loads from the server.properties and deserializes only after the 2nd server load.
+ dimensiongeneratorsettings = DimensionGeneratorSettings.field_236201_a_.encodeStart(worldsettingsimport, dimensiongeneratorsettings).flatMap(nbt -> DimensionGeneratorSettings.field_236201_a_.parse(worldsettingsimport, nbt)).getOrThrow(false, errorMsg->{});
+ dimensiongeneratorsettings = DimensionGeneratorSettings.field_236201_a_.encodeStart(net.minecraft.util.registry.WorldGenSettingsExport.func_240896_a_(NBTDynamicOps.field_210820_a, dynamicregistries$impl), dimensiongeneratorsettings).flatMap(nbt -> DimensionGeneratorSettings.field_236201_a_.parse(worldsettingsimport, nbt)).getOrThrow(false, errorMsg->{});
iserverconfiguration = new ServerWorldInfo(worldsettings, dimensiongeneratorsettings, Lifecycle.stable());
}
@@ -125,7 +125,7 @@
public ActionResultType func_219441_a(ServerPlayerEntity p_219441_1_, World p_219441_2_, ItemStack p_219441_3_, Hand p_219441_4_, BlockRayTraceResult p_219441_5_) {
BlockPos blockpos = p_219441_5_.func_216350_a();
BlockState blockstate = p_219441_2_.func_180495_p(blockpos);
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks.onRightClickBlock(p_219441_1_, p_219441_4_, blockpos, p_219441_5_.func_216354_b());
+ net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock event = net.minecraftforge.common.ForgeHooks.onRightClickBlock(p_219441_1_, p_219441_4_, blockpos, p_219441_5_);
+ if (event.isCanceled()) return event.getCancellationResult();
if (this.field_73091_c == GameType.SPECTATOR) {
INamedContainerProvider inamedcontainerprovider = blockstate.func_215699_b(p_219441_2_, blockpos);
@@ -144,15 +144,17 @@
+ boolean flag1 = (p_219441_1_.func_226563_dT_() && flag) && !(p_219441_1_.func_184614_ca().doesSneakBypassUse(p_219441_2_, blockpos, p_219441_1_) && p_219441_1_.func_184592_cb().doesSneakBypassUse(p_219441_2_, blockpos, p_219441_1_));
ItemStack itemstack = p_219441_3_.func_77946_l();
- if (!flag1) {
+ if (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1) {
+ if (event.getUseBlock() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (event.getUseBlock() != net.minecraftforge.eventbus.api.Event.Result.DENY && !flag1)) {
ActionResultType actionresulttype = blockstate.func_227031_a_(p_219441_2_, p_219441_1_, p_219441_4_, p_219441_5_);
if (actionresulttype.func_226246_a_()) {
CriteriaTriggers.field_232607_M_.func_226695_a_(p_219441_1_, blockpos, itemstack);
@@ -312,7 +343,7 @@
@@ -311,8 +342,8 @@
}
}
if (!p_219441_3_.func_190926_b() && !p_219441_1_.func_184811_cZ().func_185141_a(p_219441_3_.func_77973_b())) {
- if (!p_219441_3_.func_190926_b() && !p_219441_1_.func_184811_cZ().func_185141_a(p_219441_3_.func_77973_b())) {
- ItemUseContext itemusecontext = new ItemUseContext(p_219441_1_, p_219441_4_, p_219441_5_);
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.ALLOW || (!p_219441_3_.func_190926_b() && !p_219441_1_.func_184811_cZ().func_185141_a(p_219441_3_.func_77973_b()))) {
+ if (event.getUseItem() == net.minecraftforge.eventbus.api.Event.Result.DENY) return ActionResultType.PASS;
ActionResultType actionresulttype1;
if (this.func_73083_d()) {
@@ -118,8 +118,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
@@ -76,8 +76,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ for (int x = 0; x < handlers.length; x++)
+ handlers[x].invalidate();
+ }
@@ -51,8 +51,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ if (chestHandler != null)
+ chestHandler.invalidate();
+ }
@@ -1,6 +1,6 @@
--- a/net/minecraft/tileentity/LockableTileEntity.java
+++ b/net/minecraft/tileentity/LockableTileEntity.java
@@ -81,4 +81,22 @@
@@ -81,4 +81,21 @@
}
protected abstract Container func_213906_a(int p_213906_1_, PlayerInventory p_213906_2_);
@@ -10,7 +10,6 @@
+ return new net.minecraftforge.items.wrapper.InvWrapper(this);
+ }
+
+ @javax.annotation.Nullable
+ public <T> net.minecraftforge.common.util.LazyOptional<T> getCapability(net.minecraftforge.common.capabilities.Capability<T> cap, @javax.annotation.Nullable net.minecraft.util.Direction side) {
+ if (!this.field_145846_f && cap == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY )
+ return itemHandler.cast();
@@ -18,8 +17,8 @@
+ }
+
+ @Override
+ public void func_145843_s() {
+ super.func_145843_s();
+ protected void invalidateCaps() {
+ super.invalidateCaps();
+ itemHandler.invalidate();
+ }
}
@@ -49,7 +49,7 @@
this.field_145850_b.func_175666_e(this.field_174879_c, this.field_195045_e.func_177230_c());
}
}
@@ -133,6 +140,8 @@
@@ -133,8 +140,15 @@
public void func_145843_s() {
this.field_145846_f = true;
@@ -57,8 +57,15 @@
+ requestModelDataUpdate();
}
+ @Override
+ public void onChunkUnloaded() {
+ this.invalidateCaps();
+ }
+
public void func_145829_t() {
@@ -175,6 +184,13 @@
this.field_145846_f = false;
}
@@ -175,6 +189,13 @@
return this.field_200663_e;
}
@@ -0,0 +1,12 @@
--- a/net/minecraft/util/registry/SimpleRegistry.java
+++ b/net/minecraft/util/registry/SimpleRegistry.java
@@ -212,7 +212,8 @@
}
public static <T> Codec<SimpleRegistry<T>> func_241745_c_(RegistryKey<? extends Registry<T>> p_241745_0_, Lifecycle p_241745_1_, Codec<T> p_241745_2_) {
- return Codec.unboundedMap(ResourceLocation.field_240908_a_.xmap(RegistryKey.func_240902_a_(p_241745_0_), RegistryKey::func_240901_a_), p_241745_2_).xmap((p_239656_2_) -> {
+ // FORGE: Fix MC-197860
+ return new net.minecraftforge.common.LenientUnboundedMapCodec<>(ResourceLocation.field_240908_a_.xmap(RegistryKey.func_240902_a_(p_241745_0_), RegistryKey::func_240901_a_), p_241745_2_).xmap((p_239656_2_) -> {
SimpleRegistry<T> simpleregistry = new SimpleRegistry<>(p_241745_0_, p_241745_1_);
p_239656_2_.forEach((p_239653_2_, p_239653_3_) -> {
simpleregistry.func_218381_a(p_239653_2_, p_239653_3_, p_241745_1_);
@@ -9,3 +9,33 @@
private static final Supplier<Set<PointOfInterestType>> field_234168_y_ = Suppliers.memoize(() -> {
return Registry.field_218370_L.func_201756_e().map(VillagerProfession::func_221149_b).collect(Collectors.toSet());
});
@@ -36,7 +36,7 @@
}).filter((p_234173_0_) -> {
return p_234173_0_.func_177229_b(BedBlock.field_176472_a) == BedPart.HEAD;
}).collect(ImmutableSet.toImmutableSet());
- private static final Map<BlockState, PointOfInterestType> field_221073_u = Maps.newHashMap();
+ private static final Map<BlockState, PointOfInterestType> field_221073_u = net.minecraftforge.registries.GameData.getBlockStatePointOfInterestTypeMap();
public static final PointOfInterestType field_221054_b = func_226360_a_("unemployed", ImmutableSet.of(), 1, field_221071_s, 1);
public static final PointOfInterestType field_221055_c = func_226359_a_("armorer", func_221042_a(Blocks.field_222424_lM), 1, 1);
public static final PointOfInterestType field_221056_d = func_226359_a_("butcher", func_221042_a(Blocks.field_222423_lL), 1, 1);
@@ -112,16 +112,14 @@
}
private static PointOfInterestType func_221052_a(PointOfInterestType p_221052_0_) {
- p_221052_0_.field_221075_w.forEach((p_234169_1_) -> {
- PointOfInterestType pointofinteresttype = field_221073_u.put(p_234169_1_, p_221052_0_);
- if (pointofinteresttype != null) {
- throw (IllegalStateException)Util.func_229757_c_(new IllegalStateException(String.format("%s is defined in too many tags", p_234169_1_)));
- }
- });
return p_221052_0_;
}
public static Optional<PointOfInterestType> func_221047_b(BlockState p_221047_0_) {
return Optional.ofNullable(field_221073_u.get(p_221047_0_));
}
+
+ public ImmutableSet<BlockState> getBlockStates() {
+ return ImmutableSet.copyOf(this.field_221075_w);
+ }
}
@@ -0,0 +1,20 @@
--- a/net/minecraft/world/gen/settings/DimensionGeneratorSettings.java
+++ b/net/minecraft/world/gen/settings/DimensionGeneratorSettings.java
@@ -192,7 +192,7 @@
String s3 = (String)p_242753_1_.get("level-type");
String s4 = Optional.ofNullable(s3).map((p_236217_0_) -> {
return p_236217_0_.toLowerCase(Locale.ROOT);
- }).orElse("default");
+ }).orElseGet(net.minecraftforge.common.ForgeHooks::getDefaultWorldType);
p_242753_1_.put("level-type", s4);
long i = (new Random()).nextLong();
if (!s1.isEmpty()) {
@@ -210,6 +210,8 @@
Registry<Biome> registry = p_242753_0_.func_243612_b(Registry.field_239720_u_);
Registry<DimensionSettings> registry1 = p_242753_0_.func_243612_b(Registry.field_243549_ar);
SimpleRegistry<Dimension> simpleregistry = DimensionType.func_242718_a(registry2, registry, registry1, i);
+ net.minecraftforge.common.world.ForgeWorldType type = net.minecraftforge.registries.ForgeRegistries.WORLD_TYPES.getValue(new net.minecraft.util.ResourceLocation(s4));
+ if (type != null) return type.createSettings(p_242753_0_, i, flag, false, s);
switch(s4) {
case "flat":
JsonObject jsonobject = !s.isEmpty() ? JSONUtils.func_212745_a(s) : new JsonObject();
@@ -0,0 +1,11 @@
--- a/net/minecraft/world/server/ServerChunkProvider.java
+++ b/net/minecraft/world/server/ServerChunkProvider.java
@@ -353,7 +353,7 @@
if (optional1.isPresent()) {
Chunk chunk = optional1.get();
ChunkPos chunkpos = p_241099_7_.func_219277_h();
- if (!this.field_217237_a.func_219243_d(chunkpos)) {
+ if (!this.field_217237_a.func_219243_d(chunkpos) || field_217237_a.func_219246_e().shouldForceTicks(chunkpos.func_201841_a())) {
chunk.func_177415_c(chunk.func_177416_w() + j);
if (flag1 && (this.field_217246_l || this.field_217247_m) && this.field_73251_h.func_175723_af().func_177730_a(chunk.func_76632_l())) {
WorldEntitySpawner.func_234979_a_(this.field_73251_h, chunk, worldentityspawner$entitydensitymanager, this.field_217247_m, this.field_217246_l, flag2);
@@ -0,0 +1,49 @@
--- a/net/minecraft/world/server/Ticket.java
+++ b/net/minecraft/world/server/Ticket.java
@@ -9,9 +9,14 @@
private long field_219483_d;
protected Ticket(TicketType<T> p_i226095_1_, int p_i226095_2_, T p_i226095_3_) {
+ this(p_i226095_1_, p_i226095_2_, p_i226095_3_, false);
+ }
+
+ public Ticket(TicketType<T> p_i226095_1_, int p_i226095_2_, T p_i226095_3_, boolean forceTicks) {
this.field_219480_a = p_i226095_1_;
this.field_219481_b = p_i226095_2_;
this.field_219482_c = p_i226095_3_;
+ this.forceTicks = forceTicks;
}
public int compareTo(Ticket<?> p_compareTo_1_) {
@@ -31,16 +36,16 @@
return false;
} else {
Ticket<?> ticket = (Ticket)p_equals_1_;
- return this.field_219481_b == ticket.field_219481_b && Objects.equals(this.field_219480_a, ticket.field_219480_a) && Objects.equals(this.field_219482_c, ticket.field_219482_c);
+ return this.field_219481_b == ticket.field_219481_b && Objects.equals(this.field_219480_a, ticket.field_219480_a) && Objects.equals(this.field_219482_c, ticket.field_219482_c) && this.forceTicks == ticket.forceTicks;
}
}
public int hashCode() {
- return Objects.hash(this.field_219480_a, this.field_219481_b, this.field_219482_c);
+ return Objects.hash(this.field_219480_a, this.field_219481_b, this.field_219482_c, forceTicks);
}
public String toString() {
- return "Ticket[" + this.field_219480_a + " " + this.field_219481_b + " (" + this.field_219482_c + ")] at " + this.field_219483_d;
+ return "Ticket[" + this.field_219480_a + " " + this.field_219481_b + " (" + this.field_219482_c + ")] at " + this.field_219483_d + " force ticks " + forceTicks;
}
public TicketType<T> func_219479_a() {
@@ -59,4 +64,11 @@
long i = this.field_219480_a.func_223184_b();
return i != 0L && p_223182_1_ - this.field_219483_d > i;
}
+
+ /* ======================================== FORGE START =====================================*/
+ private final boolean forceTicks;
+
+ public boolean isForceTicks() {
+ return forceTicks;
+ }
}
@@ -0,0 +1,48 @@
--- a/net/minecraft/world/server/TicketManager.java
+++ b/net/minecraft/world/server/TicketManager.java
@@ -49,6 +49,8 @@
private final Executor field_219388_p;
private long field_219389_q;
+ private final Long2ObjectOpenHashMap<SortedArraySet<Ticket<?>>> forcedTickets = new Long2ObjectOpenHashMap<>();
+
protected TicketManager(Executor p_i50707_1_, Executor p_i50707_2_) {
ITaskExecutor<Runnable> itaskexecutor = ITaskExecutor.func_213140_a("player ticket throttler", p_i50707_2_::execute);
ChunkTaskPriorityQueueSorter chunktaskpriorityqueuesorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(itaskexecutor), p_i50707_1_, 4);
@@ -143,6 +145,10 @@
this.field_219378_f.func_215491_b(p_219347_1_, p_219347_3_.func_219477_b(), true);
}
+ if (p_219347_3_.isForceTicks()) {
+ SortedArraySet<Ticket<?>> tickets = forcedTickets.computeIfAbsent(p_219347_1_, e -> SortedArraySet.func_226172_a_(4));
+ tickets.func_226175_a_(ticket);
+ }
}
private void func_219349_b(long p_219349_1_, Ticket<?> p_219349_3_) {
@@ -155,6 +161,13 @@
}
this.field_219378_f.func_215491_b(p_219349_1_, func_229844_a_(sortedarrayset), false);
+
+ if (p_219349_3_.isForceTicks()) {
+ SortedArraySet<Ticket<?>> tickets = forcedTickets.get(p_219349_1_);
+ if (tickets != null) {
+ tickets.remove(p_219349_3_);
+ }
+ }
}
public <T> void func_219356_a(TicketType<T> p_219356_1_, ChunkPos p_219356_2_, int p_219356_3_, T p_219356_4_) {
@@ -242,6 +255,11 @@
return this.field_219384_l.func_225396_a();
}
+ public boolean shouldForceTicks(long chunkPos) {
+ SortedArraySet<Ticket<?>> tickets = forcedTickets.get(chunkPos);
+ return tickets != null && !tickets.isEmpty();
+ }
+
class ChunkTicketTracker extends ChunkDistanceGraph {
public ChunkTicketTracker() {
super(ChunkManager.field_219249_a + 2, 16, 256);
@@ -185,11 +185,12 @@ public class FMLLoader
naming = commonLaunchHandler.getNaming();
dist = commonLaunchHandler.getDist();
production = commonLaunchHandler.isProduction();
progressWindowTick = EarlyProgressVisualization.INSTANCE.accept(dist, commonLaunchHandler.isData());
mcVersion = (String) arguments.get("mcVersion");
progressWindowTick = EarlyProgressVisualization.INSTANCE.accept(dist, commonLaunchHandler.isData(), mcVersion);
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Early Loading!"));
accessTransformer.getExtension().accept(Pair.of(naming, "srg"));
mcVersion = (String) arguments.get("mcVersion");
mcpVersion = (String) arguments.get("mcpVersion");
forgeVersion = (String) arguments.get("forgeVersion");
forgeGroup = (String) arguments.get("forgeGroup");
@@ -42,12 +42,12 @@ public class StringUtils
}
public static URL toURL(final String string) {
try
{
return new URL(string);
}
catch (MalformedURLException e)
{
if (string == null || string.trim().isEmpty() || string.contains("myurl.me") || string.contains("example.invalid"))
return null;
try {
return new URL(string); }
catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.loading;
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
@@ -5,20 +24,32 @@ import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.BiPredicate;
public class VersionSupportMatrix {
private static final HashMap<String, ArtifactVersion> overrideVersions = new HashMap<>();
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
static {
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.mcVersion);
if (MavenVersionAdapter.createFromVersionSpec("[1.16.4]").containsVersion(version)) {
overrideVersions.put("languageloader.javafml", new DefaultArtifactVersion("34")); // we also work with javafml 34
overrideVersions.put("mod.minecraft", new DefaultArtifactVersion("1.16.3")); // we work with anything declaring 1.16.3
overrideVersions.put("mod.forge", new DefaultArtifactVersion("34.1.42")); // we work with anything that supports forge 34.1.42
if (MavenVersionAdapter.createFromVersionSpec("[1.16.4,1.16.5]").containsVersion(version)) {
// 1.16.4 is Compatible with 1.16.3
add("languageloader.javafml", "34");
add("mod.minecraft", "1.16.3");
add("mod.forge", "34.1.42");
// 1.16.5 is Compatible with 1.16.4, and thus 1.16.3
add("languageloader.javafml", "35");
add("mod.minecraft", "1.16.4");
add("mod.forge", "35.1.37");
}
}
private static void add(String key, String value) {
overrideVersions.computeIfAbsent(key, k -> new ArrayList<>()).add(new DefaultArtifactVersion(value));
}
public static <T> boolean testVersionSupportMatrix(VersionRange declaredRange, String lookupId, String type, BiPredicate<String, VersionRange> standardLookup) {
return standardLookup.test(lookupId, declaredRange) || overrideVersions.containsKey(type +"." +lookupId) && declaredRange.containsVersion(overrideVersions.get(type +"." +lookupId));
if (standardLookup.test(lookupId, declaredRange)) return true;
List<ArtifactVersion> custom = overrideVersions.get(type +"." +lookupId);
return custom == null ? false : custom.stream().anyMatch(declaredRange::containsVersion);
}
}
@@ -22,9 +22,7 @@ package net.minecraftforge.fml.loading.progress;
import com.google.common.io.ByteStreams;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
@@ -40,10 +38,13 @@ import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.opengl.GL11.*;
@@ -58,8 +59,10 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
private Thread renderThread = new Thread(this::renderThreadFunc);
private boolean running = true;
private GLFWFramebufferSizeCallback framebufferSizeCallback;
private int[] fbSize;
private void initWindow() {
private void initWindow(@Nullable String mcVersion) {
GLFWErrorCallback.createPrint(System.err).set();
long glfwInitBegin = System.nanoTime();
@@ -81,10 +84,21 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
if (mcVersion != null)
{
// this emulates what we would get without early progress window
// as vanilla never sets these, so GLFW uses the first window title
// set them explicitly to avoid it using "FML early loading progress" as the class
String vanillaWindowTitle = "Minecraft* " + mcVersion;
glfwWindowHintString(GLFW_X11_CLASS_NAME, vanillaWindowTitle);
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, vanillaWindowTitle);
}
window = glfwCreateWindow(screenWidth, screenHeight, "FML early loading progress", NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window"); // ignore it and make the GUI optional?
}
framebufferSizeCallback = GLFWFramebufferSizeCallback.create(this::fbResize);
try (MemoryStack stack = stackPush()) {
IntBuffer pWidth = stack.mallocInt(1);
@@ -126,6 +140,11 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
System.err.println("Failed to load forge logo");
}
}
int[] w = new int[1];
int[] h = new int[1];
glfwGetFramebufferSize(window, w, h);
fbSize = new int[] {w[0], h[0]};
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
glfwShowWindow(window);
glfwPollEvents();
}
@@ -220,6 +239,11 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
glVertex2f(screenWidth, 0);
glEnd();
}
private void fbResize(long window, int width, int height) {
if (window == this.window && width != 0 && height != 0) {
fbSize = new int[] {width, height};
}
}
private void renderMessages() {
List<Pair<Integer, StartupMessageManager.Message>> messages = StartupMessageManager.getMessages();
@@ -233,6 +257,12 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
renderMemoryInfo();
}
@Override
public void updateFBSize(final IntConsumer width, final IntConsumer height) {
width.accept(this.fbSize[0]);
height.accept(this.fbSize[1]);
}
private static final float[] memorycolour = new float[] { 0.0f, 0.0f, 0.0f};
private void renderMemoryInfo() {
@@ -283,8 +313,8 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
}
@Override
public Runnable start() {
initWindow();
public Runnable start(@Nullable String mcVersion) {
initWindow(mcVersion);
renderThread.setDaemon(true); // Don't hang the game if it terminates before handoff (i.e. datagen)
renderThread.start();
return org.lwjgl.glfw.GLFW::glfwPollEvents;
@@ -309,6 +339,8 @@ class ClientVisualization implements EarlyProgressVisualization.Visualization {
glfwSwapInterval(0);
glfwSwapBuffers(window);
glfwSwapInterval(1);
final GLFWFramebufferSizeCallback previous = glfwSetFramebufferSizeCallback(window, null);
previous.free();
return window;
}
}
@@ -21,27 +21,38 @@ package net.minecraftforge.fml.loading.progress;
import net.minecraftforge.api.distmarker.Dist;
import java.util.Locale;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import javax.annotation.Nullable;
public enum EarlyProgressVisualization {
INSTANCE;
private Visualization visualization;
public Runnable accept(final Dist dist, final boolean isData) {
public Runnable accept(Dist dist, boolean isData)
{
return accept(dist, isData, null);
}
public Runnable accept(final Dist dist, final boolean isData, @Nullable String mcVersion) {
visualization = !isData && dist.isClient() && Boolean.parseBoolean(System.getProperty("fml.earlyprogresswindow", "true")) ? new ClientVisualization() : new NoVisualization();
return visualization.start();
return visualization.start(mcVersion);
}
public long handOffWindow(final IntSupplier width, final IntSupplier height, final Supplier<String> title, final LongSupplier monitor) {
return visualization.handOffWindow(width, height, title, monitor);
}
public void updateFBSize(IntConsumer width, IntConsumer height) {
visualization.updateFBSize(width, height);
}
interface Visualization {
Runnable start();
Runnable start(@Nullable String mcVersion);
default long handOffWindow(final IntSupplier width, final IntSupplier height, final Supplier<String> title, LongSupplier monitorSupplier) {
return new LongSupplier() {
@@ -51,11 +62,14 @@ public enum EarlyProgressVisualization {
}
}.getAsLong();
}
default void updateFBSize(IntConsumer width, IntConsumer height) {
}
}
private static class NoVisualization implements Visualization {
@Override
public Runnable start() {
public Runnable start(@Nullable String mcVersion) {
return () -> {};
}
}
+3 -1
View File
@@ -41,10 +41,12 @@ c4d268471ee793597917c966d1aaed29e438d366 assets/data_gen_test/models/block/oak_t
2abb8b11c91441badd91b7c52f5f8ba3226c92de assets/data_gen_test/models/block/oak_trapdoor_open.json
560d419e3d542cb0509bca078988308d387c15a9 assets/data_gen_test/models/block/oak_trapdoor_top.json
556f0d997250661e0401fba13a4afd1bb0627dcc assets/data_gen_test/models/block/stone.json
556f0d997250661e0401fba13a4afd1bb0627dcc assets/data_gen_test/models/block/test_block.json
db2cd929128c8a6e8e0b02437f90ad8d24238206 assets/data_gen_test/models/block/torch.json
81ce9ac0a7f4ed7a94d5496b918987a6f5a24988 assets/data_gen_test/models/block/wall_torch.json
6b40df2a47c13cd00e295244b6cf74462938359d assets/data_gen_test/models/item/fishing_rod.json
7fecdc30a209fca790df79b973c30b9e84415e0b assets/data_gen_test/models/item/fishing_rod_cast.json
098d8b38409fff6cc14a4e56355bedb1fc5931d1 assets/data_gen_test/models/item/test_block.json
b029993275f16569b0edf093362f55df6ea6f9be assets/data_gen_test/models/item/test_block_model.json
726e1884e53151492ca05bd752c67031603570f6 assets/data_gen_test/models/item/test_generated_model.json
1767c874758bd7c3235db446b6219e6e1edd25b4 assets/minecraft/blockstates/acacia_door.json
@@ -79,7 +81,7 @@ cf16f861eaf5815238c2278eb48bde0688cb73b7 assets/scaffolding_test/blockstates/sca
66442c8000af9af4ba36109b3c9d09d9ffd57277 data/data_gen_test/advancements/recipes/conditional2.json
ed4cbf1a3a2f5d8969f6346fdc9acdbe81d0c919 data/data_gen_test/recipes/conditional.json
ca9827bff0a49957e01cf3887ef5131ad8710320 data/data_gen_test/recipes/conditional2.json
40208299608468b044f64317995f9182ec219d90 data/data_gen_test/tags/blocks/test.json
8831e79c8d15b1bc00eb29d354bb22b64d9ddcdd data/data_gen_test/tags/blocks/test.json
d65c425e740dc833f29d16606a1171825876be0d data/data_gen_test/tags/blocks/thing/one.json
1f70ed4ddc878bada5e43d3c44a34157806beda8 data/data_gen_test/tags/blocks/thing/three.json
2c648bca262caaa826ddbbde796d35bb2ee5f03a data/data_gen_test/tags/blocks/thing/two.json
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "minecraft:block/stone"
}
}
@@ -0,0 +1,3 @@
{
"parent": "data_gen_test:block/test_block"
}
@@ -3,6 +3,7 @@
"values": [
"minecraft:diamond_block",
"#minecraft:stone_bricks",
"#forge:cobblestone",
{
"id": "chisel:marble/raw",
"required": false
@@ -22,6 +22,7 @@ package net.minecraftforge.client;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.block.BlockState;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.MouseHelper;
@@ -30,6 +31,7 @@ import net.minecraft.client.audio.SoundEngine;
import net.minecraft.client.gui.AbstractGui;
import net.minecraft.client.gui.ClientBossInfo;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.client.gui.screen.MainMenuScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.play.NetworkPlayerInfo;
@@ -76,6 +78,8 @@ import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.GameType;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.World;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.client.event.*;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.model.ModelLoader;
@@ -100,12 +104,15 @@ import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
import org.lwjgl.opengl.GL13;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Stream;
@@ -769,4 +776,42 @@ public class ForgeHooksClient
}
return !(squareDistance > 4096.0f);
}
public static void renderPistonMovedBlocks(BlockPos pos, BlockState state, MatrixStack stack, IRenderTypeBuffer buffer, World world, boolean checkSides, int combinedOverlay, BlockRendererDispatcher blockRenderer) {
RenderType.getBlockRenderTypes().stream()
.filter(t -> RenderTypeLookup.canRenderInLayer(state, t))
.forEach(rendertype ->
{
rendertype = rendertype == RenderType.getTranslucent() ? RenderType.getTranslucentMovingBlock() : rendertype;
setRenderLayer(rendertype);
IVertexBuilder ivertexbuilder = buffer.getBuffer(rendertype);
blockRenderer.getBlockModelRenderer().renderModel(world, blockRenderer.getModelForState(state), state, pos, stack, ivertexbuilder, checkSides, new Random(), state.getPositionRandom(pos), combinedOverlay);
});
setRenderLayer(null);
}
public static void registerForgeWorldTypeScreens()
{
ForgeWorldTypeScreens.registerTypes();
}
public static BiomeGeneratorTypeScreens.IFactory getBiomeGeneratorTypeScreenFactory(Optional<BiomeGeneratorTypeScreens> generator, @Nullable BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory)
{
return ForgeWorldTypeScreens.getGeneratorScreenFactory(generator, biomegeneratortypescreens$ifactory);
}
public static boolean hasBiomeGeneratorSettingsOptionsScreen(Optional<BiomeGeneratorTypeScreens> generator)
{
return getBiomeGeneratorTypeScreenFactory(generator, null) != null;
}
public static Optional<BiomeGeneratorTypeScreens> getWorldTypeFromGenerator(DimensionGeneratorSettings dimensionGeneratorSettings)
{
return BiomeGeneratorTypeScreens.func_239079_a_(dimensionGeneratorSettings);
}
public static Optional<BiomeGeneratorTypeScreens> getDefaultWorldType()
{
return Optional.of(ForgeWorldTypeScreens.getDefaultGenerator());
}
}
@@ -0,0 +1,118 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.client;
import com.google.common.collect.Maps;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.registries.ForgeRegistries;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Optional;
public class ForgeWorldTypeScreens
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Map<ForgeWorldType, BiomeGeneratorTypeScreens> GENERATORS = Maps.newHashMap();
private static final Map<ForgeWorldType, BiomeGeneratorTypeScreens.IFactory> GENERATOR_SCREEN_FACTORIES = Maps.newHashMap();
public static synchronized void registerFactory(ForgeWorldType type, BiomeGeneratorTypeScreens.IFactory factory)
{
if (GENERATOR_SCREEN_FACTORIES.containsKey(type))
throw new IllegalStateException("Factory has already been registered for: " + type);
GENERATOR_SCREEN_FACTORIES.put(type, factory);
}
static BiomeGeneratorTypeScreens getDefaultGenerator()
{
ForgeWorldType def = ForgeWorldType.getDefaultWorldType();
if (def == null)
{
return BiomeGeneratorTypeScreens.field_239066_a_;
}
BiomeGeneratorTypeScreens gen = GENERATORS.get(def);
if (gen == null)
{
LOGGER.error("The default world type '{}' has not been added to the GUI. Was it registered too late?", def.getRegistryName());
return BiomeGeneratorTypeScreens.field_239066_a_;
}
return gen;
}
static BiomeGeneratorTypeScreens.IFactory getGeneratorScreenFactory(Optional<BiomeGeneratorTypeScreens> generator, @Nullable BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory)
{
return generator.filter(gen -> gen instanceof GeneratorType)
.map(type -> GENERATOR_SCREEN_FACTORIES.get(((GeneratorType)type).getWorldType()))
.orElse(biomegeneratortypescreens$ifactory);
}
static void registerTypes()
{
ForgeRegistries.WORLD_TYPES.forEach(wt -> {
GeneratorType gen = new GeneratorType(wt);
GENERATORS.put(wt, gen);
BiomeGeneratorTypeScreens.registerGenerator(gen);
});
}
private static class GeneratorType extends BiomeGeneratorTypeScreens
{
private final ForgeWorldType worldType;
public GeneratorType(ForgeWorldType wt)
{
super(wt.getDisplayName());
worldType = wt;
}
public ForgeWorldType getWorldType()
{
return worldType;
}
@Nonnull
@Override
public DimensionGeneratorSettings func_241220_a_(@Nonnull DynamicRegistries.Impl dynamicRegistries, long seed, boolean generateStructures, boolean bonusChest)
{
return worldType.createSettings(dynamicRegistries, seed, generateStructures, bonusChest, "");
}
@Nonnull
@Override
protected ChunkGenerator func_241869_a(@Nonnull Registry<Biome> p_241869_1_, @Nonnull Registry<DimensionSettings> p_241869_2_, long p_241869_3_)
{
return worldType.createChunkGenerator(p_241869_1_, p_241869_2_, p_241869_3_, "");
}
}
}
@@ -0,0 +1,34 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.client;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.world.ClientWorld;
/**
* Call {@link net.minecraft.client.world.DimensionRenderInfo#setWeatherParticleRenderHandler(net.minecraftforge.client.IWeatherParticleRenderHandler)}, obtained from a {@link ClientWorld} with an implementation of this to override all weather particle rendering with your own.
* This handles ground particles that can be seen when it's raining (splash/smoke particles).
* This also includes playing rain sounds.
*/
@FunctionalInterface
public interface IWeatherParticleRenderHandler {
void render(int ticks, ClientWorld world, Minecraft mc, ActiveRenderInfo activeRenderInfoIn);
}
@@ -95,7 +95,7 @@ public abstract class BlockStateProvider implements IDataProvider {
this.blockModels = new BlockModelProvider(gen, modid, exFileHelper) {
@Override protected void registerModels() {}
};
this.itemModels = new ItemModelProvider(gen, modid, exFileHelper) {
this.itemModels = new ItemModelProvider(gen, modid, this.blockModels.existingFileHelper) {
@Override protected void registerModels() {}
};
}
@@ -255,7 +255,7 @@ public abstract class BlockStateProvider implements IDataProvider {
}
public void horizontalFaceBlock(Block block, Function<BlockState, ModelFile> modelFunc) {
horizontalBlock(block, modelFunc, DEFAULT_ANGLE_OFFSET);
horizontalFaceBlock(block, modelFunc, DEFAULT_ANGLE_OFFSET);
}
public void horizontalFaceBlock(Block block, Function<BlockState, ModelFile> modelFunc, int angleOffset) {
@@ -19,7 +19,11 @@
package net.minecraftforge.client.model.generators;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@@ -33,20 +37,19 @@ import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraft.client.renderer.model.BlockFaceUV;
import net.minecraft.client.renderer.model.BlockModel.GuiLight;
import net.minecraft.client.renderer.model.BlockPart;
import net.minecraft.client.renderer.model.BlockPartFace;
import net.minecraft.client.renderer.model.BlockPartRotation;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.model.ItemTransformVec3f;
import net.minecraft.client.renderer.model.BlockModel.GuiLight;
import net.minecraft.client.renderer.texture.MissingTextureSprite;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraftforge.common.data.ExistingFileHelper;
/**
* General purpose model builder, contains all the commonalities between item
@@ -146,7 +149,7 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
public T texture(String key, ResourceLocation texture) {
Preconditions.checkNotNull(key, "Key must not be null");
Preconditions.checkNotNull(texture, "Texture must not be null");
Preconditions.checkArgument(existingFileHelper.exists(texture, ResourcePackType.CLIENT_RESOURCES, ".png", "textures"),
Preconditions.checkArgument(existingFileHelper.exists(texture, ModelProvider.TEXTURE),
"Texture %s does not exist in any known resource pack", texture);
this.textures.put(key, texture.toString());
return self();
@@ -21,7 +21,6 @@ package net.minecraftforge.client.model.generators;
import com.google.common.base.Preconditions;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
@@ -78,9 +77,9 @@ public abstract class ModelFile {
@Override
protected boolean exists() {
if (getUncheckedLocation().getPath().contains("."))
return existingHelper.exists(getUncheckedLocation(), ResourcePackType.CLIENT_RESOURCES, "", "models");
return existingHelper.exists(getUncheckedLocation(), ModelProvider.MODEL_WITH_EXTENSION);
else
return existingHelper.exists(getUncheckedLocation(), ResourcePackType.CLIENT_RESOURCES, ".json", "models");
return existingHelper.exists(getUncheckedLocation(), ModelProvider.MODEL);
}
}
}
@@ -21,7 +21,6 @@ package net.minecraftforge.client.model.generators;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
@@ -35,61 +34,20 @@ import com.google.gson.GsonBuilder;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DirectoryCache;
import net.minecraft.data.IDataProvider;
import net.minecraft.resources.IResource;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.common.data.ExistingFileHelper.ResourceType;
public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataProvider {
private class ExistingFileHelperIncludingGenerated extends ExistingFileHelper {
private final ExistingFileHelper delegate;
public ExistingFileHelperIncludingGenerated(ExistingFileHelper delegate) {
super(Collections.emptyList(), true);
this.delegate = delegate;
}
@Override
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix)
{
if (pathPrefix.equals("models") && pathSuffix.equals(".json"))
{
if (generatedModels.containsKey(loc))
{
return true;
}
}
return delegate.exists(loc, type, pathSuffix, pathPrefix);
}
@Override
public boolean exists(ResourceLocation loc, ResourcePackType type) {
if (loc.getPath().startsWith("models/") && loc.getPath().endsWith(".json"))
{
ResourceLocation modelLoc = new ResourceLocation(
loc.getNamespace(),
loc.getPath().substring("models/".length(), loc.getPath().length() - ".json".length())
);
if (generatedModels.containsKey(modelLoc))
{
return true;
}
}
return delegate.exists(loc, type);
}
@Override
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException
{
return delegate.getResource(loc, type);
}
}
public static final String BLOCK_FOLDER = "block";
public static final String ITEM_FOLDER = "item";
protected static final ResourceType TEXTURE = new ResourceType(ResourcePackType.CLIENT_RESOURCES, ".png", "textures");
protected static final ResourceType MODEL = new ResourceType(ResourcePackType.CLIENT_RESOURCES, ".json", "models");
protected static final ResourceType MODEL_WITH_EXTENSION = new ResourceType(ResourcePackType.CLIENT_RESOURCES, "", "models");
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
protected final DataGenerator generator;
protected final String modid;
@@ -112,7 +70,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
Preconditions.checkNotNull(factory);
this.factory = factory;
Preconditions.checkNotNull(existingFileHelper);
this.existingFileHelper = new ExistingFileHelperIncludingGenerated(existingFileHelper);
this.existingFileHelper = existingFileHelper;
}
public ModelProvider(DataGenerator generator, String modid, String folder, BiFunction<ResourceLocation, ExistingFileHelper, T> builderFromModId, ExistingFileHelper existingFileHelper) {
@@ -122,6 +80,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements IDataP
public T getBuilder(String path) {
Preconditions.checkNotNull(path, "Path must not be null");
ResourceLocation outputLoc = extendWithFolder(path.contains(":") ? new ResourceLocation(path) : new ResourceLocation(modid, path));
this.existingFileHelper.trackGenerated(outputLoc, MODEL);
return generatedModels.computeIfAbsent(outputLoc, factory);
}
@@ -26,8 +26,8 @@ import java.util.List;
import java.util.Map.Entry;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
@@ -74,7 +74,7 @@ public final class MultiPartBlockStateBuilder implements IGeneratedBlockstate {
public class PartBuilder {
public BlockStateProvider.ConfiguredModelList models;
public boolean useOr;
public final Multimap<Property<?>, Comparable<?>> conditions = HashMultimap.create();
public final Multimap<Property<?>, Comparable<?>> conditions = MultimapBuilder.linkedHashKeys().arrayListValues().build();
PartBuilder(BlockStateProvider.ConfiguredModelList models) {
this.models = models;
@@ -108,10 +108,33 @@ public class ForgeConfig
.comment("Fix advancement loading to use a proper topological sort. This may have visibility side-effects and can thus be turned off if needed for data-pack compatibility.")
.translation("forge.configgui.fixAdvancementLoading")
.define("fixAdvancementLoading", true);
builder.pop();
}
}
/**
* General configuration that doesn't need to be synchronized but needs to be available before server startup
*/
public static class Common {
public final ForgeConfigSpec.ConfigValue<? extends String> defaultWorldType;
Common(ForgeConfigSpec.Builder builder)
{
builder.comment("General configuration settings")
.push("general");
defaultWorldType = builder
.comment("Defines a default world type to use. The vanilla default world type is represented by 'default'.",
"The modded world types are registry names which should include the registry namespace, such as 'examplemod:example_world_type'.")
.translation("forge.configgui.defaultWorldType")
.define("defaultWorldType", "default");
builder.pop();
}
}
/**
* Client specific configuration - only loaded clientside from forge-client.toml
*/
@@ -196,6 +219,15 @@ public class ForgeConfig
}
static final ForgeConfigSpec commonSpec;
public static final Common COMMON;
static {
final Pair<Common, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Common::new);
commonSpec = specPair.getRight();
COMMON = specPair.getLeft();
}
static final ForgeConfigSpec serverSpec;
public static final Server SERVER;
static {
@@ -33,6 +33,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
@@ -48,7 +49,10 @@ import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.advancements.Advancement;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.fluid.*;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.loot.LootContext;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.LootTableManager;
@@ -120,10 +124,12 @@ import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.loot.LootModifierManager;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.common.world.MobSpawnInfoBuilder;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.ItemAttributeModifierEvent;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.EntityTravelToDimensionEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
@@ -668,7 +674,8 @@ public class ForgeHooks
world.markAndNotifyBlock(snap.getPos(), world.getChunkAt(snap.getPos()), oldBlock, newBlock, updateFlag, 512);
}
player.addStat(Stats.ITEM_USED.get(item));
if (player != null)
player.addStat(Stats.ITEM_USED.get(item));
}
}
world.capturedBlockSnapshots.clear();
@@ -782,6 +789,7 @@ public class ForgeHooks
return evt;
}
@Deprecated //Use RayTraceResult version. TODO: Remove 1.17
public static PlayerInteractEvent.RightClickBlock onRightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, Direction face)
{
PlayerInteractEvent.RightClickBlock evt = new PlayerInteractEvent.RightClickBlock(player, hand, pos, face);
@@ -789,6 +797,13 @@ public class ForgeHooks
return evt;
}
public static PlayerInteractEvent.RightClickBlock onRightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, BlockRayTraceResult hitVec)
{
PlayerInteractEvent.RightClickBlock evt = new PlayerInteractEvent.RightClickBlock(player, hand, pos, hitVec);
MinecraftForge.EVENT_BUS.post(evt);
return evt;
}
public static void onEmptyClick(PlayerEntity player, Hand hand)
{
MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.RightClickEmpty(player, hand));
@@ -879,6 +894,14 @@ public class ForgeHooks
throw new RuntimeException("Mod fluids must override createAttributes.");
}
public static String getDefaultWorldType()
{
ForgeWorldType def = ForgeWorldType.getDefaultWorldType();
if (def != null)
return def.getRegistryName().toString();
return "default";
}
@FunctionalInterface
public interface BiomeCallbackFunction
{
@@ -1008,6 +1031,16 @@ public class ForgeHooks
MinecraftForge.EVENT_BUS.post(new AdvancementEvent(player, advancement));
}
/**
* Hook to fire {@link ItemAttributeModifierEvent}. Modders should use {@link ItemStack#getAttributeModifiers(EquipmentSlotType)} instead.
*/
public static Multimap<Attribute,AttributeModifier> getAttributeModifiers(ItemStack stack, EquipmentSlotType equipmentSlot, Multimap<Attribute,AttributeModifier> attributes)
{
ItemAttributeModifierEvent event = new ItemAttributeModifierEvent(stack, equipmentSlot, attributes);
MinecraftForge.EVENT_BUS.post(event);
return event.getModifiers();
}
/**
* Used as the default implementation of {@link Item#getCreatorModId}. Call that method instead.
*/
@@ -27,14 +27,16 @@ import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.storage.IServerConfiguration;
import net.minecraft.world.storage.SaveFormat;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.*;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent;
import net.minecraftforge.fml.event.lifecycle.*;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.server.command.EnumArgument;
@@ -71,7 +73,6 @@ import net.minecraftforge.common.data.ForgeRecipeProvider;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.fml.common.Mod;
@@ -118,12 +119,14 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::preInit);
modEventBus.addListener(this::gatherData);
modEventBus.addListener(this::loadComplete);
modEventBus.register(this);
ATTRIBUTES.register(modEventBus);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
MinecraftForge.EVENT_BUS.addGenericListener(SoundEvent.class, this::missingSoundMapping);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ForgeConfig.commonSpec);
modEventBus.register(ForgeConfig.class);
// Forge does not display problems when the remote is not matching.
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, ()-> Pair.of(()->"ANY", (remote, isServer)-> true));
@@ -154,6 +157,12 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
ArgumentTypes.register("forge:modid", ModIdArgument.class, new ArgumentSerializer<>(ModIdArgument::modIdArgument));
}
public void loadComplete(FMLLoadCompleteEvent event)
{
if (FMLEnvironment.dist == Dist.CLIENT)
ForgeHooksClient.registerForgeWorldTypeScreens();
}
public void serverStopping(FMLServerStoppingEvent evt)
{
WorldWorkerManager.clear();
@@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
package net.minecraftforge.common;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import com.mojang.datafixers.util.Unit;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Lifecycle;
import com.mojang.serialization.MapLike;
import com.mojang.serialization.codecs.BaseMapCodec;
import java.util.Map;
import java.util.Objects;
/**
* Key and value decoded independently, unknown set of keys
*/
public class LenientUnboundedMapCodec<K, V> implements BaseMapCodec<K, V>, Codec<Map<K, V>>
{
private final Codec<K> keyCodec;
private final Codec<V> elementCodec;
public LenientUnboundedMapCodec(final Codec<K> keyCodec, final Codec<V> elementCodec) {
this.keyCodec = keyCodec;
this.elementCodec = elementCodec;
}
@Override
public Codec<K> keyCodec() {
return keyCodec;
}
@Override
public Codec<V> elementCodec() {
return elementCodec;
}
@Override // FORGE: Modified from decode() in BaseMapCodec
public <T> DataResult<Map<K, V>> decode(DynamicOps<T> ops, MapLike<T> input)
{
final ImmutableMap.Builder<K, V> read = ImmutableMap.builder();
final ImmutableList.Builder<Pair<T, T>> failed = ImmutableList.builder();
final DataResult<Unit> result = input.entries().reduce(
DataResult.success(Unit.INSTANCE, Lifecycle.stable()),
(r, pair) -> {
final DataResult<K> k = keyCodec().parse(ops, pair.getFirst());
final DataResult<V> v = elementCodec().parse(ops, pair.getSecond());
final DataResult<Pair<K, V>> entry = k.apply2stable(Pair::of, v);
entry.error().ifPresent(e -> failed.add(pair));
entry.result().ifPresent(e -> read.put(e.getFirst(), e.getSecond())); // FORGE: This line moved outside the below apply2stable condition
return r.apply2stable((u, p) -> u, entry);
},
(r1, r2) -> r1.apply2stable((u1, u2) -> u1, r2)
);
final Map<K, V> elements = read.build();
final T errors = ops.createMap(failed.build().stream());
return result.map(unit -> elements).setPartial(elements).mapError(e -> e + " missed input: " + errors);
}
@Override
public <T> DataResult<Pair<Map<K, V>, T>> decode(final DynamicOps<T> ops, final T input) {
return ops.getMap(input).setLifecycle(Lifecycle.stable()).flatMap(map -> decode(ops, map)).map(r -> Pair.of(r, input));
}
@Override
public <T> DataResult<T> encode(final Map<K, V> input, final DynamicOps<T> ops, final T prefix) {
return encode(input, ops, ops.mapBuilder()).build(prefix);
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final LenientUnboundedMapCodec<?, ?> that = (LenientUnboundedMapCodec<?, ?>) o;
return Objects.equals(keyCodec, that.keyCodec) && Objects.equals(elementCodec, that.elementCodec);
}
@Override
public int hashCode() {
return Objects.hash(keyCodec, elementCodec);
}
@Override
public String toString() {
return "LenientUnboundedMapCodec[" + keyCodec + " -> " + elementCodec + ']';
}
}
@@ -136,6 +136,12 @@ public class CompoundIngredient extends Ingredient
}
}
@Override
public boolean hasNoMatchingItems()
{
return getMatchingStacks().length == 0;
}
public static class Serializer implements IIngredientSerializer<CompoundIngredient>
{
public static final Serializer INSTANCE = new Serializer();
@@ -23,9 +23,14 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.data.IDataProvider;
import net.minecraft.resources.FilePack;
import net.minecraft.resources.FolderPack;
import net.minecraft.resources.IResource;
@@ -35,20 +40,72 @@ import net.minecraft.resources.ResourcePackType;
import net.minecraft.resources.SimpleReloadableResourceManager;
import net.minecraft.resources.VanillaPack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.ModelBuilder;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.packs.ModFileResourcePack;
/**
* Enables data providers to check if other data files currently exist. The
* instance provided in the {@link GatherDataEvent} utilizes the standard
* resources (via {@link VanillaPack}), as well as any extra resource packs
* passed in via the {@code --existing} argument.
* resources (via {@link VanillaPack}), forge's resources, as well as any
* extra resource packs passed in via the {@code --existing} argument,
* or mod resources via the {@code --existing-mod} argument.
*/
public class ExistingFileHelper {
public interface IResourceType {
ResourcePackType getPackType();
String getSuffix();
String getPrefix();
}
public static class ResourceType implements IResourceType {
final ResourcePackType packType;
final String suffix, prefix;
public ResourceType(ResourcePackType type, String suffix, String prefix) {
this.packType = type;
this.suffix = suffix;
this.prefix = prefix;
}
@Override
public ResourcePackType getPackType() { return packType; }
@Override
public String getSuffix() { return suffix; }
@Override
public String getPrefix() { return prefix; }
}
private final SimpleReloadableResourceManager clientResources, serverData;
private final boolean enable;
private final Multimap<ResourcePackType, ResourceLocation> generated = HashMultimap.create();
@Deprecated//TODO: Remove in 1.17
public ExistingFileHelper(Collection<Path> existingPacks, boolean enable) {
this(existingPacks, Collections.emptySet(), enable);
}
/**
* Create a new helper. This should probably <em>NOT</em> be used by mods, as
* the instance provided by forge is designed to be a central instance that
* tracks existence of generated data.
* <p>
* Only create a new helper if you intentionally want to ignore the existence of
* other generated files.
*
* @param existingPacks
* @param existingMods
* @param enable
*/
public ExistingFileHelper(Collection<Path> existingPacks, Set<String> existingMods, boolean enable) {
this.clientResources = new SimpleReloadableResourceManager(ResourcePackType.CLIENT_RESOURCES);
this.serverData = new SimpleReloadableResourceManager(ResourcePackType.SERVER_DATA);
this.clientResources.addResourcePack(new VanillaPack("minecraft", "realms"));
@@ -58,12 +115,20 @@ public class ExistingFileHelper {
IResourcePack pack = file.isDirectory() ? new FolderPack(file) : new FilePack(file);
this.clientResources.addResourcePack(pack);
this.serverData.addResourcePack(pack);
};
}
for (String existingMod : existingMods) {
ModFileInfo modFileInfo = ModList.get().getModFileById(existingMod);
if (modFileInfo != null) {
IResourcePack pack = new ModFileResourcePack(modFileInfo.getFile());
this.clientResources.addResourcePack(pack);
this.serverData.addResourcePack(pack);
}
}
this.enable = enable;
}
private IResourceManager getManager(ResourcePackType type) {
return type == ResourcePackType.CLIENT_RESOURCES ? clientResources : serverData;
private IResourceManager getManager(ResourcePackType packType) {
return packType == ResourcePackType.CLIENT_RESOURCES ? clientResources : serverData;
}
private ResourceLocation getLocation(ResourceLocation base, String suffix, String prefix) {
@@ -73,17 +138,34 @@ public class ExistingFileHelper {
/**
* Check if a given resource exists in the known resource packs.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type the type of resources to check
* @param loc the complete location of the resource, e.g.
* {@code "minecraft:textures/block/stone.png"}
* @param packType the type of resources to check
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, ResourcePackType type) {
public boolean exists(ResourceLocation loc, ResourcePackType packType) {
if (!enable) {
return true;
}
return getManager(type).hasResource(loc);
return generated.get(packType).contains(loc) || getManager(packType).hasResource(loc);
}
/**
* Check if a given resource exists in the known resource packs. This is a
* convenience method to avoid repeating type/prefix/suffix and instead use the
* common definitions in {@link ResourceType}, or a custom {@link IResourceType}
* definition.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type a {@link IResourceType} describing how to form the path to the
* resource
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, IResourceType type) {
return exists(getLocation(loc, type.getSuffix(), type.getPrefix()), type.getPackType());
}
/**
@@ -91,25 +173,71 @@ public class ExistingFileHelper {
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type the type of resources to check
* @param packType the type of resources to check
* @param pathSuffix a string to append after the path, e.g. {@code ".json"}
* @param pathPrefix a string to append before the path, before a slash, e.g.
* {@code "models"}
* @return {@code true} if the resource exists in any pack, {@code false}
* otherwise
*/
public boolean exists(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) {
return exists(getLocation(loc, pathSuffix, pathPrefix), type);
public boolean exists(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) {
return exists(getLocation(loc, pathSuffix, pathPrefix), packType);
}
/**
* Track the existence of a generated file. This is a convenience method to
* avoid repeating type/prefix/suffix and instead use the common definitions in
* {@link ResourceType}, or a custom {@link IResourceType} definition.
* <p>
* This should be called by data providers immediately when a new data object is
* created, i.e. not during
* {@link IDataProvider#act(net.minecraft.data.DirectoryCache) act} but instead
* when the "builder" (or whatever intermediate object) is created, such as a
* {@link ModelBuilder}.
* <p>
* This represents a <em>promise</em> to generate the file later, since other
* datagen may rely on this file existing.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param type a {@link IResourceType} describing how to form the path to the
* resource
*/
public void trackGenerated(ResourceLocation loc, IResourceType type) {
this.generated.put(type.getPackType(), getLocation(loc, type.getSuffix(), type.getPrefix()));
}
/**
* Track the existence of a generated file.
* <p>
* This should be called by data providers immediately when a new data object is
* created, i.e. not during
* {@link IDataProvider#act(net.minecraft.data.DirectoryCache) act} but instead
* when the "builder" (or whatever intermediate object) is created, such as a
* {@link ModelBuilder}.
* <p>
* This represents a <em>promise</em> to generate the file later, since other
* datagen may rely on this file existing.
*
* @param loc the base location of the resource, e.g.
* {@code "minecraft:block/stone"}
* @param packType the type of resources to check
* @param pathSuffix a string to append after the path, e.g. {@code ".json"}
* @param pathPrefix a string to append before the path, before a slash, e.g.
* {@code "models"}
*/
public void trackGenerated(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) {
this.generated.put(packType, getLocation(loc, pathSuffix, pathPrefix));
}
@VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type, String pathSuffix, String pathPrefix) throws IOException {
return getResource(getLocation(loc, pathSuffix, pathPrefix), type);
public IResource getResource(ResourceLocation loc, ResourcePackType packType, String pathSuffix, String pathPrefix) throws IOException {
return getResource(getLocation(loc, pathSuffix, pathPrefix), packType);
}
@VisibleForTesting
public IResource getResource(ResourceLocation loc, ResourcePackType type) throws IOException {
return getManager(type).getResource(loc);
public IResource getResource(ResourceLocation loc, ResourcePackType packType) throws IOException {
return getManager(packType).getResource(loc);
}
/**
@@ -140,7 +140,7 @@ public interface IForgeEntity extends ICapabilitySerializable<CompoundNBT>
*/
default boolean canBeRiddenInWater(Entity rider)
{
return this instanceof LivingEntity;
return getEntity().canBeRiddenInWater();
}
/**
@@ -30,10 +30,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import net.minecraft.loot.LootSerializers;
import net.minecraft.loot.conditions.ILootCondition;
import net.minecraft.loot.conditions.LootConditionManager;
import net.minecraft.loot.functions.ILootFunction;
import net.minecraft.loot.functions.LootFunctionManager;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -41,7 +39,6 @@ import org.apache.logging.log4j.Logger;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -56,7 +53,7 @@ import net.minecraftforge.registries.ForgeRegistries;
public class LootModifierManager extends JsonReloadListener {
public static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON_INSTANCE = (new GsonBuilder()).registerTypeHierarchyAdapter(ILootFunction.class, LootFunctionManager.func_237450_a_()).registerTypeHierarchyAdapter(ILootCondition.class, LootConditionManager.func_237474_a_()).create();
private static final Gson GSON_INSTANCE = LootSerializers.func_237387_b_().create();
private Map<ResourceLocation, IGlobalLootModifier> registeredLootModifiers = ImmutableMap.of();
private static final String folder = "loot_modifiers";
@@ -0,0 +1,102 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.common.util;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.util.SoundEvent;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import javax.annotation.Nonnull;
import java.util.function.Supplier;
/**
* A subclass of {@link SoundType} that uses {@link Supplier<SoundEvent>}s.
* <p>
* This class allows mod developers to safely create custom {@code SoundType}s for use in their e.g. {@link Block}.
* <p>
* The problem with using {@code SoundType} directly is it requires {@link SoundEvent} instances directly, because
* {@code SoundType}s are required to be present during {@link Block} creation and registration. However,
* {@code SoundEvent} must also be registered.
* <p>
* A possible solution of initializing {@code SoundEvent}s first would require static initialization of the
* {@code SoundEvent} instances and later registration, which goes against the contract of the registry system and
* prevents the use of {@link DeferredRegister} and {@link RegistryObject}s.
* <p>
* This class offers an alternative and preferable solution, by allowing mods to create {@link SoundType}s using
* {@link Supplier}s of {@link SoundEvent}s instead, which do not require static initialization of {@code SoundEvent}s
* and allow the direct use of {@code RegistryObject}s.
*
* @see SoundType
*/
public class ForgeSoundType extends SoundType
{
private final Supplier<SoundEvent> breakSound;
private final Supplier<SoundEvent> stepSound;
private final Supplier<SoundEvent> placeSound;
private final Supplier<SoundEvent> hitSound;
private final Supplier<SoundEvent> fallSound;
public ForgeSoundType(float volumeIn, float pitchIn, Supplier<SoundEvent> breakSoundIn, Supplier<SoundEvent> stepSoundIn, Supplier<SoundEvent> placeSoundIn, Supplier<SoundEvent> hitSoundIn, Supplier<SoundEvent> fallSoundIn)
{
super(volumeIn, pitchIn, (SoundEvent) null, (SoundEvent) null, (SoundEvent) null, (SoundEvent) null, (SoundEvent) null);
this.breakSound = breakSoundIn;
this.stepSound = stepSoundIn;
this.placeSound = placeSoundIn;
this.hitSound = hitSoundIn;
this.fallSound = fallSoundIn;
}
@Nonnull
@Override
public SoundEvent getBreakSound()
{
return breakSound.get();
}
@Nonnull
@Override
public SoundEvent getStepSound()
{
return stepSound.get();
}
@Nonnull
@Override
public SoundEvent getPlaceSound()
{
return placeSound.get();
}
@Nonnull
@Override
public SoundEvent getHitSound()
{
return hitSound.get();
}
@Nonnull
@Override
public SoundEvent getFallSound()
{
return fallSound.get();
}
}
@@ -318,13 +318,17 @@ public class LazyOptional<T>
* call this, if they are covered with a microblock panel, thus cutting off pipe
* connectivity to this side.
* <p>
* Also should be called for all when a TE is invalidated, or a world/chunk
* unloads, or a entity dies, etc... This allows modders to keep a cache of
* capability objects instead of re-checking them every tick.
* Also should be called for all when a TE is invalidated (for example, when
* the TE is removed or unloaded), or a world/chunk unloads, or a entity dies,
* etc... This allows modders to keep a cache of capability objects instead of
* re-checking them every tick.
*/
public void invalidate()
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
if (this.isValid)
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
}
}
}
@@ -0,0 +1,121 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.common.world;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StringUtils;
import net.minecraft.util.Util;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.DimensionType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistryEntry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ForgeWorldType extends ForgeRegistryEntry<ForgeWorldType>
{
private static final Logger LOGGER = LogManager.getLogger();
public static ForgeWorldType getDefaultWorldType()
{
String defaultWorldType = ForgeConfig.COMMON.defaultWorldType.get();
if (StringUtils.isNullOrEmpty(defaultWorldType) || "default".equals(defaultWorldType))
return null; // use vanilla
ForgeWorldType def = ForgeRegistries.WORLD_TYPES.getValue(new ResourceLocation(defaultWorldType));
if (def == null)
{
LOGGER.error("The defaultWorldType '{}' specified in the forge config has not been registered. The vanilla default generator will be used.", defaultWorldType);
}
return def;
}
private final IChunkGeneratorFactory factory;
public ForgeWorldType(IChunkGeneratorFactory factory)
{
this.factory = factory;
}
public ForgeWorldType(IBasicChunkGeneratorFactory factory)
{
this.factory = factory;
}
public String getTranslationKey()
{
return Util.makeTranslationKey("generator", getRegistryName());
}
public ITextComponent getDisplayName()
{
return new TranslationTextComponent(getTranslationKey());
}
/**
* Called from both the dedicated server and the world creation screen in the client.
* to construct the DimensionGEneratorSettings:
* @return The constructed chunk generator.
*/
public ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings)
{
return this.factory.createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed, generatorSettings);
}
public DimensionGeneratorSettings createSettings(DynamicRegistries dynamicRegistries, long seed, boolean generateStructures, boolean generateLoot, String generatorSettings)
{
return this.factory.createSettings(dynamicRegistries, seed, generateStructures, generateLoot, generatorSettings);
}
public interface IChunkGeneratorFactory
{
ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings);
default DimensionGeneratorSettings createSettings(DynamicRegistries dynamicRegistries, long seed, boolean generateStructures, boolean bonusChest, String generatorSettings) {
Registry<Biome> biomeRegistry = dynamicRegistries.getRegistry(Registry.BIOME_KEY);
Registry<DimensionType> dimensionTypeRegistry = dynamicRegistries.getRegistry(Registry.DIMENSION_TYPE_KEY);
Registry<DimensionSettings> dimensionSettingsRegistry = dynamicRegistries.getRegistry(Registry.NOISE_SETTINGS_KEY);
return new DimensionGeneratorSettings(seed, generateStructures, bonusChest,
DimensionGeneratorSettings.func_242749_a(dimensionTypeRegistry,
DimensionType.getDefaultSimpleRegistry(dimensionTypeRegistry, biomeRegistry, dimensionSettingsRegistry, seed),
createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed, generatorSettings)));
}
}
public interface IBasicChunkGeneratorFactory extends IChunkGeneratorFactory
{
ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed);
default ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings)
{
return createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed);
}
}
}
@@ -21,6 +21,7 @@ package net.minecraftforge.event;
import java.io.File;
import java.util.*;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -36,6 +37,7 @@ import net.minecraft.command.Commands;
import net.minecraft.entity.Entity;
import net.minecraft.entity.Pose;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.LivingEntity;
@@ -103,6 +105,7 @@ import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
import net.minecraftforge.event.entity.ProjectileImpactEvent;
import net.minecraftforge.event.entity.item.ItemExpireEvent;
import net.minecraftforge.event.entity.living.AnimalTameEvent;
import net.minecraftforge.event.entity.living.LivingConversionEvent;
import net.minecraftforge.event.entity.living.LivingDestroyBlockEvent;
import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent;
import net.minecraftforge.event.entity.living.LivingExperienceDropEvent;
@@ -748,4 +751,14 @@ public class ForgeEventFactory
MinecraftForge.EVENT_BUS.post(evt);
return evt;
}
public static boolean canLivingConvert(LivingEntity entity, EntityType<? extends LivingEntity> outcome, Consumer<Integer> timer)
{
return !MinecraftForge.EVENT_BUS.post(new LivingConversionEvent.Pre(entity, outcome, timer));
}
public static void onLivingConvert(LivingEntity entity, LivingEntity outcome)
{
MinecraftForge.EVENT_BUS.post(new LivingConversionEvent.Post(entity, outcome));
}
}
@@ -0,0 +1,143 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.event;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
import net.minecraftforge.eventbus.api.Event;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import com.google.common.collect.Multimap;
import javax.annotation.Nullable;
import java.util.Collection;
/**
* This event is fired when the attributes for an ItemStack are being calculated.
* Attributes are calculated on the server when equipping and unequipping an item to add and remove attributes respectively, both must be consistent.
* Attributes are calculated on the client when rendering an item's tooltip to show relevant attributes.
* <br>
* Note that this event is fired regardless of if the stack has NBT overriding attributes or not. If your attribute should be
* ignored when attributes are overridden, you can check for the presence of the {@code AttributeModifiers} tag.
* <br>
* This event is fired on the {@link net.minecraftforge.common.MinecraftForge#EVENT_BUS}.
*/
public class ItemAttributeModifierEvent extends Event
{
private final ItemStack stack;
private final EquipmentSlotType slotType;
private final Multimap<Attribute, AttributeModifier> originalModifiers;
private Multimap<Attribute, AttributeModifier> unmodifiableModifiers;
@Nullable
private Multimap<Attribute, AttributeModifier> modifiableModifiers;
public ItemAttributeModifierEvent(ItemStack stack, EquipmentSlotType slotType, Multimap<Attribute, AttributeModifier> modifiers)
{
this.stack = stack;
this.slotType = slotType;
this.unmodifiableModifiers = this.originalModifiers = modifiers;
}
/**
* Returns an unmodifiable view of the attribute multimap. Use other methods from this event to modify the attributes map.
* Note that adding attributes based on existing attributes may lead to inconsistent results between the tooltip (client)
* and the actual attributes (server) if the listener order is different. Using {@link #getOriginalModifiers()} instead will give more consistent results.
*/
public Multimap<Attribute, AttributeModifier> getModifiers()
{
return this.unmodifiableModifiers;
}
/**
* Returns the attribute map before any changes from other event listeners was made.
*/
public Multimap<Attribute, AttributeModifier> getOriginalModifiers()
{
return this.originalModifiers;
}
/**
* Gets a modifiable map instance, creating it if the current map is currently unmodifiable
*/
private Multimap<Attribute, AttributeModifier> getModifiableMap()
{
if (this.modifiableModifiers == null)
{
this.modifiableModifiers = HashMultimap.create(this.originalModifiers);
this.unmodifiableModifiers = Multimaps.unmodifiableMultimap(this.modifiableModifiers);
}
return this.modifiableModifiers;
}
/**
* Adds a new attribute modifier to the given stack.
* Modifier must have a consistent UUID for consistency between equipping and unequipping items.
* Modifier name should clearly identify the mod that added the modifier.
* @param attribute Attribute
* @param modifier Modifier instance.
* @return True if the attribute was added, false if it was already present
*/
public boolean addModifier(Attribute attribute, AttributeModifier modifier)
{
return getModifiableMap().put(attribute, modifier);
}
/**
* Removes a single modifier for the given attribute
* @param attribute Attribute
* @param modifier Modifier instance
* @return True if an attribute was removed, false if no change
*/
public boolean removeModifier(Attribute attribute, AttributeModifier modifier)
{
return getModifiableMap().remove(attribute, modifier);
}
/**
* Removes all modifiers for the given attribute
* @param attribute Attribute
* @return Collection of removed modifiers
*/
public Collection<AttributeModifier> removeAttribute(Attribute attribute)
{
return getModifiableMap().removeAll(attribute);
}
/**
* Removes all modifiers for all attributes
*/
public void clearModifiers()
{
getModifiableMap().clear();
}
/** Gets the slot containing this stack */
public EquipmentSlotType getSlotType()
{
return this.slotType;
}
/** Gets the item stack instance */
public ItemStack getItemStack()
{
return this.stack;
}
}
@@ -122,9 +122,20 @@ public class RegistryEvent<T extends IForgeRegistryEntry<T>> extends GenericEven
return this.registry;
}
/*
* This used to be fired on the Mod specific bus, and we could tell which mod was asking for mappings.
* It no longer is, so this method is useless and just returns getAllMappings.
* TODO: Ask cpw how if he wants to re-enable the ModBus rethrow.
*/
@Deprecated
public ImmutableList<Mapping<T>> getMappings()
{
return ImmutableList.copyOf(this.mappings.stream().filter(e -> e.key.getNamespace().equals(this.activeMod.getModId())).collect(Collectors.toList()));
return this.activeMod == null ? getAllMappings() : getMappings(this.activeMod.getModId());
}
public ImmutableList<Mapping<T>> getMappings(String modid)
{
return ImmutableList.copyOf(this.mappings.stream().filter(e -> e.key.getNamespace().equals(modid)).collect(Collectors.toList()));
}
public ImmutableList<Mapping<T>> getAllMappings()
@@ -0,0 +1,108 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.event.entity.living;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraftforge.eventbus.api.Cancelable;
import java.util.function.Consumer;
public class LivingConversionEvent extends LivingEvent
{
public LivingConversionEvent(LivingEntity entity)
{
super(entity);
}
/**
* LivingConversionEvent.Pre is triggered when an entity is trying
* to replace itself with another entity
*
* This event may trigger every tick even if it was cancelled last tick
* for entities like Zombies and Hoglins. To prevent it, the conversion
* timer needs to be changed or reset
*
* This event is {@link Cancelable}
* If cancelled, the replacement will not occur
*/
@Cancelable
public static class Pre extends LivingConversionEvent
{
private final EntityType<? extends LivingEntity> outcome;
private final Consumer<Integer> timer;
public Pre(LivingEntity entity, EntityType<? extends LivingEntity> outcome, Consumer<Integer> timer)
{
super(entity);
this.outcome = outcome;
this.timer = timer;
}
/**
* Gets the entity type of the new entity this living entity is
* converting to
* @return the entity type of the new entity
*/
public EntityType<? extends LivingEntity> getOutcome()
{
return outcome;
}
/**
* Sets the conversion timer, by changing this it prevents the
* event being triggered every tick
* Do note the timer of some of the entities are increments, but
* some of them are decrements
* Not every conversion is applicable for this
* @param ticks timer ticks
*/
public void setConversionTimer(int ticks)
{
timer.accept(ticks);
}
}
/**
* LivingConversionEvent.Post is triggered when an entity is replacing
* itself with another entity.
* The old living entity is likely to be removed right after this event.
*/
public static class Post extends LivingConversionEvent
{
private final LivingEntity outcome;
public Post(LivingEntity entity, LivingEntity outcome)
{
super(entity);
this.outcome = outcome;
}
/**
* Gets the finalized new entity (with all data like potion
* effect and equipments set)
* @return the finalized new entity
*/
public LivingEntity getOutcome()
{
return outcome;
}
}
}
@@ -20,13 +20,16 @@
package net.minecraftforge.event.entity.player;
import com.google.common.base.Preconditions;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
@@ -129,27 +132,35 @@ public class PlayerInteractEvent extends PlayerEvent
}
/**
* This event is fired on both sides whenever the player right clicks while targeting a block.
* This event controls which of {@link net.minecraft.block.Block#onBlockActivated} and/or {@link net.minecraft.item.Item#onItemUse}
* will be called after {@link net.minecraft.item.Item#onItemUseFirst} is called.
* Canceling the event will cause none of the above three to be called
*
* Let result be a return value of the above three methods, or {@link #cancellationResult} if the event is cancelled.
* If we are on the client and result is not {@link EnumActionResult#SUCCESS}, the client will then try {@link RightClickItem}.
*
* There are various results to this event, see the getters below.
* Note that handling things differently on the client vs server may cause desynchronizations!
* This event is fired on both sides whenever the player right clicks while targeting a block. <br>
* This event controls which of {@link Item#onItemUseFirst}, {@link Block#onBlockActivated}, and {@link Item#onItemUse}
* will be called. <br>
* Canceling the event will cause none of the above three to be called. <br>
* <br>
* Let result be the first non-pass return value of the above three methods, or pass, if they all pass. <br>
* Or {@link #cancellationResult} if the event is cancelled. <br>
* If result equals {@link ActionResultType#PASS}, we proceed to {@link RightClickItem}. <br>
* <br>
* There are various results to this event, see the getters below. <br>
* Note that handling things differently on the client vs server may cause desynchronizations!
*/
@Cancelable
public static class RightClickBlock extends PlayerInteractEvent
{
private Result useBlock = DEFAULT;
private Result useItem = DEFAULT;
private BlockRayTraceResult hitVec;
@Deprecated //Use RayTraceResult version. TODO: Remove 1.17
public RightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, Direction face) {
super(player, hand, pos, face);
}
public RightClickBlock(PlayerEntity player, Hand hand, BlockPos pos, BlockRayTraceResult hitVec) {
super(player, hand, pos, hitVec.getFace());
this.hitVec = hitVec;
}
/**
* @return If {@link net.minecraft.block.Block#onBlockActivated} should be called
*/
@@ -167,9 +178,18 @@ public class PlayerInteractEvent extends PlayerEvent
}
/**
* DENY: Block will never be used.
* DEFAULT: Default behaviour (sneak will not use block, unless all items return true in {@link net.minecraft.item.Item#doesSneakBypassUse}).
* ALLOW: Block will always be used, regardless of sneaking and doesSneakBypassUse.
* @return The ray trace result targeting the block.
*/
public BlockRayTraceResult getHitVec()
{
return hitVec;
}
/**
* DENY: {@link Block#onBlockActivated} will never be called. <br>
* DEFAULT: {@link Block#onBlockActivated} will be called if {@link Item#onItemUseFirst} passes. <br>
* Note that default activation can be blocked if the user is sneaking and holding an item that does not return true to {@link Item#doesSneakBypassUse}. <br>
* ALLOW: {@link Block#onBlockActivated} will always be called, unless {@link Item#onItemUseFirst} does not pass. <br>
*/
public void setUseBlock(Result triggerBlock)
{
@@ -177,9 +197,9 @@ public class PlayerInteractEvent extends PlayerEvent
}
/**
* DENY: The item will never be used.
* DEFAULT: The item will be used if the block fails.
* ALLOW: The item will always be used.
* DENY: Neither {@link Item#onItemUse} or {@link Item#onItemUseFirst} will be called. <br>
* DEFAULT: {@link Item#onItemUseFirst} will always be called, and {@link Item#onItemUse} will be called if the block passes. <br>
* ALLOW: {@link Item#onItemUseFirst} will always be called, and {@link Item#onItemUse} will be called if the block passes, regardless of cooldowns or emptiness. <br>
*/
public void setUseItem(Result triggerItem)
{
@@ -19,6 +19,7 @@
package net.minecraftforge.fml;
import java.util.Collections;
import net.minecraft.util.registry.Bootstrap;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
@@ -39,14 +40,23 @@ public class DatagenModLoader {
return runningDataGen;
}
public static void begin(final Set<String> mods, final Path path, final java.util.Collection<Path> inputs, Collection<Path> existingPacks, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat) {
@Deprecated //TODO: Remove in 1.17
public static void begin(final Set<String> mods, final Path path, final Collection<Path> inputs, Collection<Path> existingPacks, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat) {
begin(mods, path, inputs, existingPacks, Collections.emptySet(), serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
}
public static void begin(final Set<String> mods, final Path path, final Collection<Path> inputs, Collection<Path> existingPacks, Set<String> existingMods, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat) {
if (mods.contains("minecraft") && mods.size() == 1) return;
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
runningDataGen = true;
Bootstrap.register();
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
existingFileHelper = new ExistingFileHelper(existingPacks, structureValidator);
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ()->{});
if (!mods.contains("forge")) {
//If we aren't generating data for forge, automatically add forge as an existing so mods can access forge's data
existingMods.add("forge");
}
existingFileHelper = new ExistingFileHelper(existingPacks, existingMods, structureValidator);
ModLoader.get().runEventGenerator(mc->new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p->dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper));
dataGeneratorConfig.runAll();
}
@@ -268,7 +268,7 @@ public class ModLoader
{
final Map<String, IModInfo> modInfoMap = modFile.getModFileInfo().getMods().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
LOGGER.debug(LOADING, "ModContainer is {}", ModContainer.class.getClassLoader());
LOGGER.trace(LOADING, "ModContainer is {}", ModContainer.class.getClassLoader());
final List<ModContainer> containers = modFile.getScanResult().getTargets()
.entrySet()
.stream()
@@ -59,7 +59,7 @@ public class FMLModContainer extends ModContainer
try
{
modClass = Class.forName(className, true, modClassLoader);
LOGGER.debug(LOADING,"Loaded modclass {} with {}", modClass.getName(), modClass.getClassLoader());
LOGGER.trace(LOADING,"Loaded modclass {} with {}", modClass.getName(), modClass.getClassLoader());
}
catch (Throwable e)
{
@@ -77,9 +77,9 @@ public class FMLModContainer extends ModContainer
{
try
{
LOGGER.debug(LOADING, "Loading mod instance {} of type {}", getModId(), modClass.getName());
LOGGER.trace(LOADING, "Loading mod instance {} of type {}", getModId(), modClass.getName());
this.modInstance = modClass.newInstance();
LOGGER.debug(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.getName());
LOGGER.trace(LOADING, "Loaded mod instance {} of type {}", getModId(), modClass.getName());
}
catch (Throwable e)
{
@@ -87,9 +87,9 @@ public class FMLModContainer extends ModContainer
throw new ModLoadingException(modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, modClass);
}
try {
LOGGER.debug(LOADING, "Injecting Automatic event subscribers for {}", getModId());
LOGGER.trace(LOADING, "Injecting Automatic event subscribers for {}", getModId());
AutomaticEventSubscriber.inject(this, this.scanResults, this.modClass.getClassLoader());
LOGGER.debug(LOADING, "Completed Automatic event subscribers for {}", getModId());
LOGGER.trace(LOADING, "Completed Automatic event subscribers for {}", getModId());
} catch (Throwable e) {
LOGGER.error(LOADING,"Failed to register automatic subscribers. ModID: {}, class {}", getModId(), modClass.getName(), e);
throw new ModLoadingException(modInfo, ModLoadingStage.CONSTRUCT, "fml.modloading.failedtoloadmod", e, modClass);
@@ -116,9 +116,9 @@ public class FMLModContainer extends ModContainer
@Override
protected <T extends Event & IModBusEvent> void acceptEvent(final T e) {
try {
LOGGER.debug(LOADING, "Firing event for modid {} : {}", this.getModId(), e);
LOGGER.trace(LOADING, "Firing event for modid {} : {}", this.getModId(), e);
this.eventBus.post(e);
LOGGER.debug(LOADING, "Fired event for modid {} : {}", this.getModId(), e);
LOGGER.trace(LOADING, "Fired event for modid {} : {}", this.getModId(), e);
} catch (Throwable t) {
LOGGER.error(LOADING,"Caught exception during event {} dispatch for modid {}", e, this.getModId(), t);
throw new ModLoadingException(modInfo, modLoadingStage, "fml.modloading.errorduringevent", t);
@@ -264,7 +264,7 @@ public class FMLHandshakeMessages
}
public static S2CConfigData decode(final PacketBuffer buffer) {
return new S2CConfigData(buffer.readString(128), buffer.readByteArray());
return new S2CConfigData(buffer.readString(32767), buffer.readByteArray());
}
public String getFileName() {
@@ -82,19 +82,19 @@ public class ModFileResourcePack extends ResourcePack
{
try
{
Path root = modFile.getLocator().findPath(modFile, type.getDirectoryName()).toAbsolutePath();
Path root = modFile.getLocator().findPath(modFile, type.getDirectoryName(), resourceNamespace).toAbsolutePath();
Path inputPath = root.getFileSystem().getPath(pathIn);
return Files.walk(root).
map(path -> root.relativize(path.toAbsolutePath())).
filter(path -> path.getNameCount() > 1 && path.getNameCount() - 1 <= maxDepth). // Make sure the depth is within bounds, ignoring domain
filter(path -> path.getNameCount() <= maxDepth). // Make sure the depth is within bounds
filter(path -> !path.toString().endsWith(".mcmeta")). // Ignore .mcmeta files
filter(path -> path.subpath(1, path.getNameCount()).startsWith(inputPath)). // Make sure the target path is inside this one (again ignoring domain)
filter(path -> path.startsWith(inputPath)). // Make sure the target path is inside this one
filter(path -> filter.test(path.getFileName().toString())). // Test the file name against the predicate
// Finally we need to form the RL, so use the first name as the domain, and the rest as the path
// It is VERY IMPORTANT that we do not rely on Path.toString as this is inconsistent between operating systems
// Join the path names ourselves to force forward slashes
map(path -> new ResourceLocation(path.getName(0).toString(), Joiner.on('/').join(path.subpath(1,Math.min(maxDepth, path.getNameCount()))))).
map(path -> new ResourceLocation(resourceNamespace, Joiner.on('/').join(path))).
collect(Collectors.toList());
}
catch (IOException e)
@@ -199,7 +199,7 @@ public class ServerLifecycleHooks
IModInfo mod = e.getKey().getModInfos().get(0);
if (Objects.equals(mod.getModId(), "minecraft")) continue; // skip the minecraft "mod"
final String name = "mod:" + mod.getModId();
final ResourcePackInfo packInfo = ResourcePackInfo.createResourcePack(name, true, e::getValue, factory, ResourcePackInfo.Priority.BOTTOM, IPackNameDecorator.PLAIN);
final ResourcePackInfo packInfo = ResourcePackInfo.createResourcePack(name, false, e::getValue, factory, ResourcePackInfo.Priority.BOTTOM, IPackNameDecorator.PLAIN);
if (packInfo == null) {
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
@@ -20,6 +20,7 @@
package net.minecraftforge.network;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -84,7 +85,7 @@ public class VanillaConnectionNetworkFilter extends MessageToMessageEncoder<IPac
@Nonnull
private static SEntityPropertiesPacket filterEntityProperties(SEntityPropertiesPacket msg)
{
SEntityPropertiesPacket newPacket = new SEntityPropertiesPacket();
SEntityPropertiesPacket newPacket = new SEntityPropertiesPacket(msg.getEntityId(), Collections.emptyList());
msg.getSnapshots().stream()
.filter(snapshot -> {
ResourceLocation key = ForgeRegistries.ATTRIBUTES.getKey(snapshot.func_240834_a_());
@@ -57,6 +57,7 @@ import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder;
import net.minecraft.world.gen.treedecorator.TreeDecoratorType;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.fml.common.registry.GameRegistry;
/**
@@ -111,6 +112,7 @@ public class ForgeRegistries
// Custom forge registries
public static final IForgeRegistry<DataSerializerEntry> DATA_SERIALIZERS = RegistryManager.ACTIVE.getRegistry(DataSerializerEntry.class);
public static final IForgeRegistry<GlobalLootModifierSerializer<?>> LOOT_MODIFIER_SERIALIZERS = RegistryManager.ACTIVE.getRegistry(GlobalLootModifierSerializer.class);
public static final IForgeRegistry<ForgeWorldType> WORLD_TYPES = RegistryManager.ACTIVE.getRegistry(ForgeWorldType.class);
public static final class Keys {
//Vanilla
@@ -152,6 +154,7 @@ public class ForgeRegistries
//Forge
public static final RegistryKey<Registry<DataSerializerEntry>> DATA_SERIALIZERS = key("data_serializers");
public static final RegistryKey<Registry<GlobalLootModifierSerializer<?>>> LOOT_MODIFIER_SERIALIZERS = key("forge:loot_modifier_serializers");
public static final RegistryKey<Registry<ForgeWorldType>> WORLD_TYPES = key("forge:world_types");
private static <T> RegistryKey<Registry<T>> key(String name)
{
@@ -51,10 +51,7 @@ import net.minecraft.state.StateContainer;
import net.minecraft.stats.StatType;
import net.minecraft.tags.TagRegistryManager;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.ObjectIntIdentityMap;
import net.minecraft.util.RegistryKey;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.*;
import net.minecraft.util.registry.DefaultedRegistry;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.SimpleRegistry;
@@ -74,6 +71,7 @@ import net.minecraft.world.gen.treedecorator.TreeDecoratorType;
import net.minecraftforge.common.ForgeTagHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.fml.ModContainer;
@@ -114,6 +112,7 @@ public class GameData
private static final ResourceLocation BLOCK_TO_ITEM = new ResourceLocation("minecraft:blocktoitemmap");
private static final ResourceLocation BLOCKSTATE_TO_ID = new ResourceLocation("minecraft:blockstatetoid");
private static final ResourceLocation BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE = new ResourceLocation("minecraft:blockstatetopointofinteresttype");
private static final ResourceLocation SERIALIZER_TO_ENTRY = new ResourceLocation("forge:serializer_to_entry");
private static final ResourceLocation STRUCTURES = new ResourceLocation("minecraft:structures");
@@ -156,7 +155,7 @@ public class GameData
// Villagers
makeRegistry(VILLAGER_PROFESSIONS, VillagerProfession.class, "none").create();
makeRegistry(POI_TYPES, PointOfInterestType.class, "unemployed").disableSync().create();
makeRegistry(POI_TYPES, PointOfInterestType.class, "unemployed").addCallback(PointOfInterestTypeCallbacks.INSTANCE).disableSync().create();
makeRegistry(MEMORY_MODULE_TYPES, c(MemoryModuleType.class), "dummy").disableSync().create();
makeRegistry(SENSOR_TYPES, c(SensorType.class), "dummy").disableSaving().disableSync().create();
makeRegistry(SCHEDULES, Schedule.class).disableSaving().disableSync().create();
@@ -180,6 +179,7 @@ public class GameData
// Custom forge registries
makeRegistry(DATA_SERIALIZERS, DataSerializerEntry.class, 256 /*vanilla space*/, MAX_VARINT).disableSaving().disableOverrides().addCallback(SerializerCallbacks.INSTANCE).create();
makeRegistry(LOOT_MODIFIER_SERIALIZERS, c(GlobalLootModifierSerializer.class)).disableSaving().disableSync().create();
makeRegistry(WORLD_TYPES, ForgeWorldType.class).disableSaving().disableSync().create();
}
@SuppressWarnings("unchecked") //Ugly hack to let us pass in a typed Class object. Remove when we remove type specific references.
private static <T> Class<T> c(Class<?> cls) { return (Class<T>)cls; }
@@ -228,6 +228,12 @@ public class GameData
{
return RegistryManager.ACTIVE.getRegistry(Block.class).getSlaveMap(BLOCKSTATE_TO_ID, ObjectIntIdentityMap.class);
}
@SuppressWarnings("unchecked")
public static Map<BlockState, PointOfInterestType> getBlockStatePointOfInterestTypeMap()
{
return RegistryManager.ACTIVE.getRegistry(PointOfInterestType.class).getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class);
}
@SuppressWarnings("unchecked")
public static Map<IDataSerializer<?>, DataSerializerEntry> getSerializerMap()
@@ -613,6 +619,41 @@ public class GameData
}
}
private static class PointOfInterestTypeCallbacks implements IForgeRegistry.AddCallback<PointOfInterestType> , IForgeRegistry.ClearCallback<PointOfInterestType>, IForgeRegistry.CreateCallback<PointOfInterestType>
{
static final PointOfInterestTypeCallbacks INSTANCE = new PointOfInterestTypeCallbacks();
@Override
public void onAdd(IForgeRegistryInternal<PointOfInterestType> owner, RegistryManager stage, int id, PointOfInterestType obj, @Nullable PointOfInterestType oldObj)
{
Map<BlockState, PointOfInterestType> map = owner.getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class);
if (oldObj != null)
{
oldObj.getBlockStates().forEach(map::remove);
}
obj.getBlockStates().forEach((state) ->
{
PointOfInterestType oldType = map.put(state, obj);
if (oldType != null)
{
throw new IllegalStateException(String.format("Point of interest types %s and %s both list %s in their blockstates, this is not allowed. Blockstates can only have one point of interest type each.", oldType, obj, state));
}
});
}
@Override
public void onClear(IForgeRegistryInternal<PointOfInterestType> owner, RegistryManager stage)
{
owner.getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class).clear();
}
@Override
public void onCreate(IForgeRegistryInternal<PointOfInterestType> owner, RegistryManager stage)
{
owner.setSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, new HashMap<>());
}
}
private static <T extends IForgeRegistryEntry<T>> void loadRegistry(final ResourceLocation registryName, final RegistryManager from, final RegistryManager to, final Class<T> regType, boolean freeze)
{
ForgeRegistry<T> fromRegistry = from.getRegistry(registryName);
@@ -144,6 +144,7 @@ public net.minecraft.client.gui.ScreenManager func_216911_a(Lnet/minecraft/inven
public net.minecraft.client.gui.ScreenManager$IScreenFactory
protected net.minecraft.client.gui.overlay.DebugOverlayGui field_211537_g # rayTraceBlock
protected net.minecraft.client.gui.overlay.DebugOverlayGui field_211538_h # rayTraceFluid
public net.minecraft.client.gui.screen.WorldOptionsScreen func_239043_a_(Lnet/minecraft/world/gen/settings/DimensionGeneratorSettings;)V # func_239043_a_
protected net.minecraft.client.gui.widget.list.AbstractList$AbstractListEntry field_230666_a_ # list
public net.minecraft.client.particle.ParticleManager func_199283_a(Lnet/minecraft/particles/ParticleType;Lnet/minecraft/client/particle/IParticleFactory;)V # registerFactory
public net.minecraft.client.particle.ParticleManager func_215234_a(Lnet/minecraft/particles/ParticleType;Lnet/minecraft/client/particle/ParticleManager$IParticleMetaFactory;)V # registerFactory
+1
View File
@@ -77,6 +77,7 @@ net/minecraft/nbt/CompressedStreamTools func_74797_a(Ljava/io/File;)Lnet/minecra
net/minecraft/nbt/CompressedStreamTools func_74795_b(Lnet/minecraft/nbt/CompoundNBT;Ljava/io/File;)V # write
net/minecraft/network/play/server/SCommandListPacket func_197693_a()Lcom/mojang/brigadier/tree/RootCommandNode; # getRoot
net/minecraft/network/play/server/SEntityPropertiesPacket func_149441_d()Ljava/util/List; # getSnapshots
net/minecraft/network/play/server/SEntityPropertiesPacket func_149442_c()I # getEntityId
net/minecraft/potion/Effect func_220303_e()Lnet/minecraft/potion/EffectType; # getEffectType
net/minecraft/potion/Effect func_111186_k()Ljava/util/Map; # getAttributeModifierMap
net/minecraft/potion/Effect func_188408_i()Z # isBeneficial
@@ -0,0 +1,65 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraftforge.common.util.ForgeSoundType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
@Mod(CustomSoundTypeTest.MODID)
public class CustomSoundTypeTest
{
static final String MODID = "custom_sound_type_test";
private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID);
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
private static final DeferredRegister<SoundEvent> SOUND_EVENTS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, MODID);
private static final RegistryObject<SoundEvent> TEST_STEP_EVENT = SOUND_EVENTS.register("test_step",
() -> new SoundEvent(new ResourceLocation(MODID, "block.sound_type_test.step")));
private static final SoundType TEST_SOUND_TYPE = new ForgeSoundType(1.0F, 1.0F, TEST_STEP_EVENT, TEST_STEP_EVENT, TEST_STEP_EVENT, TEST_STEP_EVENT, TEST_STEP_EVENT);
private static final RegistryObject<Block> TEST_STEP_BLOCK = BLOCKS.register("test_block",
() -> new Block(AbstractBlock.Properties.create(Material.WOOD).sound(TEST_SOUND_TYPE)));
private static final RegistryObject<Item> TEST_STEP_BLOCK_ITEM = ITEMS.register("test_block",
() -> new BlockItem(TEST_STEP_BLOCK.get(), new Item.Properties().group(ItemGroup.MISC)));
public CustomSoundTypeTest()
{
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
BLOCKS.register(modEventBus);
ITEMS.register(modEventBus);
SOUND_EVENTS.register(modEventBus);
}
}
@@ -41,6 +41,7 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.ObjectArrays;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
@@ -214,6 +215,7 @@ public class DataGeneratorTest
getOrCreateBuilder(BlockTags.makeWrapperTag(new ResourceLocation(MODID, "test").toString()))
.addItemEntry(Blocks.DIAMOND_BLOCK)
.addTag(BlockTags.STONE_BRICKS)
.addTag(net.minecraftforge.common.Tags.Blocks.COBBLESTONE)
.addOptional(new ResourceLocation("chisel", "marble/raw"))
.addOptionalTag(new ResourceLocation("forge", "storage_blocks/ruby"));
@@ -437,7 +439,7 @@ public class DataGeneratorTest
ModelFile barrel = models().cubeBottomTop("barrel", mcLoc("block/barrel_side"), mcLoc("block/barrel_bottom"), mcLoc("block/barrel_top"));
ModelFile barrelOpen = models().cubeBottomTop("barrel_open", mcLoc("block/barrel_side"), mcLoc("block/barrel_bottom"), mcLoc("block/barrel_top_open"));
directionalBlock(Blocks.BARREL, state -> state.get(BarrelBlock.PROPERTY_OPEN) ? barrelOpen : barrel); // Testing custom state interpreter
logBlock((RotatedPillarBlock) Blocks.ACACIA_LOG);
stairsBlock((StairsBlock) Blocks.ACACIA_STAIRS, "acacia", mcLoc("block/acacia_planks"));
@@ -456,6 +458,9 @@ public class DataGeneratorTest
simpleBlock(Blocks.TORCH, models().torch("torch", mcLoc("block/torch")));
horizontalBlock(Blocks.WALL_TORCH, models().torchWall("wall_torch", mcLoc("block/torch")), 90);
models().cubeAll("test_block", mcLoc("block/stone"));
itemModels().withExistingParent("test_block", modLoc("block/test_block"));
}
// Testing the outputs
@@ -464,6 +469,7 @@ public class DataGeneratorTest
// Vanilla doesn't generate these models yet, so they have minor discrepancies that are hard to test
// This list should probably be cleared and investigated after each major version update
private static final Set<ResourceLocation> IGNORED_MODELS = ImmutableSet.of(new ResourceLocation(MODID, "block/cube"));
private static final Set<ResourceLocation> CUSTOM_MODELS = ImmutableSet.of(new ResourceLocation(MODID, "block/test_block"));
private List<String> errors = new ArrayList<>();
@@ -471,7 +477,7 @@ public class DataGeneratorTest
public void act(DirectoryCache cache) throws IOException
{
super.act(cache);
this.errors.addAll(testModelResults(models().generatedModels, models().existingFileHelper, IGNORED_MODELS));
this.errors.addAll(testModelResults(models().generatedModels, models().existingFileHelper, Sets.union(IGNORED_MODELS, CUSTOM_MODELS)));
this.registeredBlocks.forEach((block, state) -> {
if (IGNORED_BLOCKS.contains(block)) return;
JsonObject generated = state.toJson();
@@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.client.rendering;
import net.minecraft.client.Minecraft;
@@ -0,0 +1,53 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.entity.living;
import net.minecraft.entity.merchant.villager.VillagerEntity;
import net.minecraft.entity.monster.piglin.PiglinEntity;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.LivingConversionEvent;
import net.minecraftforge.fml.common.Mod;
@Mod("living_conversion_event_test")
public class LivingConversionEventTest
{
public LivingConversionEventTest()
{
MinecraftForge.EVENT_BUS.addListener(this::canLivingConversion);
MinecraftForge.EVENT_BUS.addListener(this::onLivingConversion);
}
public void canLivingConversion(LivingConversionEvent.Pre event)
{
if (event.getEntityLiving() instanceof PiglinEntity)
{
event.setCanceled(true);
event.setConversionTimer(0);
}
}
public void onLivingConversion(LivingConversionEvent.Post event)
{
if (event.getEntityLiving() instanceof VillagerEntity)
event.getEntityLiving().addPotionEffect(new EffectInstance(Effects.LUCK, 20));
}
}
@@ -0,0 +1,55 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.item;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.AttributeModifier.Operation;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraftforge.event.ItemAttributeModifierEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod(ItemAttributeModifierTest.MOD_ID)
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, modid = ItemAttributeModifierTest.MOD_ID)
public class ItemAttributeModifierTest
{
public static final String MOD_ID = "item_modifier_test";
public static final boolean ENABLED = true;
private static final AttributeModifier MODIFIER = new AttributeModifier(MOD_ID, 10f, Operation.ADDITION);
@SubscribeEvent
public static void onItemAttribute(ItemAttributeModifierEvent event)
{
if (ENABLED && event.getSlotType() == EquipmentSlotType.MAINHAND)
{
final Item item = event.getItemStack().getItem();
if (item == Items.APPLE)
{
event.addModifier(Attributes.ARMOR, MODIFIER);
}
else if (item == Items.GOLDEN_SWORD)
{
event.clearModifiers();
}
}
}
}
@@ -0,0 +1,82 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.world;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.client.ForgeWorldTypeScreens;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ObjectHolder;
@Mod("forge_world_type_test")
public class ForgeWorldTypeTest
{
@ObjectHolder("forge_world_type_test:test_world_type")
public static ForgeWorldType testWorldType;
public ForgeWorldTypeTest()
{
FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(ForgeWorldType.class, this::registerWorldTypes);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::registerWorldTypeScreenFactories);
}
private void registerWorldTypes(RegistryEvent.Register<ForgeWorldType> event)
{
event.getRegistry().registerAll(
new ForgeWorldType(DimensionGeneratorSettings::func_242750_a).setRegistryName("test_world_type")
);
event.getRegistry().registerAll(
new ForgeWorldType(this::createChunkGenerator).setRegistryName("test_world_type2")
);
}
private ChunkGenerator createChunkGenerator(Registry<Biome> biomes, Registry<DimensionSettings> dimensionSettings, long seed, String settings)
{
return DimensionGeneratorSettings.func_242750_a(biomes, dimensionSettings, seed);
}
private void registerWorldTypeScreenFactories(FMLClientSetupEvent event)
{
ForgeWorldTypeScreens.registerFactory(testWorldType, (returnTo, dimensionGeneratorSettings) -> new Screen(testWorldType.getDisplayName())
{
@Override
protected void init()
{
super.init();
addButton(new Button(0, 0, 120, 20, new StringTextComponent("close"), btn -> {
Minecraft.getInstance().displayGuiScreen(returnTo);
}));
}
});
}
}
+10 -2
View File
@@ -3,7 +3,7 @@ loaderVersion="[28,)"
license="LGPL v2.1"
[[mods]]
modId="containertypetest"
modId="containertypetest"
[[mods]]
modId="potion_event_test"
[[mods]]
@@ -88,6 +88,8 @@ license="LGPL v2.1"
modId="custom_tag_types_test"
[[mods]]
modId="biome_loading_event_test"
[[mods]]
modId="living_conversion_event_test"
[[mods]]
modId="player_game_mode_event_test"
[[mods]]
@@ -95,4 +97,10 @@ license="LGPL v2.1"
[[mods]]
modId="forge_codecs_test"
[[mods]]
modId="render_local_player_test"
modId="render_local_player_test"
[[mods]]
modId="forge_world_type_test"
[[mods]]
modId="custom_sound_type_test"
[[mods]]
modId="item_modifier_test"
@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "custom_sound_type_test:block/test_block"
}
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "minecraft:block/cartography_table_side3"
}
}
@@ -0,0 +1,3 @@
{
"parent": "custom_sound_type_test:block/test_block"
}
@@ -0,0 +1,8 @@
{
"block.sound_type_test.step": {
"subtitle": "Test step",
"sounds": [
"minecraft:mob/horse/zombie/hit1"
]
}
}